单向链表
单向链表最简单的实现形式就是由多个节点的集合共同构成一个线性序列。每个节点存储一个对象的引用,这个引用指向序列中的一个元素,即存储指向列表中的下一个节点
链表的第一个节点和最后一个结点分别为列表的头节点和尾节点
实现单向链表的代码如下
class Node:#节点
def __init__(self,elem):
self.elem=elem
self.next=None #初始下一节点为空
class SingleLinkList:
#单链表
def __init__(self,node=None):#初始化链表
self._head=node
def is_empty(self):#判断链表是否为空
return self._head==None
def length(self):
cur=self._head
count=0
while cur!=None:
count+=1
cur=cur.next
return count
def travel(self):#遍历整个链表
cur=self._head
while cur!=None:
print(cur.elem,end=' ')
cur=cur.next
print('\n')
def add(self,item):#向链表头部添加元素
node=Node(item)
node.next=self._head
self._head=node
def append(self,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(self,pos,item):#指定位置插入元素
if pos<=0 or pos>self.length()+1:
return False
else:
node=Node(item)
if pos==1:
node.next=self._head
self._head=node
else:
j=1
cur=self._head
while j<pos-1:
j+=1
cur=cur.next
node.next=cur.next
cur.next=node
return True
def remove(self,item):
cur=self._head
pre=None
flag=1
while cur!=None and flag:
if cur.elem==item:
if cur==self._head:
self._head=cur.next
else:
pre.next=cur.next
flag=0
else:
pre=cur
cur=cur.next
def search(self,item):
#查找结点是否存在
cur=self._head
while cur!=None:
if cur.elem==item:
return True
cur=cur.next
return False
L=SingleLinkList()
用单链表实现栈
用单链表实现栈首先需要决定用链表的头部或尾部来实现栈顶。最好的选择是在头部,因为只有在头部我们才能在一个常数时间内有效地插入和删除元素由于所有操作都会影响栈顶,因此规定栈顶在链表的头部
class Empty:
pass
class LinkedStack:
class _Node:
def __init__(self,element,next):
self._element=element
self._next=next
def __init__(self):
self._head=None
self._size=0
def __len__(self):
return self._size
def is_empty(self):
return self._size==0
def push(self,e):
self._head=self._Node(e,self._head)
self._size+=1
def top(self):
if self.is_empty():
raise Empty('Stack is Empty')
return self._head._element
def pop(self):
if self.is_empty():
raise Empty('Stack is Empty')
e=self._head._element
self._head=self._head._next
self._size-=1
return e
def travel(self):
cur=self._head
while cur!=None:
print(cur._element,end=' ')
cur=cur._next
print('\n')
LS=LinkedStack()
LS.push(5)
LS.push(4)
LS.push(3)
LS.travel()
print(LS.top())
print(LS.pop())
LS.travel()
用单向链表实现队列
由于需要对队列的两端执行操作,我们显示地为每个队列维护一个_head和一个_tail指针作为实例变量,将队列的前端和链表的头部对应,队列的后端与链表的尾部对应
class Empty:
pass
class LinkedQueue:
class _Node:
def __init__(self,element,next):
self._element=element
self._next=next
def __init__(self):
self._head=None
self._tail=None
self._size=0
def __len__(self):
return self._size
def is_empty(self):
return self._size==0
def first(self):
if self.is_empty()==True:
raise Empty('Queue is Empty')
return self._head._element
def dequeue(self):
if self.is_empty():
raise Empty('Queue is Empty')
e=self._head._element
self._head=self._head._next
self._size-=1
if self.is_empty():
self._tail=None
return e
def enqueue(self,e):
node=self._Node(e,None)
if self.is_empty():
self._head=node
else:
self._tail._next=node
self._tail=node
self._size+=1
Q=LinkedQueue()
Q.enqueue(3)
Q.enqueue(4)
Q.enqueue(5)
print(Q.dequeue())
print(Q.dequeue())
print(Q.dequeue())
循环链表
在链表中,可以使链表的尾部节点的"next"指针指向链表的头部,我们称这种结构为循环链表
用循环链表实现队列
因为循环链表尾部的next指针是指向头部的,所以用循环链表实现队列时不需要_head变量 只设一个_tail变量即可
class Empty(Exception):
pass
class CircularQueue:
class _Node:
def __init__(self,element,next):
self._element=element
self._next=next
def __init__(self):
self._tail=None
self._size=0
def __len__(self):
return self._size
def is_empty(self):
return self._size==0
def first(self):
if self.is_empty():
raise Empty('Queue is empty')
head=self._tail._next
return head._element
def dequeue(self):
if self.is_empty():
raise Empty('Queue is empty')
head=self._tail._next
if self._size==1:
self._tail=None
else:
self._tail._next=head._next
self._size-=1
return head._element
def enqueue(self,e):
node=self._Node(e,None)
if self.is_empty():
node._next=node
else:
node._next=self._tail._next
self._tail._next=node
self._tail=node
self._size+=1
def rotate(self):#现在的头节点变成尾节点
if self._size>0:
self._tail=self._tail._next
CQ=CircularQueue()
CQ.enqueue(3)
CQ.enqueue(4)
CQ.enqueue(5)
print(CQ.dequeue())
print(CQ.dequeue())
print(CQ.dequeue())
双向链表
如果一个链表的每个节点都维护了指向其先驱节点以及后继节点的引用 这样的结构被称为双向链表 引入prev 引用其前驱节点
头哨兵和尾哨兵:
在操作接近一个双向链表的边界时,为了避免一些特殊情况,在链表的两端都追加节点 在列表的起始位置添加头节点,在列表的结尾位置添加尾节点 这些特定的节点被称为哨兵。这些节点中并不存储主序列的元素
当使用哨兵节点时,一个空链表需要初始化,使头节点的next 指向尾节点,并令尾节点的prev指向头节点
class Empty(Exception):
pass
class DoublyLinkedBase:
class _Node:
def __init__(self,element,prev,next):
self._element=element
self._prev=prev
self._next=next
def __init__(self):
self._header=self._Node(None,None,None)
self._tailer=self._Node(None,None,None)
self._header._next=self._tailer
self._tailer._prev=self._header
self._size=0
def __len__(self):
return self._size
def is_empty(self):
return self._size==0
def _insert_between(self,e,predecessor,successor):
newest=self._Node(e,predecessor,successor)
predecessor._next=newest
successor._prev=newest
self.size+=1
return newest
def _delete_node(self,node):
predecessor=node._prev
successor=node._next
predecessor._next=successor
successor._prev=predecessor
self._size-=1
element=node._element
node._prev=node._next=node._element=None
return element
用双向链表实现双端队列
class Empty(Exception):
pass
class _DoublyLinkedBase:
class _Node:
def __init__(self,element,prev,next):
self._element=element
self._prev=prev
self._next=next
def __init__(self):
self._header=self._Node(None,None,None)
self._tailer=self._Node(None,None,None)
self._header._next=self._tailer
self._tailer._prev=self._header
self._size=0
def __len__(self):
return self._size
def is_empty(self):
return self._size==0
def _insert_between(self,e,predecessor,successor):
newest=self._Node(e,predecessor,successor)
predecessor._next=newest
successor._prev=newest
self._size+=1
return newest
def _delete_node(self,node):
predecessor=node._prev
successor=node._next
predecessor._next=successor
successor._prev=predecessor
self._size-=1
element=node._element
node._prev=node._next=node._element=None
return element
class LinkedDeque(_DoublyLinkedBase):
def first(self):
if self.is_empty():
raise Empty('Deque is empty')
return self._header._next._element
def last(self):
if self.is_empty():
raise Empty('Deque is empty')
return self._tailer._prev._element
def insert_first(self,e):
self._insert_between(e,self._header,self._header._next)
def insert_last(self,e):
self._insert_between(e,self._tailer._prev,self._tailer)
def delete_first(self):
if self.is_empty():
raise Empty('Deque is empty')
return self._delete_node(self._header._next)
def delete_last(self):
if self.is_empty():
raise Empty('Deque is empty')
return self._delete_node(self._tailer._prev)
LD=LinkedDeque()
LD.insert_first(1)
LD.insert_first(2)
LD.insert_first(3)
LD.insert_first(4)
print(LD.delete_last())
print(LD.delete_first())
含位置信息的列表抽象数据类型
位置实例是一个简单的对象,只支持以下方法
p.element():返回存储在位置p的元素
在位置列表ADT中位置可以充当一些方法的参数或是作为其他方法的返回值。在描述位置列表的行为时,我们介绍如下列表L所支持的访问器方法:
L.first():返回L中第一个元素的位置。如果L为空,则返回None
L.last():返回L中最后一个元素的位置。如果L为空,则返回None
L.before§:返回L中p紧邻的前面元素的位置。如果p为第一个位置,则返回None
L.after§:返回L中p紧邻的后面元素的位置。如果p为最后一个位置,则返回None
L.is_empty():如果L列表不包含任何元素,返回True
Len(L):返回列表元素的个数
Iter(L):返回列表元素的前向迭代器
L.add_first(e)在L前面插入新元素e,返回新元素的位置
L.add_last(e)在L后面插入新元素e,返回新元素的位置
L.add_before(p,e)在L中位置p之前插入一个新元素e,返回新元素的位置
L.add_after(p,e)在L中位置p之后插入一个新元素e,返回新元素的位置
L.replace(p,e):用元素e取代位置p处的元素,返回之前p位置处的元素
L.delete§:删除并且返回L中位置p处的元素,取消该位置
用双向链表实现位置列表类PositionalList
class Empty(Exception):
pass
class _DoublyLinkedBase:
class _Node:
def __init__(self,element,prev,next):
self._element=element
self._prev=prev
self._next=next
def __init__(self):
self._header=self._Node(None,None,None)
self._tailer=self._Node(None,None,None)
self._header._next=self._tailer
self._tailer._prev=self._header
self._size=0
def __len__(self):
return self._size
def is_empty(self):
return self._size==0
def _insert_between(self,e,predecessor,successor):
newest=self._Node(e,predecessor,successor)
predecessor._next=newest
successor._prev=newest
self.size+=1
return newest
def _delete_node(self,node):
predecessor=node._prev
successor=node._next
predecessor._next=successor
successor._prev=predecessor
self._size-=1
element=node._element
node._prev=node._next=node._element=None
return element
class PositionalList(_DoublyLinkedBase):
class Position:
def __init__(self,container,node):
self._container=container
self.node=node
def element(self):
return self._node._element
def __eq__(self,other):
return type(other) is type(self) and other._node is self._node
def __ne__(self,other):
return not (self==other)
def _validate(self,p):
if not isinstance(p,self.Position):
raise TypeError('p must be proper Position type')
if p._container is not self:
raise ValueError('p does not belong to this container')
if p._node._next is None:
raise ValueError('p is no longer vaild')
return p._node
def _make_position(self,node):
if node is self._header or node is self._tailer:
return None
else:
return self.Position(self,node)
def first(self):
return self._make_position(self._header._next)
def last(self):
return self._make_position(self._tailer._prev)
def before(self,p):
node=self._validate(p)
return self._make_position(node._prev)
def after(self,p):
node=self._validate(p)
return self._make_position(node._next)
def __iter__(self):
cursor=self.first()
while cursor is not None:
yield cursor.element()
cursor=self.after(cursor)
def _insert_between(self,e,predecessor,successor):
node=super()._insert_between(e,predecessor,successor)
return self._make_position(node)
def add_first(self,e):
return self._insert_between(e,self._header,self._header._next)
def add_last(self,e):
return self._insert_between(e,self._tailer._prev,self._tailer)
def add_before(self,p,e):
original=self._validate(p)
return self._insert_between(e,original._prev,original)
def add_after(self,p,e):
original=self._validate(p)
return self._insert_between(e,original,original._next)
def delete(self,p):
original=self._validate(p)
return self._delete_node(original)
def replace(self,p,e):
original=self._validate(p)
old_value=original._element
original._element=e
return old_value
位置列表的排序(直接插入排序)
def insertion_sort(L):#插入排序
if len(L)>1:
maker=L.first()
while maker!=L.last():
pivot=L.after(maker)
value=pivot.element()
if value>maker.element():
maker=pivot
else:
walk=maker
while walk!=L.first() and L.before(walk).element()>=value:
walk=L.before(walk)
L.delete(pivot)
L.add_before(walk,value)