Python list operation (realization)

Operation Python list

In the interview Python development, we often encounter questions about the operation of the list. One linked list data structure as a very classic unordered list structure, but also a development engineer must master. In this article, I will some common structural features of the operating data for the list itself, as well as give you a list of explain in simple terms, I hope the readers of this article can master the operation of the list.

1. What is the list?

Simply put, the list is an unordered list. You can put inside a linked list data as a random arrangement, and there is no fixed order between the elements. So, since it is out of order, so we can not operate like a target list as easily come and go with the index positioning and operating elements inside, as shown below:

imgfigure 1

So this situation, how can we find various elements inside of it?

In fact, in each of the elements of the list which is actually called the object of Node node, Node will each hold two messages, one is the value of value of this node, the other is the next node of the node corresponding reference next. In this way, in fact, between the node and the node to form a chain structure, like a chain, inter-related, which is the origin of the name list. With such a chain structure, just give us a starting point, we will be able to find a node to all nodes along the starting point of a node, this list is the core of the whole data structure.

2. How to implement a linked list?

As already mentioned, the key list structure is Node node object, so you want to achieve before the list, we need to define Node node object. Data stored in each node in the value of the current node, and a reference to next current node to the next node, so we could have defined a Node object:

class Node:

    def __init__(self, data):
        self.data = data    # 保存当前节点的值
        self.next = None    # 保存当前节点中下一个节点的引用

To be able to get and set information Node inside, we need to define several methods, as follows:

def __init__(self, data):
        self.data = data
        self.next = None
    
    # 获取node里面的数据
    def getData(self):
        return self.data
    
    # 获取下一个节点的引用
    def getNext(self):
        return self.next
    
    # 设置node里面的数据
    def setData(self, newdata):
        self.data = newdata
    
    # 设置下一个节点的引用
    def setNext(self, newnext):
        self.next = newnext

These methods for accessing data inside Node convenient to use in the list structure inside.

After a good Node object definitions, then we can begin to define the list of objects. We are here talking about a one-way linked list, so the English became Single Link List. When you define a list, most notably head (head) defined the list, as we said before, we just found the head of the list, will be able to find all other node along the head. Therefore, initial definition list is very simple, as long as we attribute to define a head, as follows:

class MySingleLinkList():
    

    def __init__(self):

        # 定义链表的头结点

        self.head = None

Here we should note that the list object itself does not contain any nodes Node objects, on the contrary, it contains only a single link structure of the first node reference (self.head), in fact, it will always point to the head of the list the first node. If you head to None, in fact, it means that this is an empty list. Objects and Node object list LinkList independent by definition, does not contain each other. The basic idea is very important, as long as we remember this basic principle, then we can begin the list followed by other methods of implementation.

imgfigure 2

In general, the basic operation of a linked list should contain mainly in the following:

  • It determines whether the list is empty isEmpty ()
def isEmpty(self):
    '''
    判断head指向的节点是否为None,如果head指向None,说明该链表为空
    '''
    return self.head == None
  • Get the length of the list size ()

The key length of the list is to get to traverse the linked list, and count the number of nodes. Traversing the list will be frequently used to the basic operation of the list operations, such as query list node, delete operation will involve traversing the list. We have said before, when traversing the list, we must first find the head node of the list, from the head of the list began to find next of each node, until the final one node to the next None, it means to traverse completed.

def size(self):
    current = self.head  # 将链表的头节点赋值给current,代表当前节点
    count = 0
    while current != None:
        count += 1
        current = current.getNext()  # 计数后,不断把下一个节点的引用赋值给当前节点,这样我们就能不断向后面的节点移动
    return count
  • Increases toward a linked list node add ()

Add a node to the list, we have to consider two questions. The first question is, where are the new node is added? You can think about, is an unordered list structure, in fact, where the new node is added to the list itself does not matter. But adding to a different position in the list, for our code difficulty of the operation is different. Because the list structure we defined earlier always just keep a reference to the first node, so from this point of view, the easiest way is to add a new node to the head of the list, so that the new node to become the first list node and the previous node in turn backward. The second problem is that, when adding a new node, to require action? In fact, to add a new node requires two steps. First, the need to assign to the next node before the head of a new node, the new node is next, and then assign the new node to the head node, it becomes the new head (Figure 3).

imgimage 3

def add(self, val):
    temp = Node(val)
    temp.next = self.head   # 将原来的开始节点设置为新开始节点的下一节点
    self.head = temp        # 将新加入节点设置为现在的第一个节点

必须要注意temp.next = self.head和self.head=temp这两个语句的先后顺序,如果把self.head=temp写在前面,则会使得head原来指向的下一个节点的信息全部丢失,这并不是我们想要的结果(如图4所示)。

img图4

  • 查找指定节点是否在链表中 search()

要实现查找算法,必然也是要遍历链表的,我们可以设置一个布尔变量作为是否查找到目标元素的标志,然后通过遍历链表中的每个元素,判断该元素的值是否等于要查找的值,如果是,则将布尔值设置为True,最后返回该布尔值即可。代码如下:

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
  • 移除指定节点 remove()

移除指定节点也是在链表中一个常见的操作,在移除指定节点时,除了要先遍历链表找到指定元素外,还需要对这个即将被移除的节点做一些处理,以确保剩下的节点能够正常工作。在我们找到要被移除的节点时,按照之前写过的遍历方法我们知道,current应该是指向要被移除的节点。可问题是怎么才能移除掉该节点呢?为了能够移除节点,我们需要修改上一个节点中的链接,以便使其直接指向当前将被移除节点的下一个节点,使没有任何其他节点指向这个被移除的节点,以达到移除节点的目的。但这里有个问题,就是当我们循环链表到当前节点时,没法回退回去操作当前节点的前一个节点。所以,为了解决这个问题,在遍历链表时,除了需要记录当前指向的节点current外,还需要设置一个变量来记录当前节点的上一个节点previous,每次循环时,如果当前节点不是要被移除的节点,那么就将当前节点的值赋值给previous,而将下一个节点的引用赋值给当前节点,以达到向前移动的目的。同时,在找到了将被移除的节点后,我们会把found设置为true,停止遍历。

另外,在删除节点时,可能会有三种情况:

(1) is removed node is the beginning node in the linked list, then the previous value must be None, we only need to assign current.next to head to.
(2) the removed node is the last node in the list.
(3) node is removed is the common node (ie not the first nor the last node).
Wherein (2) (3) do not require special handling cases, arranged directly next previous to the current to next.

def remove(self, item):
    current = self.head
    previous = None
    found = False
    
    # 判断指定值是否存在于链表中 
    if not self.search(item):
        return
        
    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())
  • Get the value of all nodes in the list of the getAllData ()

Gets the value of all the nodes in the linked list to help us keep track of exactly what the value of the list. Since the list is not as common as the list can be printed out directly to see, so in general we need to traverse the list by means of the value of each node in the linked list taken out into a list, and then print the list, to obtain the list the purpose of all node values.

def getAllData(self):    # 得到链表中所有的值
    data = []
    current = self.head
    while current:
        data.append(current.getData())
        current = current.getNext()
    return data

These are our usual method of operation and the corresponding code is implemented in the list, then we can try to manipulate what we write and test these methods right.

linkList = MySingleLinkList()
for i in range(10, 50, 5):
    linkList.add(i)
print(linkList.size())  # output: 8
print(linkList.getAllData()) # output: [45, 40, 35, 30, 25, 20, 15, 10]

linkList.remove(25)
print(linkList.getAllData()) # output: [45, 40, 35, 30, 20, 15, 10]

linkList.search(25)  # output: False
linkList.isEmpyt()   # output: False

These are defined python algorithm we often encounter in the interview and in the list of common operations

Guess you like

Origin www.cnblogs.com/TMesh-python/p/11731484.html