Python数据结构(链表)
单向链表
单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
表元素域elem用来存放具体的数据
链接域next用来存放下一个节点的位置(python中的标识)
变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点
节点实现
python
class node(object):
def __init__(self,item):
# __item存放的是数据元素
self.item = item
# __next是下一个节点的表示
self.next = None
单链表的操作
python
class node(object):
def __init__(self,item):
# __item存放的是数据元素
self.item = item
# __next是下一个节点的表示
self.next = None
class SingleLinkList(object):
def __init__(self,node=None):
self.head = node # 定义头节点,默认值为Node
def is_empty(): #链表是否为空
return self.head == None:
def length(): #链表长度
cur = self.head #cur游标表当前的节点,用来移动遍历节点
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(): #遍历整个链表
cur = self.head
while cur != None:
print(cur.item, end=" ")
cur = cur.next
print("")
def get_all(self):#查找整个链表数据
cur = self.head
res = []
while True:#遍历整个链表,并转成列表形式
if cur.next == None:
if cur.item:
res.append(cur.item)
break
else:
if cur.item:
res.append(cur.item)
cur = cur.next
return res
def reverse_printing(self):
res = self.get_all()#获取列表形式所有链表数据
ret =res[::-1]#反转列表
return ret
def reverse(self):#反转链表
res = self.reverse_printing()#获取逆序的列表形式链表
sign1 = self.head#创建游标
while True:#遍历整个链表,断开各连接,没有指向的数据会被垃圾回收
if sign1.next == None:
break
sign2 = sign1.next
sign1.next = None
sign1 = sign2
sign = self.head
for ele in res:#根据逆序列表形式链表,重新构建链表
body = Item(ele)
sign.next = body
sign = sign.next
def ReverseList(self): #反转链表
cur = self.head
pre = None
while cur:
nextNode = cur.next
cur.next = pre
pre = cur
cur = nextNode
return pre
def add(item): #链表头部添加元素,头插法
node = Node(item)
node.next = self.head
self.head = node
def append(item): #链表尾部添加元素,尾插法
node = Node(item)
if self.is_empty():
self.head = node
else:
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = node
def insert(pos,item): #指定位置添加元素
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
pre = self.head
count = 0
while count < (pos-1):
count += 1
pre = pre.next
# 当循环退出后,pre指向pos-1的位置
node = Node(item)
node.next = pre.next
pre.next = node
def remove(item): #删除节点
# 双指针
cur = self.head
pre = None
while cur != None:
if cur.item == item:
# 先判断此节点是否为头结点
if cur == self.head:
self.head = cur.next
else:
pre.next = cur.next
break
else:
pre = cur
cur = cur.next
# 单指针
pre = self.head
while pre != None:
if pre.next.item == item:
if pre == self.head:
self.head = pre.next
else:
pre.next = pre.next.next
break
else:
pre = pre.nex
def search(item): #查找节点是否存在
cur = self.head
while cur != None:
if cur.item == item:
return True
else:
cur = cur.next
return False
链表与顺序表的对比
链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活。
链表与顺序表的各种操作复杂度如下所示:
操作 | 链表 | 顺序表 |
---|---|---|
访问元素 | O(n) | O(1) |
在头部插入/删除 | O(1) | O(n) |
在尾部插入/删除 | O(n) | O(1) |
在中间插入/删除 | O(n) | O(n) |
注意虽然表面看起来复杂度都是 O(n),但是链表和顺序表在插入和删除时进行的是完全不同的操作。链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部的特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。
单向循环链表
单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点
操作
python
class Node(object):
def __init__(self,item):
self.item = item
self.next = Node
class SingleCycleLinkList(object): #单向循环链表
def __init__(self,node=Node):
self.head = node# 定义头节点
if node:
node.next = node
def is_empty(self): #判空
return self.head = None
def length(self): #链表长度
if self.is_empty():
return 0
cur = self.head
count = 1
while cur.next != self.head:
count += 1
cur = cur.next
return count
def travel(self): #遍历链表
if self.is_empty():
return
cur = self.head
while cur.next != self.next:
print(cur.item, end=' -> ')
cur = cur.next
print(cur.item) #尾节点不能进入循环所以要出循环后打印出来
def add(self,item): #头插法
node = Node(item)
if self.is_empty():
self.head = node
node.next = node
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
#退出循环后cur指向尾节点
node.next = self.head
self.head = node
cur.next = self.head #cur.next = node
def append(self,item): #尾插法
node = Node(item)
if self.is_empty():
self.head = node
node.next = node
else:
cur = self.head
while cur.next != self.head:
cur =cur.next
node.next = self.head
cur.next = node
def insert(self,pos,item): #在指定位置插入元素
if pos < 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
pre = self.head
count = 0
while count < (pos-1):
count += 1
pre = pre.next
node = Node(item)
node.next = pre.next
pre.next = node
def remove(self,item): #删除节点
cur = self.head
pre = None
while cur.next != self.head:
if cur.item == item;
#判断此节点是否为头结点
if cur == sef.head:
#删除是头结点的情况先找到尾节点
rear = self.head
while rear.next != self.head:
rear = rear.next
self.head = cur.next
rear.next = self.head
else:
#中间节点
pre.next = cur.next
return
else:
pre = cur
cur = cur.next
#退出循环,cur指向尾节点
if cur.item == item:
if cur == self.head:
#链表只有一个节点的情况
self.head = None
else:
pre.next = cur.next
def search(self,item): #查找节点
if self.is_empty():
return False
cur = self.head
while cur.next!= self.head:
if cur.item = item:
return True
else:
cur = cur.next
#退出循环,cur指向尾节点
if cur.item == item:
return True
return False
双向链表
一种更复杂的链表是"双向链表"或"双面链表"。每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值,而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。
操作
python
class Node(object): #应为前几个方法与单链表都一样用面向对象的思想可以把单链表中的类继承过来
"""双链表的节点"""
def __init__(self, item):
self.item = item
self.next = None
self.prev = None
def is_empty(): #链表是否为空
return self.head == None:
def length(): #链表长度
cur = self.head #cur游标表当前的节点,用来移动遍历节点
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(): #遍历整个链表
cur = self.head
while cur != None:
print(cur.item, end=" ")
cur = cur.next
print("")
def add(item): #链表头部添加元素,头插法
node = Node(item)
node.next = self.head
self.head.prev = node
self.head = node
def append(item): #链表尾部添加元素,尾插法
node = Node(item)
if self.is_empty():
self.head = node
else:
cur = self.head
while cur.next != None:
cur = cur.next
cur.next = node
node.prev = cur
def insert(pos,item): #指定位置添加元素
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
cur = self.head
count = 0
while count < pos:
count += 1
cur = cur.next
# 当循环退出后,cur指向pos的位置
node = Node(item)
node.next = cur
node.prev = cur.prev
cur.prev.next = node
cur.prev = node
def remove(item): #删除节点
cur = self.head
while cur != None:
if cur.item == item:
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:
cur = cur.nex
def search(item): #查找节点是否存在
cur = self.head
while cur != None:
if cur.item == item:
return True
else:
cur = cur.next
return False