Python data structure and algorithm 18 unordered list implementation

Source: Internet
Author: User

Unordered list implementation: Linked List

To implement Unordered Lists, we must first implement a structure called a "linked list. As mentioned above, we keep the relative position between the list elements. Of course, in the case of continuous storage, you do not need to save the relative location (such as an array), but if the data is stored in a random way like Figure 1, in this case, you need to configure additional information for each element to specify its location for the next element (Figure 2), so that the relative location of each element, it is achieved through the link from one element to another.



Figure 1 unfixed physical location of Elements


Figure 2 maintain relative relationship through clear link

Note that the position of the first element of the linked list must be specified separately. Once the first element is known, it can tell us the position of the first element, and so on. External reference of a linked list usually points to its header. Similarly, the last element must indicate that "the following element is missing ".

Node

Node is the basic module for implementing the linked list. Each Node consists of at least two important parts. First, the data that contains the node itself is called a "data domain ". Second, it includes "references" to the next node ". The following code is the code of the Node class. To construct a node, initialize the data of the node. 3. assign values to the node and return a Node object. However, figure 4 shows a common node. The node class also includes methods for accessing and modifying data domains and pointer domains.

Listing 1

classNode:
    def__init__(self,initdata):
        self.data= initdata
        self.next=None
 
    defgetData(self):
        returnself.data
 
    defgetNext(self):
        returnself.next
 
    defsetData(self,newdata):
        self.data= newdata
 
    defsetNext(self,newnext):
        self.next= newnext

Use the above class to create a Node object

>>> temp= Node(93)
>>> temp.getData()
93

The special reference value None is very important in node classes and linked lists. The reference to None indicates that there is no next node. In the constructor, a node is created and its "Reference" is assigned to None. Because sometimes the last node is called a "grounding point", we simply use an electrical grounding symbol to represent None. It is a good idea to assign a value of None to initialize a "Reference.


Figure 3 node objects include data domains and references to the next node



Figure 4 typical node Representation

Unordered list class

As mentioned above, the unordered list is implemented through a set of nodes. Each node includes references to the next node. As long as we find the first node and reference it, we can go through each data item. In this way, the unordered list class must save the reference to the first node. The following is a constructor. Note that each list object contains a reference to the "List Header" (head.

Listing 2

classUnorderedList:
 
    def__init__(self):
        self.head=None

Initialize the list when it is created. There are no data items here. The value assignment statement

>>> mylist= UnorderedList()

The created linked list is shown in Figure 5. We have discussed the special reference None of the node class, which indicates that the head does not reference any node. Finally, as shown in Example 6 of the linked list given above, head points to the first node, and the first node includes the first data item. Similarly, the first node includes references to the next node. It is particularly important that the Linked List class does not include any Node object. On the contrary, it only includes references to the first element in the list.

Figure 5 empty list




Figure 6 integer linked list

The isEmpty method in the following code segment is used to check whether the head reference is None. The return value expression self. head = None in the method is true only when there are no nodes in the linked list. Since a new linked list is empty, the constructor and the isEmpty function must be consistent. This also shows the advantage of using None to represent "end. In python, None can be compared with any reference. If two variables reference the same object, they are equal. This method will be frequently used in the future.

Listing 3

defisEmpty(self):
    returnself.head==None
In this case, how can we add new data items to the list? You need to implement a new add method. But before that, we need to deal with an important problem: where should the linked list put new data items? Since the list is unordered, the location of the new data item has little to do with the original element, and the new data item can be placed in any location, we can put the new item in the easiest location to process.

Recall that the linked list structure only provides one inbound, that is, the head of the list. All other nodes must be accessed one by one through reference, the easiest place to handle is the head position or the start position. In other words, a new data item is always the first item in the list, and the original data items are listed after it by reference.

Figure 6 shows the linked list formed several times through the add method.

>>> mylist.add(31)
>>> mylist.add(77)
>>> mylist.add(17)
>>> mylist.add(93)
>>> mylist.add(26)
>>> mylist.add(54)

Note that 31 is the first data to be added, and eventually it is the last data in the linked list. Similarly, 54 is the last added, and it becomes the data of the first node of the linked list.

The Add method is implemented in code 4. Each data item is inside the Node object. Create a new node in row 2nd and save the data in its data domain. Then you need to connect the node with the existing structure. Figure 7 shows the two steps. Step 1: change the reference of the new node to the reference of the original first node. In this way, other nodes in the list establish a link with the new node, as long as you change the head to a reference to the new node. The value assignment statement in row 4th sets the head of the list.

The order of the above two steps is particularly important. What will happen if the reverse order of 3 and 4 is used? If the head reference is modified first, as shown in figure 8, because the head is the only external reference entry to the list nodes, once it is lost, all the original nodes will disappear from the memory.

Listing 4

Code 4

defadd(self,item):
    temp = Node(item)
    temp.setNext(self.head)
    self.head= temp

Figure 7 Add a new node in two steps


Figure 8 result of inverted two-step sequence

The following methods, such as size, search, and remove, are based on a technology of linked list, that is, traversal implementation. Traversal refers to the process of accessing each node systematically. To this end, we start from the external reference of the first node. Every time a node is accessed, We can traverse it by moving it to the next node.

In order to implement the size method, we also need to record the nodes we pass through in a traversal table. Code 5 shows the counter code. The external reference is called current, and the head of the linked list is initialized in the second row. At the beginning, the counter variable is 0 because it has never experienced any node, and the traversal is implemented in line 4-6. As long as the current reference does not see None, it points current to the next node (row 6th ).

Finally, count is returned after iteration. Figure 9 shows the processing process.

Listing 5

defsize(self):
    current =self.head
    count =0
    while current !=None:
        count = count +1
        current = current.getNext()
 
    return count

Figure 9 traversal from start to end

You also need to use the traversal technology to search for a value in the unordered list. when accessing each node, you must compare whether its data is consistent with the data to be searched. In this way, you may not need to traverse all the nodes to find them. If you find them, you do not need to continue searching. In fact, if we get to the end of the list, we cannot find it.

List6 shows the implementation of the search method. Like in the size method, traversal starts from the head (two rows), and a found variable is used to record whether it has been found. Because the initial status is not found, the found Initialization is False. Row 4th uses two conditions to determine whether to continue traversing. Row 1 is followed by node 2, which is not found yet. Row 5 checks whether the value of the current node matches. If yes, if the found value is True, the traversal ends.

Listing 6

defsearch(self,item):
    current =self.head
    found =False
    while current !=Noneandnot found:
        if current.getData()== item:
            found =True
        else:
            current = current.getNext()
 
    return found

Try to find 17

>>> mylist.search(17)
True

17. In the list, the traversal process only needs to be directed to the node containing 17. At this point, found is set to True. The while condition is not True. When the loop is exited, The found value is returned. 10

Keys + keys/dPDo6zO0sPHvdDL/keys + s/keys + keys/keys + rXEv9jWxrHkwb + hozwvcD4KPHA + keys/LHsNK7sr21vc/keys + keys/ export/yzazSu7bUz/OjrL7Nz/Oz3/O2ua3R/KGjzbwxMs/export + export "0" cellspacing = "0" cellpadding = "0">
defremove(self,item):
    current =self.head
    previous =None
    found =False
    whilenot found:
        if current.getData()== item:
            found =True
        else:
            previous = current
            current = current.getNext()
 
    if previous ==None:
        self.head= current.getNext()
    else:
        previous.setNext(current.getNext())

Figure 11 previous and current Initialization


Figure 12 Movement history of previou and current


Once the search process ends, the deletion process starts. Figure 13 shows the link to be modified. However, there is a special case for processing. If the data to be deleted is on the first node, current is the first node, and previous is still None, as we mentioned earlier, the node where prevous is located is to modify its next reference. However, in this special case, it is not the previous next but the head of the list. (Figure 14)


Figure 13 deleting a node in the middle



Figure 14 remove the first node


For 12 rows, let's check whether there are any special cases mentioned above. If previous has not moved forward, it will still be None, but found is True. In this case (13 rows), the head is changed to the next node pointing to current, in effect, the first node is deleted. However, if previous is not None, the node to be deleted is somewhere in the middle. In this case, the next of the node where previous is located must be modified, and 15 rows use the setNext method to delete the node. Note that in both cases, the modified references point to current. getNext ().

But are these two conditions applicable to the last node of the node to be deleted? For exercises.

The following are all the code and test code of the unordered list.

Class Node:

Def _ init _ (self, initdata ):

Self. data = initdata

Self. next = None

Def getData (self ):

Return self. data

Def getNext (self ):

Return self. next

Def setData (self, newdata ):

Self. data = newdata

Def setNext (self, newnext ):

Self. next = newnext

ClassUnorderedList:

Def _ init _ (self ):

Self. head = None

Def isEmpty (self ):

Return self. head = None

Def add (self, item ):

Temp = Node (item)

Temp. setNext (self. head)

Self. head = temp

Def size (self ):

Current = self. head

Count = 0

While current! = None:

Count = count + 1

Current = current. getNext ()

Return count

Def search (self, item ):

Current = self. head

Found = False

While current! = None and not found:

If current. getData () = item:

Found = True

Else:

Current = current. getNext ()

Return found

Def remove (self, item ):

Current = self. head

Previous = None

Found = False

While not found:

If current. getData () = item:

Found = True

Else:

Previous = current

Current = current. getNext ()

If previous = None:

Self. head = current. getNext ()

Else:

Previous. setNext (current. getNext ())

Mylist = UnorderedList ()

Mylist. add (31)

Mylist. add (77)

Mylist. add (17)

Mylist. add (93)

Mylist. add (26)

Mylist. add (54)

Print (mylist. size ())

Print (mylist. search (93 ))

Print (mylist. search (100 ))

Mylist. add (100)

Print (mylist. search (100 ))

Print (mylist. size ())

Mylist. remove (54)

Print (mylist. size ())

Mylist. remove (93)

Print (mylist. size ())

Mylist. remove (31)

Print (mylist. size ())

Print (mylist. search (93 ))


For other methods, append, insert, index, and pop are left as exercises. Note that you should consider whether each method applies to the first element or other situations. In addition, insert, index, and pop require the index name of the linked list. We agree that the index name is an integer starting from 0.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.