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.
原因就是头指针中保存的首地址被赋予了一个新的值。