顺序表可以在O(1)的时间内定位元素,但是插入或者删除需要O(n)的时间,因为其需要移动大量的元素块。
链表的实现不需要连续的存储区。链表的每个结点含有表元素和指向后继元素的指针。
在链表表首插入和删除元素的复杂度都是O(1),在其他位置插入和删除元素的复杂度都是O(n)。
下面定义一个链表的结点类:
class LNode: def __init__(self, elem, pnext = None): self.elem = elem self.pnext = pnext
1、向链表插入元素
表首插入:在表首插入元素,需要将新结点的pnext指向原来的表首元素,然后修改表头变量,使其指向新的结点
示例代码:
q = LNode(13) q.pnext = head.pnext head = q
一般情况插入:要想在链表的某个位置插入元素,需要找到插入位置的前一个结点pre,将新结点的pnext指向原来pre结点的后一个结点,并且将pre结点的pnext指向新的结点。
q = LNode(13) q.pnext = pre.pnext pre.pnext = q
尾端插入:需要先找到最后一个结点,然后在其后面插入新的结点。
def append(self, elem): if self.head is None: self.head = LNode(elem) return p = self.head while p.pnext is not None: p = p.pnext p.pnext = LNode(elem)
2、删除链表中的元素
删除表首元素:删除表首元素只需要将表头指针指向表中的第二个结点即可。被丢弃的结点会被Python解释器自动回收。
head = head.pnext
一般情况的删除:一般情况删除需要先找到被删元素的前一个结点pre,将其pnext指向被删结点的下一个结点即可。
pre.pnext = pre.pnext.pnext
删除表尾元素:需要找到倒数第二个结点,也就是p.pnext.pnext为None的p。
def pop_last(self): if self.head is None: return False p = self.head if p.pnext is None: e = p.elem self.head = None return e while p.pnext.pnext is not None: p = p.pnext e = p.pnext.elem p.pnext = None return e打印链表中所有元素:
def printall(self): p = self.head while p is not None: print(p.elem, end='') if p.pnext is not None: print(', ', end='') p = p.pnext print('')
以下是所有的代码:
class LinkedListUnderflow(ValueError): pass class LNode: def __init__(self, elem, pnext=None): self.elem = elem self.pnext = pnext class LList: def __init__(self): self.head = None self.length = 0 #对结点进行计数 def is_empty(self): return self.head is None def prepend(self, elem): #在表首添加元素 self.head = LNode(elem, self.head) self.length += 1 def append(self, elem):#在表尾添加元素 if self.head is None: #如果表头为空,说明是空表,直接将元素添加到表头 self.head = LNode(elem) self.length += 1 return p = self.head while p.pnext is not None: p = p.pnext p.pnext = LNode(elem) self.length += 1 def insert(self, index, value): #在一般位置插入元素 if index > self.length: raise LinkedListUnderflow('in insert') else: p = self.head if index == 0: #如果在表首插入元素 self.prepend(value) return i = 0 while i < index-1: #找出插入结点的前一个结点 p = p.pnext i += 1 insert_node = LNode(value) insert_node.pnext = p.pnext #插入结点的pnext指向后一个结点 p.pnext = insert_node #p的pnext指向插入结点 self.length += 1 return def delete(self, index): if index > self.length: raise LinkedListUnderflow('in insert') else: if index == 0: self.head = self.head.pnext self.length -= 1 return else: p = self.head i = 0 while i < index-1: p = p.pnext i += 1 p.pnext = p.pnext.pnext self.length -= 1 return def pop_first(self): if self.head is None: raise LinkedListUnderflow('in pop') e = self.head.elem self.head = self.head.pnext return e def pop_last(self): if self.head is None: return False p = self.head if p.pnext is None: e = p.elem self.head = None return e while p.pnext.pnext is not None: p = p.pnext e = p.pnext.elem p.pnext = None return e def printall(self): p = self.head while p is not None: print(p.elem, end='') if p.pnext is not None: print(', ', end='') p = p.pnext print('') def clear(self): self.head = None #直接将表头指针置为None,就可以删除整个链表 self.length = 0 print('clear successfully') if __name__=="__main__": lst = LList() for i in range(6): lst.append(i) lst.printall() lst.delete(3) lst.clear() lst.printall() print(lst.length)