Python-链接表的深刻认识与总结

1.逆序构造链表

图片讲解:

逆序构造

逆序构造的时候就像头插法一样,将当前的node作为下一个的node.next.
#定义节点
class Node(object):
    def __init__(self,item,Next=None):
        self.item=item
        self.next=Next

head=None
for i in range (5):
    head=Node(i,head)
print(head.__dict__)
{'item': 4, 'next': <__main__.Node object at 0x00000261774FBD68>}
print(head.next.__dict__)
{'item': 3, 'next': <__main__.Node object at 0x00000261774FBBA8>}

2.顺序构造链表以及增、删、改、查、插(头插,尾插法)、遍历

顺序构造

顺序构造的时候将,下一个节点作为头结点的Next ,即node.next=Node.

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Node(object):
    def __init__(self,item,Next=None):
        self.item=item
        self.next=Next
print(head.__dict__,head.next.__dict__)
{'item': 2, 'next': <__main__.Node object at 0x00000261775DE2B0>} {'item': 1, 'next': None}
class Node_forward(object):
    def __init__(self,item):
        self.item=item
        self.next=None
class SingleListNode(object):
    def __init__(self):
        #初始化头结点
        print("初始化头结点")
        self.head=None
    #创建链表
    def append(self,item):
        node=Node_forward(item)
        if self.head==None:
            self.head=node
        else:
            cur=self.head
            while(cur.next!=None):
                cur=cur.next
            cur.next=node
    #《遍历链表》
    def travel(self):
        cur=self.head
        while (cur!=None):
            #cur 没有next属性,所以判断条件肯定不能是cur.next
            print(cur.item,end=' ')
            cur=cur.next
    #《计算链表长度》
    def length(self):
        cur=self.head
        count=0
        while(cur!=None):
            count+=1
            cur=cur.next
        return count
    #《插入指定的位置》->注意如果是在第一个节点前面插入我们叫头插法,也就是pos<0
    def insert(self,pos,item):
        item=Node_forward(item)
        if pos>=0:#在第pos个后面insert item
            cur=self.head
            count=0
            while(count<pos):
                count+=1
                cur=cur.next
            item.next=cur.next
            cur.next=item
        else:
            cur=self.head
            item.next=cur
            self.head=item#这里不能是cur.next=item,见文章最后的解释
#             cur=item
#             cur.next=item
    #《删除指定的位置或者元素》
    def delete(self,pos=None,item=None):
        #可以传pos也可以传item
        cur=self.head
        count=0
        if pos==0:#删除的是第一个节点的情况
            self.head=cur.next  #测试删除是否也是这样子的,删除第0个节点不行
#             cur=cur.next
        else:
            while(count<pos-1):
                count+=1
                cur=cur.next
            print("cur:",cur.__dict__)
            cur.next=cur.next.next
    #《销毁链表》
    def distroy(self):
        self.head=None
#         cur=self.head
#         cur=None  #cur与self.head指向的不是一个吗?
    #《查找指定元素》或者《查找某一个元素在什么位置》
    def search(self,pos=None,item=None):        
        count=0
        if pos!=None:
            cur=self.head #
            #打开通过查找位置获取元素的功能
            while(count<pos):
                count+=1
                cur=cur.next
            print("在pos={}的位置的值为{}".format(pos,cur.item))
        if item!=None:
            #打开查找元素的位置
            count=0
            cur=self.head#cur需要重置,因为可能会同时查找pos->item, item->pos
            while(cur.item!=item):
                count+=1
                cur=cur.next
            print("item={}的位置在{}".format(item,count))
            
        
        
        
        
sll=SingleListNode()
初始化头结点
for i in range (4):
    sll.append(i)
sll.travel()
0 1 2 3 
sll.distroy()
sll.travel()
sll.delete(0)
sll.travel()
0 1 2 3 
sll.search(3,2)
在pos=3的位置的值为3
item=2的位置在2
sll.insert(0,5)
sll.travel()
0 5 1 2 3 
sll.distroy()
#头插法
sll.insert(-1,5)
sll.travel()
0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 


---------------------------------------------------------------------------

KeyboardInterrupt                         Traceback (most recent call last)

<ipython-input-470-9179d83aa49c> in <module>()
----> 1 sll.travel()


<ipython-input-450-cc612d094f80> in travel(self)
     19         while (cur!=None):
     20             #cur 没有next属性,所以判断条件肯定不能是cur.next
---> 21             print(cur.item,end=' ')
     22             cur=cur.next
     23     #《计算链表长度》


~\AppData\Roaming\Python\Python36\site-packages\ipykernel\iostream.py in write(self, string)
    374             is_child = (not self._is_master_process())
    375             # only touch the buffer in the IO thread to avoid races
--> 376             self.pub_thread.schedule(lambda : self._buffer.write(string))
    377             if is_child:
    378                 # newlines imply flush in subprocesses


~\AppData\Roaming\Python\Python36\site-packages\ipykernel\iostream.py in schedule(self, f)
    201             self._events.append(f)
    202             # wake event thread (message content is ignored)
--> 203             self._event_pipe.send(b'')
    204         else:
    205             f()


~\AppData\Roaming\Python\Python36\site-packages\zmq\sugar\socket.py in send(self, data, flags, copy, track, routing_id, group)
    389                                  copy_threshold=self.copy_threshold)
    390             data.group = group
--> 391         return super(Socket, self).send(data, flags=flags, copy=copy, track=track)
    392 
    393     def send_multipart(self, msg_parts, flags=0, copy=True, track=False, **kwargs):


zmq\backend\cython\socket.pyx in zmq.backend.cython.socket.Socket.send()


zmq\backend\cython\socket.pyx in zmq.backend.cython.socket.Socket.send()


zmq\backend\cython\socket.pyx in zmq.backend.cython.socket._send_copy()


~\AppData\Roaming\Python\Python36\site-packages\zmq\backend\cython\checkrc.pxd in zmq.backend.cython.checkrc._check_rc()


KeyboardInterrupt: 
sll.append(3)
sll.travel()
2 3 
sll.length()
3
sll.append(4)
sll.travel()
1 2 3 4 
sll.length()
4

3. 探究 cur=self.head时,cur=None 不能销毁(distroy)链表

class Test_Node(object):
    def __init__(self,item):
        self.item=item
        self.next=None
        
node=Test_Node(1)
print(node.__dict__)
{'item': 1, 'next': None}
class SingelListNode(object):
    def __init__(self):
        self.__head=None
    def append_create(self,elem):
        elem=Test_Node(elem)
        if self.__head==None:
            self.__head=elem
        else:
            cur=self.__head
            while(cur.next!=None):
                cur=cur.next
            cur.next=elem
    def travel(self):
        cur=self.__head
        while(cur!=None):
            print(cur.item,end="->")
            cur=cur.next
        print("NULL")
    def destroy(self):
#         self.__head=None
        cur=self.__head
        cur=None
        
sl=SingelListNode()
sl.append_create(1)
sl.travel()
1->NULL
sl.append_create(2)
sl.travel()
1->2->NULL
sl.destroy()
sl.travel()
1->2->NULL

在distroy链表的时候用 "cur=self.__head;cur=None"跟python中 b=2;a=b;a=3;那么print(b)等于2是一个道理,不像列表:

#list1=[1,2,3];list2=list1;list2=[2,3,4],那么list1也会被改变

list1=[1,2,3]
list2=list1
list2=[2,3,4]#改变List指针指向,list1不会受干扰
print(list1)
[1, 2, 3]
list1=[1,2,3]
list2=list1
list2[0]=5 #修改list2中的值,则会改变list1中的值,因为list2的指向地址没有改变
print(list1)
[5, 2, 3]

所以在:

def destroy(self):
     // self.__head=None
     cur=self.__head
     cur=None

cur只是重新指向了一个空的地址,但是没有影响travel()从self.__head这个地址的起始点开始遍历

就像insert中:

else:
 cur=self.head
 item.next=cur
 self.head=item#这里不能是cur.next=item,否则链表不改变,难道是因为self.head一直保持是None?
 cur=item

cur=item只是让cur指向了item,
但是self.__head的首地址还是没有变的,首地址没有变,头插法就没有用。

4. 那么cur有什么用?

cur其实可以用来修改元素的,下面的代码:

def append_create(self,elem):
        elem=Test_Node(elem)
        if self.__head==None:
            self.__head=elem
        else:
            cur=self.__head
            while(cur.next!=None):
                cur=cur.next
            cur.next=elem
上述创建列表的时候,cur=self.__head,也就是说 cur被赋予了两种属性:item和 next,所以在cur.next这行代码中,他可以去修改self.__head中的值,这就像上面举的例子:
list1=[1,2,3]
list2=list1
list2[0]=5 #修改list2中的值,则会改变list1中的值,因为list2的指向地址没有改变
print(list1)
[5, 2, 3]
cur就像list2一样,他被赋予了list1是个列表的属性,如果是下面这行代码:
list1=[1,2,3]
list2=list1
list1=[8,8,8]
print(list2)
[1, 2, 3]

list2是继续指向list1之前的地址的,不管list1怎么变,因为list2是指向这个地址的

回到上面说的:也就是说 cur被赋予了两种属性:item和 next,所以在cur.next这行代码中,他可以去修改self.head中的值,
如果之后销毁链表的话 也就是self.head=None,那么 cur肯定也是None,因为他们指向的是一个地址

5.一不小心成了循环链表

    def insert(self,pos,item):
        item=Node_forward(item)
        if pos>=0:#在第pos个后面insert item
            cur=self.head
            count=0
            while(count<pos):
                count+=1
                cur=cur.next
            item.next=cur.next
            cur.next=item
        else:
            cur=self.head
            item.next=cur
            #self.head=item#这里不能是cur.next=item,见文章最后的解释
#             cur=item
            cur.next=item

在上面的插入代码中,注意最后的cur.next=item,这个时候就成了一个循环链表输出 50505050505 。
但是你将self.head=item 放开的话,头节点起始地址就发生变化了,因为self.__head 是全局变量的效应,在travel()的时候,起始是从item开始的,而不是
从之前的0开始的,亦形成了一个循环链表 但是输出的是:0505050505.
原因就是头指针中保存的首地址被赋予了一个新的值。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值