6.1 简介
结点(node):包含数据以及至少一个指向另一个结点的指针。
链式结构(linked structure):包含结点的容器。
链表(linked list):每个结点一个接一个串联起来的链式结构。
头结点:指向链表第一个结点(首元结点)的结点,其数据域不储存链表,其指针称为头指针(head pointer)。
首元结点:链表的第一个元素,即头指针指向的节点。
尾结点(tail node):链表的最后一个结点。
外部引用(external references):指向结点的引用变量,但并不包含在结点中。(???)
结点可以用python类来实现
class Node(object):
def __init__(self, item):
self.item = item
self.next = None
6.2 单链表
单链表(single linked list):每一个结点只包含一个指针域,并允许从第一个结点遍历到最后一个结点的链表。
遍历
遍历单链表时,我们需要使用一个临时用工作指针,来指向链表中的每一个结点。遍历的最开始,临时用工作指针curNode指向首元结点,即head指向的节点。使用结点的next方法,来移动curNode,最后当遍历到最后一个结点时,由于最后一个结点指向的是None,所以之后curNode便指向None,遍历结束。
def traversal(head):
curNode = head # 临时用工作指针
while curNode is not None:
print curNode.data
curNode = curNode.next
搜索
线性搜索,实际上就是遍历,直到找到符合目标的结点为止。
# 在未排序单链表中搜索
def unorderedSearch(head, target):
curNode = head
while curNode is not None and curNode.data != target:
curNode = curNode.next
return curNode is not None
补插元素(prepend)
补插元素,即在单链表的首元结点之前再插入一个结点。即将头指针指向新节点,新节点再指向原来的首元结点即可。
# 补插元素
def prepend(head, item):
newNode = listNode(item) # 创建新节点
newNode.next = head # 将新节点的指针指向原首元结点
head = newNode # 将新节点设置为首元结点
删除结点得分两种情况:(1)删除的是首元结点,(2)删除的是非首元结点。
删除结点得使用两个临时工作用指针,分别是predNode和curNode。初始状态是predNode指向None,curNode指向首元结点,如果删除的是首元结点,curNode就指向None,头指针就指向下一个节点即可。如果删除的是非首元结点,就先进行搜索,让curNode指向要删除的结点,此时predNode指向的是要删除结点的上一个结点。直接将要删除的结点指向None,preNode指向的结点,指向要删除结点的下一结点即可。
# 删除结点
def remove(head, target):
predNode = None
curNode = head # 需要两个临时用工作指针,两个指针同时移动,curNode先移动,predNode紧随其后
while curNode is not None and curNode.data != target:
predNode = curNode
curNode = curNode.next
if curNode is not None:
if curNode is head: # 如果删除的是首元结点,此时curNode指向的也是首元结点
head = curNode.next # 直接将curNode指向结点的下一结点设置为首元结点即可,此时原来的首元结点的引用次数降为零,被python虚拟机回收内存。
else:
predNode.next = curNode.next # 删除curNode指向的结点,此时predNode指向的是curNode指向结点的上一结点,将该结点的指针域指向curNode指向结点的下一结点,即curNode.next