链表(Linked List)
很多的教材都是用C语言实现链表,因为c有指针,可以很方便的控制内存,很方便就实现链表,其他的语言,则没那么方便,由于python是动态语言,可以直接把对象赋值给新的变量,于是在python一切皆为对象的原理上实现链表的各项操作。
在实现链表python类的属性和方法操作之前,先整理一些链表的理论知识。
一、链表的基本结构
链表是通过一个个节点(Node)组成的,每个节点都包含了称为数据域(value)和指针域(next)的基本单元,它也是一种递归的数据结构。它能保持数据之间的逻辑顺序,但存储空间不必按照顺序存储。
链表的基本元素有:
- 节点:每个节点有两个部分,左边部分称为值域,用来存放用户数据;右边部分称为指针域,用来存放指向下一个元素的指针。
- head:head节点永远指向第一个节点
- tail: tail永远指向最后一个节点
- None:链表中最后一个节点的指针域为None值
二、链表的种类以及和动态数组(Array List)的对比
三、单向链表属性与各类操作方法代码
from util.Empty import Empty from util.Outbound import Outbound #先定一个node的类 class Node: #value + next def __init__ (self, value = None, next = None): self.value = value self.next = next #各类链表的操作方法 class LinkedList: def __init__(self): #定义一开始是空的属性 self.head = Node() self.tail = None self.length = 0 def peek(self): if not self.head.next: raise Empty( 'LinkedList is empty' ) return self.head.next def get_first(self): if not self.head.next: raise Empty( 'LinkedList is empty' ) return self.head.next def get_last(self): if not self.head.next: raise Empty( 'LinkedList is empty' ) node = self.head while node.next != None: node = node.next return node def get(self, index): if (index < 0 or index >= self.length): raise Outbound( 'index is out of bound' ); if not self.head.next: raise Empty( 'LinkedList is empty' ) node = self.head.next for i in range(index): node = node.next return node #加入到原node前面:O(1) def add_first(self, value): node = Node(value, None) #create一个node(为了插进一个链表) node.next = self.head.next #先连后一个的value self.head.next = node #再连上一个的next self.length += 1 #加入在原node后面:O(n) def add_last(self, value): new_node = Node(value) node = self.head while node.next != None: node = node.next node.next = new_node self.length += 1 def add(self, index, value): if (index < 0 or index > self.length): raise Outbound( 'index is out of bound' ) if not self.head.next: raise Empty( 'LinkedList is empty' ) new_node = Node(value) node = self.head for i in range(index): node = node.next new_node.next = node.next; node.next = new_node; self.length += 1 # O(1) def remove_first(self): if not self.head.next: raise Empty( 'LinkedList is empty' ) value = self.head.next self.head.next = self.head.next.next self.length -= 1 return value #O(n) def remove_last(self): if not self.head.next: raise Empty( 'LinkedList is empty' ) node = self.head.next prev = self.head while node.next != None: prev = node node = node.next prev.next = None return node.value #O(n) def remove(self, index): if (index < 0 or index >= self.length): raise Outbound( 'index is out of bound' ); if not self.head.next: raise Empty( 'LinkedList is empty' ) node = self.head for i in range(index): node = node.next result = node.next; node.next = node.next.next; self.length += 1 return result; #O(n) def printlist(self): node = self.head.next count = 0 while node and count<20: print(node.value, end = " ") node = node.next count = count + 1 print('')
ll = LinkedList() for i in range(1, 10): ll.add_last(i) #ll.add_end(i+1) mm = LinkedList() for i in range(100, 110): mm.add_last(i) #ll.add_end(i+1) ll.printlist() mm.printlist() #输出结果 1 2 3 4 5 6 7 8 9 100 101 102 103 104 105 106 107 108 109
ll.add_first(0) ll.add_first(-1) print('Linked List: ') ll.printlist() ''' Linked List: -1 0 1 2 3 4 5 6 7 8 9 ''' node = ll.peek() print('peek: ' , str(node.value)) #peek: -1 node = ll.get_first() print('get first: ' , str(node.value)) #get first: -1 node = ll.get_last() print('get last: ' , str(node.value)) #get last: 9 node = ll.get(0) print('get position 0: ' , str(node.value)) #get position 0: -1 node = ll.get(2) print('get position 2: ' , str(node.value)) #get position 2: 1 ll.add(0, -2) ll.add(4, 1.5) print('Linked List: ') ''' Linked List: -2 -1 0 1 1.5 2 3 4 5 6 7 8 9 ''' ll.printlist() node = ll.remove(0) print('remove position 0: ' , str(node.value)) ll.printlist() node = ll.remove(3) print('remove position 3: ' , str(node.value)) ll.printlist() ''' remove position 0: -2 -1 0 1 1.5 2 3 4 5 6 7 8 9 remove position 3: 1.5 -1 0 1 2 3 4 5 6 7 8 9 ''' ll = LinkedList() for i in range(1, 4): ll.add_first(i) #ll.add_end(i+1) print('Linked List: ') ll.printlist() ll.remove_first() ll.remove_first() print('Linked List: ') ll.printlist() ll.remove_first() print('Linked List: ') ll.printlist() ll = LinkedList() for i in range(1, 10): ll.add_last(i) ll.remove_first() ll.remove_last() ll.remove_first() ll.remove_last() print('Linked List: ') ll.printlist() ''' Linked List: 3 2 1 Linked List: 1 Linked List: Linked List: 3 4 5 6 7 '''
四、操作链表的原理知识
1.遍历链表
链表的基本操作:遍历next节点
- 在列表中查找一个元素
- 在列表中插入一个元素
- 从列表中删除一列元素
不可以用head来遍历列表
- 否则会丢失列表的一些节点
- 可以使用和head相同类型的索引变量:current