Python实现链表
链表是一种非常灵活的数据组织技术,实现链表有多种不同的方式。首先来看单链表。
1.单向链接表
单向链接表的结点是一个二元组,形式如下图所示
表元素域 | 下一节点链接域 |
---|
#节点类的定义
class LNode:
def __init__(self,elem, next_=None):
self.elem = elem
self.next = next_
单向链表的基本操作:
- 创建空链表
- 删除链表
- 判断表是否为空
- 表首插入元素
- 一般插入元素
- 表首删除元素
- 一般删除元素
单链表类的实现
1.结点类LNode的简单使用方法
lnode = LNode(1)
p = lnode
for i in range(2,10):
p.next = LNode(i)
p = p.next
while p is not None:
print(p.elem)
p = p.next
为处理链表中出现的异常状态,现定义一个异常类型
class LinkListError(ValueError):
pass
现基于结点类定义单链表对象的类
class SingleLink:
def __init__(self):
self.head = None
#判断链表是否为空
def is_empty(self):
return self.head is None
#头部添加结点
def prepend(self, elem):
node = LNode(elem)
node.next = self.head
self.head = node
#上述三句语句可简写为如下
#self.head = LNode(elem, self.head)
#头部删除
def pop(self):
if self.head is None:
raise LinkListError("no value")
e = self.head.elem
self.head = self.head.next
return e
#尾部增加结点
def append(self, elem):
if self.head is None:
self.head = LNode(elem)
p = self.head
while p.next:
p = p.next
p.next = LNode(elem)
#删除最后一个结点
def pop_last(self):
if self.head is None:
raise LinkNodeError("empty link")
p = self.head
if p.next is None:
e = p.next.elem
p = None
return e
while p.next.next:
p = p.next:
e = p.next.elem
p.next = None
return e
#打印出所有结点中包含的值
def printall(self):
p = self.head
while p.next:
print(p.elem, end="->")
p = p.next
2.单向链接表变形
基础的单链表在尾端进行操作时,时间复杂度为O(n),现对单链表进行改造,使其在对尾端结点进行操作时,时间复杂度为O(1),图示如下:
class LinkList1(SingleLink):
def __init__(self):
SingleLink.__init__(self)
self._rear = None
#头部增加结点
def prepend(self, elem):
if self.head is None:
self.head = LNode(elem)
self._rear = self.head
else:
self.head = LNode(elem, self.head)
#尾部增加结点
def append(self, elem):
if self.head is None:
self.head = LNode(elem)
self._rear = self.head
else:
self._rear.next = LNode(elem)
self._rear = self._rear.next
#删除尾结点
def pop_last(self):
if self.head is None:
raise LinkListError("empty link...")
p = self.head
if p.next is None:
e = self.head.elem
self.head = None
return e
while p.next.next:
p = p.next
e = p.next
p.next = None
self._rear = p
2.双向链接表
区别与单链表,双向链表多了一个反向引用域,可在结点类的基础上进行派生
双链表的结点类
#双链表结点类
class DLNode(LNode):
def __init__(self, elem, prev = None, next_ = None):
LNode.__init__(self, elem, next_)
self.prev = prev
双链表的实现
#双链表类
class DLList(LinkList1):
def __init__(self):
LinkList1.__init__(self)
#头部增加结点
def prepend(self, elem):
p = DLNode(elem, None, self.head)
if self.head is None:
self.rear = p
else:
p.next.pre = p
self.head = p
#尾部增加
def append(self, elem):
p = DLNode(elem, self.rear, self.head)
if self.head is None:
self.head = p
else:
p.pre.next = p
self.rear = p
#删除首结点
def pop(self):
if self.head is None:
raise LinkListError("empty link...")
e = self.head.elem
self.head = self.head.next
if self.head:
self.head.pre = None
return e
#删除尾节点
def pop_last(self):
if self.head is None:
raise LinkListError("empty link...")
e = self.rear.elem
self.rear = self.rear.pre
if self.rear:
self.rear.next = None
#上述代码借鉴自裘宗燕老师的《数据结构与算法》Python语言描述