1 单链表
单链表由两部分组成:元素域与链接域。 元素域保存作为表元素的数据项,链接域保存同一个表里的下一个结点的标识。
单链表有以下特点:
- 一个单链表由一些具体的表结点组成;
- 每个结点是一个对象,由自己的标识,也称为该结点的链接;
- 结点之间通过结点链接建立起单向的顺序链接;
- 在python中,通常用None值作为单链表中最后一个结点的链接域。
为方便讨论,现在定义一个简单的表结点类:
class LNode:
def __init__(self,elem,next_=None):
self.elem=elem
self.next=next_
1.1 基本链表操作
1.1.1 创建空链表:只需要把表头变量设置成空链接,在python语言中设置成为None。
1.1.2 删除链表:应丢弃这个链表里的所有结点。在python语言中,只需要将表指针赋值为None,就抛弃了链表中的所有结点。python解释器的存储管理系统会自动回收不用的存储。
1.1.3 判断表是否为空:将表头变量的值与空链接比较,在python语言中,就是检查相应的变量是否为None。
1.1.4 判断表是否会满:一般而言链表不会满。
1.2 加入元素
1.2.1 表首端插入: 三步即可完成:
- 创建一个新节点并存入数据;
- 把原链表首节点的链接域存入新结点的链接域next。
- 修改表头变量,使之指向新节点。
示例代码段:
q=LNode(13)
q.next=head.next
head=q
1.2.2 表中间元素的插入(包括链表末尾插入): 设变量pre已指向要插入元素位置的歉前一结点,操作也分为三步:
- 创建一个新节点并存入数据;
- 把pre所指结点的next域的值存入新节点的链接域next;
- 修改pre的next域,使之指向新结点;
示例代码段
q=LNode(12)
q.next=pre.next
pre.next=q
1.3 删除元素
1.3.1 删除表首元素:删除表中第一个元素对应于删除表的第一个结点,为此只需要修改表头指针,令其指向表中的第二个结点。
示例代码段
head=head.next
1.3.2 一般元素的情况删除:一般情况删除须先找到删除元素所在结点的前一结点,设用变量pre指向,然后修改pre的next域,使之指向被删除域的下一结点。
示例代码段
pre.next=pre.next.next
1.4 扫描、定位和遍历
1.4.1 扫描:由于单链表只有一个方向的链接,开始情况下只有表头变量在掌握中,所以对表的内容的检查只能从表头变量开始,沿着表中链接逐步进行。这种行为称之为链表的扫描。
- 按下标定位:按Python惯例,链表首结点的元素应看做下标为0,其他元素依次排列,确定第i个元素所在结点的操作称为按下标定位。代码示例段如下:
p=head
while p is not None and i > 0:
i-=1
p=p.next
- 按元素定位:假设在链表中需要找到满足谓词pred的元素,示例代码段如下:
p=head
while p is not None and not pred(p.elem):
p=p.next
- 完整的遍历
p=head
while p is not None:
print p.elem
p=p.next
1.5 链表操作的时间复杂度
- 创建空表:O(1)
- 删除表:O(1)
- 判断空表:O(1)
- 加入元素(都需要加一个T()分配时间):
- 首端加入元素,O(1)
- 尾端加入元素,O(n)
- 定位加入元素,O(n),平均情况和最坏情况
- 删除元素:
- 首端删除元素:O(1)
- 尾端删除元素:O(n)
- 定位删除元素:O(n),平均情况和最坏情况
- 其他删除:通常需要扫描整个表或其一部分
1.6 LList类的定义,初始化函数和简单操作
现在基于结点类LNode定义一个单链表类,只有一个引用链接结点的_head域,初始化为None表示建立的是一个空表。
class LList:
def __init__(self):
self._head=None
def is_empty(self):
return self._head is None
#insert element on the beginning of the list
def prepend(self):
self._head=LNode(elem,self._head)
def pop(self):
if self._head is None: #if list is none, raise exception
raise Error
e=self._head.elem
self._head=self._head.next
return e
# insert element on the end of the List
def append(self,elem):
if self._head is None:
self._head=LNode(elem)
return
p=self._head
while p is not None:
p=p.next
p.next=LNode(elem)
# delete the last node and return it's value
def pop_last(self):
if self._head is None:
raise ExceptionError
p=self._head
if p.next is None:
e=p.elem
self._head=None
return e
while p.next.next is not None:
p=p.next
e=p.next.elem
p.next=None
return e
#basic scan element in the List
def find(self,pred):
p=self._head
while p is not None:
if pred(p.elem):
return p.elem
p=p.next
# print all elem in the list
def printall(self):
p=self._head
while p is not None:
print p.elem
if p.next is not None:
print ','
p=p.next
print ''
参考文献:数据结构与算法:Python语言描述