我们为了解决问题,需要将数据保存下来,然后根据数据的存储方式来设计算法实现进行处理,那么数据的存储方式不同就会导致需要不同的算法进行处理。我们希望算法解决问题的效率越快越好,于是我们就需要考虑数据究竟如何保存的问题,这就是数据结构。
算法与数据结构的区别 数据结构指数据对象中数据元素之间的关系。 高效的程序需要在数据结构的基础上设计和选择算法。
程序 = 数据结构 + 算法 总结:算法是为了解决实际问题而设计的,数据结构是算法需要处理的问题载体
链表定义 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址)。
单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
表元素域elem用来存放具体的数据。
链接域next用来存放下一个节点的位置(python中的标识)
变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 """ 节点的实现 class SingleNode(object): # 单链表的节点 def __init__(self,item): # _item存放数据元素 self.item = item # _next是下一个节点的标识 self.next = None # python中等号的意思为 将变量指向某个地址 比如 a=10 将a指向了存放10的地址 比如109323281251 # next = 下一个节点的标识 就是将next指向了下一个节点的地址 # !!! 做到了单链表的 [元素][next]——[元素][next] """ class Node(object): """节点""" def __init__(self, elem): self.elem = elem self.next = None
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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 """ 单链表的操作: is_empty() 链表是否为空 length() 链表长度 travel() 遍历整个链表 add(item) 链表头部添加元素 append(item) 链表尾部添加元素 insert(pos, item) 指定位置添加元素 remove(item) 删除节点 search(item) 查找节点是否存在 """ class singleLinkList(object): """单链表""" def __init__(self, node=None): self._head = node def is_empty(self): """链表是否为空""" return self._head == None def length(self): """返回链表长度""" # cur用来遍历节点 cur = self._head # cur = self._head = node # 所以后面循环中 会有 cur = cur.next = node.next 把游标cur 移到下一个节点 # count用来计数 count = 0 while cur != None: cur = cur.next count += 1 # 把游标 cur 指向第一个节点 如果第一个节点不是None 计数+1 return count def travel(self): """遍历整个列表""" cur = self._head while cur != None: print(cur.elem, end=" ") cur = cur.next print(' ') def add(self, elem): """链表头部添加元素""" node = Node(elem) self._head, node.next = node, self._head def append(self, elem): """链表尾部添加元素""" # cur = self._head # while cur != None: # cur = cur.next # cur.elem = elem # cur.next = None # 当cur = None的时候说明已经到了最后一个节点的Next 空节点 # cur指向空节点 在空节点上创建Node 就是添加元素 个人理解 node = Node(elem) 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, elem): """指定位置添加元素""" if pos <= 0: self.add(elem) elif pos > (self.length() - 1): self.append(elem) else: cur = self._head i = 1 node = Node(elem) while i < pos: i += 1 cur = cur.next # 当循环退出后 cur找到前一个节点 node.next = cur.next cur.next = node def remove(self, elem): """移除指定元素""" """还需要加个是否为空的判断""" # cur = self._head # # 如果第一节点就是要删除的元素 那么直接让self._head指向第二节点 # if cur.elem == elem: # self._head = cur.next # # 现在第一位不是要删除的了 # # 那么假设 cur指向第一节点 behind指向第二节点 只要behind.elem是要删除的元素 # # 就让cur.next指向 behind.next就可以实现第一节点指向第三节点 丢弃第二节点 # # 实现删除功能 # else: # behind = cur.next # while behind != None: # if behind.elem == elem: # cur.next = behind.next # # cur = behind # behind = cur.next cur = self._head pre = None while cur != None: # 判断元素 if cur.elem == elem: # 判断是否头节点 if cur == self._head: self._head = cur.next else: pre.next = cur.next break else: pre = cur cur = cur.next def search(self, elem): """查询指定元素""" cur = self._head while cur != None: if cur.elem == elem: print('存在') break else: cur = cur.next return False if __name__ == "__main__": ll = singleLinkList() print(ll.is_empty()) print(ll.length()) ll.append(3) ll.append(4) ll.add(2) ll.add(1) # 1 2 3 4 ll.insert(1, 100) ll.travel() # 1 100 2 3 4 ll.insert(3, 200) # 1 100 2 200 3 4 ll.travel() ll.remove(4) ll.travel()
双向链表 一种更复杂的链表是“双向链表”或“双面链表”。每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值;而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。
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 132 133 134 135 136 137 138 139 140 141 142 143 class Node(object): def __init__(self, elem): self.elem = elem self.next = None self.prev = None class DoubleLinkList(object): """双向链表""" def __init__(self, node=None): self._head = node def is_empty(self): """链表是否为空""" return self._head is None def length(self): """返回链表长度""" # cur用来遍历节点 cur = self._head # cur = self._head = node # 所以后面循环中 会有 cur = cur.next = node.next 把游标cur 移到下一个节点 # count用来计数 count = 0 while cur is not None: cur = cur.next count += 1 # 把游标 cur 指向第一个节点 如果第一个节点不是None 计数+1 return count def travel(self): """遍历整个列表""" cur = self._head while cur is not None: print(cur.elem, end=" ") cur = cur.next print(' ') def add(self, elem): """链表头部添加元素""" node = Node(elem) if self.is_empty(): self._head = node else: node.next = self._head self._head.prev = node self._head = node def append(self, elem): """链表尾部添加元素""" node = Node(elem) if self.is_empty(): # 如果链表是空,就是直接添加节点 self._head = node else: cur = self._head while cur.next is not None: cur = cur.next cur.next = node node.prev = cur def insert(self, pos, elem): """指定位置添加元素""" if pos <= 0: self.add(elem) elif pos > (self.length() - 1): self.append(elem) else: cur = self._head i = 1 node = Node(elem) while i < pos: i += 1 cur = cur.next # 当循环退出后 cur找到前一个节点 # node指向cur的下一个节点 node.next = cur.next # cur下一个节点的头指向node cur.next.prev = node # cur指向node cur.next = node # node的头指向cur node.prev = cur def remove(self, elem): """移除指定元素""" """还需要加个是否为空的判断""" cur = self._head pre = None while cur is not None: # 判断元素 if cur.elem == elem: # 判断是否头节点 if cur == self._head: if cur.next is None: self._head = None else: cur.next.prev = None self._head = cur.next else: pre.next = cur.next cur.next.prev = pre break else: pre = cur cur = cur.next def search(self, elem): """查询指定元素""" cur = self._head while cur is not None: if cur.elem == elem: print('存在') break else: cur = cur.next return False if __name__ == '__main__': dl = DoubleLinkList() dl.add(2) dl.add(1) dl.append(3) dl.append(4) dl.travel() # 1 2 3 4 dl.insert(1, 100) dl.travel() # 1 100 2 3 4 dl.insert(3, 200) dl.travel() # 1 100 2 200 3 4 dl.remove(200) dl.travel() # 1 100 2 3 4 dl.remove(100) dl.travel() # 1 2 3 4
单向循环链表 单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。
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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 class Node(object): """节点""" def __init__(self, elem): self.elem = elem self.next = None class SingleCircleLinkList(object): """单向循环链表""" def __init__(self, node=None): self._head = node def is_empty(self): """链表是否为空""" return self._head is None def length(self): """返回链表长度""" if self._head is None: return 0 count = 1 cur = self._head while cur.next is not self._head: cur = cur.next count += 1 return count def travel(self): """遍历整个列表""" if self.is_empty(): return cur = self._head print(cur.elem) while cur.next is not self._head: cur = cur.next print(cur.elem) print(' ') def add(self, elem): """链表头部添加元素""" node = Node(elem) # 如果没有节点 头指向node node.next指向自己 if self.is_empty(): self._head = node node.next = self._head # 如果有节点存在 node.next指向头 尾部.next指向node else: cur = self._head node.next = self._head while cur.next is not self._head: cur = cur.next cur.next = node self._head = node def append(self, elem): """链表尾部添加元素""" node = Node(elem) if self.is_empty(): # 如果链表是空,就是直接添加节点 self._head = node node.next = self._head else: cur = self._head while cur.next is not self._head: cur = cur.next cur.next = node node.next = self._head def insert(self, pos, elem): """指定位置添加元素""" if pos <= 0: self.add(elem) elif pos > (self.length() - 1): self.append(elem) else: node = Node(elem) cur = self._head count = 0 # 移动到指定位置的前一个位置 while count < (pos - 1): count += 1 cur = cur.next node.next = cur.next cur.next = node def remove(self, elem): """移除指定元素""" """还需要加个是否为空的判断""" if self.is_empty(): return cur = self._head pre = None # 判断是否是头部 if cur.elem is elem: # 判断链表是否只有一个节点 if cur.next is self._head: self._head = None # 不止一个节点 else: # pre = self._head while cur.next is not self._head: cur = cur.next cur.next = self._head.next self._head = self._head.next # 不是头部 else: pre = self._head while cur.next is not self._head: if cur.elem is elem: pre.next = cur.next return else: pre = cur cur = cur.next def search(self, elem): """查询指定元素""" cur = self._head while cur is not None: if cur.elem == elem: print('存在') break else: cur = cur.next return False if __name__ == '__main__': dl = SingleCircleLinkList() dl.add(2) dl.add(1) dl.append(3) dl.append(4) dl.travel() # 1 2 3 4 dl.insert(1, 100) dl.travel() # 1 100 2 3 4 dl.insert(3, 200) dl.travel() # 1 100 2 200 3 4 dl.remove(200) dl.travel() # 1 100 2 3 4 dl.remove(100) dl.travel() # 1 2 3 4