前言
本篇章主要介绍线性表中的双链表,并用Python实现其基本操作。
1. 双链表
单链表结点中只有一个指向其后继的指针,使得单链表只能从头结点依次顺序地向后遍历。比如在插入或删除操作时,需要访问某个结点的前驱结点,就只能从头开始遍历。为了克服单链表的这种缺点,就有了带两个指针的单链表,即双链表,prior指针指向其前驱结点,next指针指向其后继结点。
双链表的结点定义如下:
class DoubleLinkNode(object):
def __init__(self, data=None, prior=None, next=None):
self.data = data
self.prior = prior
self.next = next
双链表在单链表的基础上加了一个指向其前驱的指针,因此双链表中的按值查找和按位查找的操作与单链表相同,但是在插入和删除操作上,双链表可以很方便地找到其前驱结点,因此,插入和删除的操作时间复杂度都为
,但是我在下面的代码中传入的不是结点,而是整个链表按值或位插入或删除,所以复杂度仍为
,重在算法的思想嘛,哈哈哈哈哈!
2. 基本操作
双链表的插入和删除操作相比单链表,多了一个前驱指针的操作,注意不要乱了执行的顺序。
操作名称 | 操作说明 |
---|---|
InsertInHead(val_list) | 头插法创建双链表 |
InsertInTail(val_list) | 尾插法创建双链表 |
IsEmpty() | 判断双链表是否为空 |
LengthList() | 返回双链表的长度 |
TraverseList() | 打印出双链表里的数据元素 |
InsertInPosition(pos, data) | 在指定位置插入 |
SearchWithPosition(pos) | 按位置查找结点 |
SearchWithVal(data) | 按值查找结点 |
RemoveWithPosition(pos) | 移除指定位置的结点 |
RemoveWithVal(data) | 移除指定值的结点 |
3. 代码实现
class DoubleLinkList(object):
def __init__(self):
self.__head = DoubleLinkNode(None)
def InsertInHead(self, val_list):
"""
头插法
:param val_list:
:return:
"""
prehead = self.__head
for val in val_list:
new_node = DoubleLinkNode(val)
if self.IsEmpty():
prehead.next = new_node
new_node.prior = prehead
else:
new_node.next = prehead.next
prehead.next.prior = new_node
prehead.next = new_node
new_node.prior = prehead
def InsertInTail(self, val_list):
"""
尾插法
:param val_list:
:return:
"""
prehead = self.__head
for val in val_list:
new_node = DoubleLinkNode(val)
prehead.next = new_node
new_node.prior = prehead
prehead = prehead.next
def IsEmpty(self):
"""
判断双链表是否为空, 空表返回True
:return:
"""
if self.__head.next is None:
return True
def LengthList(self):
"""
返回双链表的长度
:return:
"""
prehead = self.__head
count = 0
if self.IsEmpty():
return count
while prehead.next:
count += 1
prehead = prehead.next
return count
def TraverseList(self):
"""
遍历双链表, 并打印
:return:
"""
prehead = self.__head
if self.IsEmpty():
print('链表为空!')
return 0
while prehead.next:
prehead = prehead.next
print(prehead.data, end=' ')
print('')
def InsertInPosition(self, pos, data):
"""
在某个位置插入
:param pos: [1, LengthSingleLinkList + 1]
:param data:
:return:
"""
prehead = self.__head
new_node = DoubleLinkNode(data)
if pos <= 0 or pos > self.LengthList() + 1:
print('插入位置错误!')
return 0
count = 0
while count < pos - 1:
prehead = prehead.next
count += 1
if prehead.next is not None:
new_node.next = prehead.next
prehead.next.prior = new_node
prehead.next = new_node
new_node.prior = prehead
def SearchWithPosition(self, pos):
"""
按位置查找元素
:param pos: [1, LengthSingleLinkList]
:return:
"""
prehead = self.__head
if pos <= 0 or pos > self.LengthList():
print('位置错误!')
return -1
count = 0
while count < pos:
prehead = prehead.next
count += 1
data = prehead.data
return data
def SearchWithVal(self, data):
"""
按值查找元素
:param data:
:return:
"""
prehead = self.__head
count = 0
while prehead.next:
prehead = prehead.next
count += 1
if prehead.data == data:
return count
print('该节点不存在!')
return -1
def RemoveWithPosition(self, pos):
"""
按位置移除元素
:param pos: [1, LengthSingleLinkList]
:return:
"""
prehead = self.__head
if pos <= 0 or pos > self.LengthList():
print('位置错误!')
return 0
count = 0
while count < pos - 1:
prehead = prehead.next
count += 1
temp = prehead.next
if temp.next is None:
prehead.next = None
else:
prehead.next = temp.next
temp.next.prior = prehead
del temp
def RemoveWithVal(self, data):
"""
按值移除元素
:param data:
:return:
"""
prehead = self.__head
while prehead.next:
prehead = prehead.next
if prehead.data == data:
if prehead.next is None:
prehead.prior.next = None
else:
prehead.prior.next = prehead.next
prehead.next.prior = prehead.prior
return -1
print('该节点不存在!')
测试代码如下:
from LinkList import DoubleLinkList
if __name__ == '__main__':
l1 = DoubleLinkList()
print('头插法创建双链表l1: ', end='')
l1.InsertInHead([1, 3, 5, 7])
l1.TraverseList()
l2 = DoubleLinkList()
print('尾插法创建双链表l2: ', end='')
l2.InsertInTail([1, 3, 5, 7])
l2.TraverseList()
print('链表l2的长度为: %d' % l2.LengthList())
print('在链表l2的第3个位置上插入值为2的节点: ', end='')
l2.InsertInPosition(3, 2)
l2.TraverseList()
print('链表l2的第4个位置上的节点的值为: %d' % l2.SearchWithPosition(4))
print('链表l2值为7的节点的位置为: %d' % l2.SearchWithVal(7))
print('移除链表l2的第5个位置上的节点: ', end='')
l2.RemoveWithPosition(5)
l2.TraverseList()
print('移除链表l2值为1的节点: ', end='')
l2.RemoveWithVal(1)
l2.TraverseList()
运行结果如下: