python实现双向链表
双向链表:
在单链表的节点中只有一个指向其后继节点的指针域next,因此若已知某节点的指针为p,其后继节点的指针为p->next,而找其前驱节点则只能从该链表的头指针开始顺着各节点的next域进行,也就是说找后记的时间性能是O(1),找前驱的节点为O(n),如果也希望找到前驱的时间性能是O(1),则可以通过付出空间为代价,每一个节点再加一个指向前驱的指针域。因此这就是双向链表
双向链表实现的功能
1、判断是否为空
def is_empty(self):
"""判断是否为空"""
return self.__head is None
2、求长度
def length(self):
"""链表长度"""
#cur游标,用来移动遍历节点
cur=self.__head
#count记录数量
count=0
while cur!=None:
count+=1
cur=cur.next
return count
3、头插入
def add(self,data):
"""链表头部添加元素,头插法"""
#第一种方法
node=Node(data)
node.next=self.__head
self.__head=node
node.next.prev=node
#第二种方法
#node.next=self.__head
#self.__head.prev=node
#self.__head=node
分析:
对于头插入来说,我们首先需要对传入进来的数据进行封装成Node型,变成一个有三个域的节点,我们以第一种方法为例,请看如图
为了不改变链表原有的状态,我们需要对刚转换过来的node进行操作,那么首先需要将node的next域指向头节点所指向的节点(node.next=self.__head),然后把头指针指向node(self.__head=node),为了让其变为双向链表我们需要100的前驱指向node,( node.next.prev=node),那么100的前驱就是node.next.prev。
4、尾插入
def append(self,data):
"""链表尾部添加元素,尾插入"""
node=Node(data)
if self.is_empty():
self.__head=node
else:
cur=self.__head
while cur.next !=None:
cur=cur.next
cur.next=node
node.prev=cur
尾插入与头插入类似,但是这里要考虑链表为空的情况如果链表为空,我们直接将node插入到头节点上去,一般情况下,我们需要找到最后一个节点,所以我们就用到了cur来标记,直到cur为空就是最后一个节点,
5、索引插入
def insert(self,pos,data):
"""指定位置添加元素"""
if pos<=0:
self.add(data)
elif pos>(self.length()-1):
self.append(data)
else:
cur=self.__head
count=0
while count<pos:
count+=1
cur=cur.next
#当循环退出后,cur指向pos
#第一种写法
node=Node(data)
node.next=cur
node.prev=cur.prev
cur.prev=node
cur.prev.next=node
cur.prev=node
#第二种写法
#node.next=cur
#ndoe.prev=cur.prev
#cur.pre=node
#node.prev.next=node
对于索引插入来说,有三种情况:
(1)当插入的位置小于或者等于0相当于头插入。
(2)当插入的位置大于或者等于双向链表长度-1相当于尾部插入。
(3)一般的插入。
那对于一般插入来说,我们需要找到需要插入的地方,那么就需要用到一个count用来计数,知道count等于pos时就找到了插入的地方,在双向链表里不同与单链表的地方在于我们只需要用到一个cur标记就可以了,而对于单向链表还需要用到一个pre来标记前一个节点。
下面是对于循环单链表的插入的
6、删除指定元素
def remove(self,data):
"""删除节点"""
cur=self.__head
while cur!=None:
if cur==data:
#先判断此节点是否是头节点
#头节点
if cur==self.__head:
self.__head=cur.next
if cur.next:
#判断链表是否只有一个节点
cur.next.prev=None
else:
cur.prev.next=cur.next
#处理最后一个节点考虑的情况
if cur.next:
cur.next.prev=cur.prev
break
else:
pre=cur
cur=cur.next
这里笔者不在一一分析
7、查询元素
def search(self,data):
"""查找节点是否存在"""
cur=self.__head
while cur!=None:
if cur.data==data:
return True
else:
cur=cur.next
return False
8、遍历双向链表
def travel(self):
"""遍历整个链表"""
cur=self.__head
while cur!=None:
print(cur.elem,end=" ")
cur=cur.next
print(" ")
在双向链表与单链表当中 1 ,2,8,三个操作完全相同,可以使用面向对象技术通过继承来实现,这里未用到。
9、主函数:
if __name__=="__main__":
ll=DoubleLink()
print(ll.is_empty())
print(ll.length())
ll.append(1)
print(ll.is_empty())
print(ll.length())
ll.append(2)
ll.add(8)
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
#8 1 2 3 4 5 6
ll.insert(-1,9)#9 8 1 23456
ll.travel()
ll.insert(3,200)#9 8 1 100 2 3456
ll.travel()
ll.insert(10,200)#9 8 1 100 23456
ll.travel()
ll.remove(9)
ll.travel()
ll.remove(200)
ll.travel()
print(ll.is_empty())
print(ll.length())
实现的结果: