链表(linked_list)是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个结点,一个是存储元素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。
链表通过将链点 i 与其邻居链点 i+1 通过指针相关联,从索引 0 到索引 N-1 对链点进行排序。
单链表
链表分为单链表和双链表两种。在接下来的内容里,我们将逐步介绍单链表的具体功能是如何实现的。
1. 创建 Node 类
创建一个 Node 的类,作为基础数据结构:链点,并初始化对应的内参。
具体实现代码如下:
1 2 3 4
| class Node: def __init__(self, data): self.data = data self.next = None
|
2. 创建 Linked_List 类
创建一个 Linked_List 的类,并初始化对应的内参。
具体实现代码如下:
1 2 3
| class Linked_List: def __init__(self, head=None): self.head = head
|
3. 添加 append 函数
添加一个 append 的函数,功能是向链表添加新的结点
具体实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12
| def append(self, new_element): current = self.head if self.head: while current.next: current = current.next current.next = new_element else: self.head = new_element
|
4. 添加 is_empty 函数
添加一个 is_empty 的函数,功能是判断链表是否为空
具体实现代码如下:
1 2 3 4 5 6
| def is_empty(self): """ 判断链表是否为空 """ return not self.head
|
5. 添加 insert 函数
insert(new_element) 往链表中任意位置添加一个 new_element 元素
流程如下:
- 先判断要插入的位置是否在链表的索引范围内。
- 当插入的位置是头结点(即索引为 0)时,做特殊情况处理。
- 当要插入结点的位置不在 0 时,找到要插入的位置,插入新结点
具体实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| def insert(self, position, new_element): """ 在链表中指定索引处插入元素 """ if position < 0 or position > self.get_length(): raise IndexError('insert 插入时,key 的值超出了范围') temp = self.head if position == 0: new_element.next = temp self.head = new_element return i = 0 while i < position: pre = temp temp = temp.next i += 1 pre.next = new_element new_element.next = temp
|
6. 添加 remove 函数
remove() 从链表中任意位置删除一个元素
流程如下:
- 先判断要删除的元素索引是否存在,如果不存在抛出错误
- 接着判断当存在链表元素时才能执行删除操作。
- 当要删除的是头结点时(即索引为 0),做特殊情况处理。
- 其他情况时,通过循环找到要删除的结点。
- 最后要做的就是把这个结点删除掉。
具体实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| def remove(self, position): """ 删除指定索引的链表元素 """ if position < 0 or position > self.get_length()-1: raise IndexError('删除元素的索引超出范围')
i = 0 temp = self.head while temp != None: if position == 0: self.head = temp.next temp.next = None return
pre = temp temp = temp.next i += 1 if i == position: pre.next = temp.next temp.next = None return
|
7. 添加其他函数
get_length:获取链表的长度
print_list:遍历链表,并将元素依次打印出来
reverse:将链表反转
initlist: 将列表转换为链表
具体实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| def get_length(self): """ 返回链表的长度 """ 头部结点赋值给头部结点 temp = self.head length = 0 while temp != None: length = length+1 temp = temp.next return length
def print_list(self): """ 遍历链表,并将元素依次打印出来 """ print("linked_list:") temp = self.head while temp is not None: print(temp.data) temp = temp.next
def reverse(self): """ 将链表反转 """ prev = None current = self.head while current: next_node = current.next current.next = prev prev = current current = next_node self.head = prev
def initlist(self,data_list): """ 将列表转换为链表 """ self.head = Node(data_list[0]) temp = self.head for i in data_list[1:]: node = Node(i) temp.next = node temp = temp.next
|
基于链表的基本功能介绍,我们给出链表的完整代码
在/home/shiyanlou/
下新建一个文件linked_list.py
。
具体实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
| class Node: def __init__(self, data): self.data = data self.next = None
class Linked_List: def __init__(self, head=None): self.head = head
def append(self, new_element): """ 在链表后面增加一个元素 """ current = self.head if self.head: while current.next: current = current.next current.next = new_element else: self.head = new_element
def is_empty(self): """ 判断链表是否为空 """ return not self.head
def get_length(self): """ 获取链表的长度 """ temp = self.head length = 0 while temp != None: length = length+1 temp = temp.next return length
def insert(self, position, new_element): """ 在链表中指定索引处插入元素 """ if position < 0 or position > self.get_length(): raise IndexError('insert 插入时,key 的值超出了范围') temp = self.head if position == 0: new_element.next, self.head = temp, new_element return i = 0 while i < position: pre, temp = temp, temp.next i += 1 pre.next, new_element.next = new_element, temp
def print_list(self): """ 遍历链表,并将元素依次打印出来 """ print("linked_list:") temp = self.head new_list = [] while temp is not None: new_list.append(temp.data) temp = temp.next print(new_list)
def remove(self, position): """ 删除指定索引的链表元素 """ if position < 0 or position > self.get_length()-1: raise IndexError('删除元素的位置超出范围')
i = 0 temp = self.head while temp != None: if position == 0: self.head = temp.next temp.next = None return True pre, temp = temp, temp.next
i += 1 if i == position: pre.next, temp.next = temp.next, None return
def reverse(self): """ 将链表反转 """ prev = None current = self.head while current: next_node, current.next = current.next, prev prev, current = current, next_node self.head = prev
def initlist(self, data_list): “”“ 将列表转换为链表 ”“” self.head = Node(data_list[0]) temp = self.head for i in data_list[1:]: node = Node(i) temp.next = node temp = temp.next
|
复杂度分析
链表属于常见的一种线性结构,对于插入和移除而言,时间复杂度都为 O(1)
但是对于搜索操作而言,不管从链表的头部还是尾部,都需要遍历 O(n),所以最好复杂度为 O(1),最坏的情况就是从头部遍历到尾部才搜索出对应的元素,所以最坏复杂度为 O(n),平均复杂度为 O(n)。
归纳如下:
- 最好复杂度为 O(1)
- 最坏复杂度为 O(n)
- 平均复杂度为 O(n)
双链表
双向链表(Double_linked_list)也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
这里直接给出参考代码,大家有兴趣请自行探索,这里就不再详细介绍。
具体实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| class Node(object): def __init__(self, item): self.item = item self.next = None self.prev = None
class DLinkList(object): def __init__(self): self._head = None
def is_empty(self): return self._head == None
def get_length(self): cur = self._head count = 0 while cur != None: count = count+1 cur = cur.next return count
def travel(self): cur = self._head while cur != None: print(cur.item) cur = cur.next print("")
def add(self, item): node = Node(item) if self.is_empty(): self._head = node else: node.next = self._head self._head.prev = node 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 node.prev = cur
def search(self, item): cur = self._head while cur != None: if cur.item == item: return True cur = cur.next return False
def insert(self, pos, item): if pos <= 0: self.add(item) elif pos > (self.length()-1): self.append(item) else: node = Node(item) cur = self._head count = 0 while count < (pos-1): count += 1 cur = cur.next node.prev = cur node.next = cur.next cur.next.prev = node cur.next = node
def remove(self, item): if self.is_empty(): return else: cur = self._head if cur.item == item: if cur.next == None: self._head = None else: cur.next.prev = None self._head = cur.next return while cur != None: if cur.item == item: cur.prev.next = cur.next cur.next.prev = cur.prev break cur = cur.next
|
交换单链表里两个链点
在这个实验中,我们要给定两个值,如果这两个值都在单链表的链点中,即交换这两个链点在单链表的位置。
举例:
1->2->3->4->5
input:1 4 output:4->2->3->1->5
目标:
- 交换两个链点在链表中的位置
- 不改变其他链点在链表中的位置
思路:
- 采用 insert 的思想,对于要交换的两个链点 d1 d2,各自声明新的 D1 D2 ,使 D1=d1, D2=d2
- 然后把 然后再根据 d1 d2 的位置,改变索引的位置,即完成交换的全部操作
参考代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| class Node: def __init__(self, data): self.data = data self.next = None
class Linkedlist: def __init__(self): self.head = None
def print_list(self): print("linked_list:") temp = self.head new_list = [] while temp is not None: new_list.append(temp.data) temp = temp.next print(new_list)
def insert(self, new_data): new_node = Node(new_data) new_node.next = self.head self.head = new_node
def swapNodes(self, d1, d2): prevD1 = None prevD2 = None if d1 == d2: return else: D1 = self.head while D1 is not None and D1.data != d1: prevD1 = D1 D1 = D1.next D2 = self.head while D2 is not None and D2.data != d2: prevD2 = D2 D2 = D2.next if D1 is None and D2 is None: return if prevD1 is not None: prevD1.next = D2 else: self.head = D2 if prevD2 is not None: prevD2.next = D1 else: self.head = D1 temp = D1.next D1.next = D2.next D2.next = temp
if __name__ == '__main__': list = Linkedlist() list.insert(5) list.insert(4) list.insert(3) list.insert(2) list.insert(1) list.print_list() list.swapNodes(1, 4) print("After swapping") list.print_list()
|