链表
1. 什么是链表
链表(Linked List):一种线性表数据结构。它使用一组任意的存储单元(可以是连续的,也可以是不连续的),来存储一组具有相同类型的数据。即「链表」 是实现线性表的链式存储结构的基础。
1. 单链表
每个数据元素占用若干存储单元的组合称为一个「链节点」,还存放一个指出这个数据元素在逻辑关系上的直接后继元素所在链节点的地址,该地址被称为「后继指针 next」
2. 双向链表
链表的一种,也叫做双链表。它的每个链节点中有两个指针,分别指向直接后继和直接前驱
3. 循环链表
链表的一种。它的最后一个链节点指向头节点,形成一个环
2. 单链表
1. 链表的创建、头尾插入和遍历
# 创建链表 class Link: def __init__(self, item): self.item = item self.next = None # 头插法插入数据: 头改变 def head_insert(li): head = Link(li[0]) # 第一个定为head for element in li[1:]: link = Link(element) # 插入链表 link.next = head # 链表的next指向当前的head head = link # head指向新插入的元素 return head # 尾插法插入数据: 头不变,tail改变 def tail_insert(li): head = Link(li[0]) # 指定head tail = head # 指定tail,即尾部,只有一个时,head等于tail for element in li[1:]: link = Link(element) # 插入数据 tail.next = link # 尾部的next指向插入的数据 tail = link # 尾部指向插入的元素 return head # 链表遍历 def print_link(lk): while lk: print(lk.item, end=' ') lk = lk.next # 等价于link.next.next.item,next的数量看元素的个数 a = head_insert([1, 2, 3, 5, 7, 9]) print_link(a)
2. 单链表的中间插入
代码实现:
# 中间插入数据 def center_insert(index, val): count = 0 # 定义一个计数器,用来判断插入的指针位置 head = tail_insert([1, 2, 3, 5, 7, 9]) # 调用函数插入数据 curNode = head # curNode指向插入的位置,初始值为第0个 while curNode and count < index - 1: count += 1 curNode = curNode.next # 循环多少次,就叠加多少个next node = Link(val) # 插入元素 node.next = curNode.next # 插入元素的next指向当前插入位置的下一个元素,即尾巴相连 curNode.next = node # 当前位置的为前一个元素的next,即头部相连 return head
3. 单链表的删除
代码实现:
# 删除链表头部 def del_head(): head = tail_insert([1, 2, 3, 5, 7, 9]) # 插入链表数据 if head: # 存在则将head指向他的下一个元素 head = head.next return head # 从链表中间删除元素 def del_center(index): head = tail_insert([1, 2, 3, 5, 7, 9]) # 插入链表数据 count = 0 curNode = head while curNode and count < index - 1: count += 1 curNode = curNode.next curNode.next = curNode.next.next # 删除元素的前一个元素的next跳过删除的元素,指向删除元素的后一个元素 return head
3. 双向链表
# 构建节点类 class Node: def __init__(self, item): self.item = item self.next = None # 尾指向 self.previous = None # 头指向 # 构建双向链表类 class DoubleLink: def __init__(self, node=None): self._head = node # 指定头元素 # 判断链表是否为空 def is_empty(self): return self._head is None # 输出链表的长度 def length(self): count = 0 if self.is_empty(): # 为空直接返回0 return count else: cur = self._head while cur is not None: # cur.next不为None,进行计算 count += 1 cur = cur.next return count # 遍历链表 def traver(self): cur = self._head # 确定头元素 while cur is not None: print(cur.item,end=' ') cur = cur.next # 头插法插入元素 def add_head(self,item): node = Node(item) # 链表为空时 if self.is_empty(): self._head = node # 链表不为空时 else: node.next = self._head # 插入元素的next为初始头元素 self._head.previous = node # 初始头元素的previous为插入元素 self._head = node # 更新头元素为插入元素 # 尾插法插入元素 def add_end(self,item): node = Node(item) # 插入元素 # 链表为空时,插入元素为头元素 if self.is_empty(): self._head = node # 链表不为空时 else: cur = self._head # 构建一个移动指针 while cur.next is not None: # 当指针指向元素不是最后一个元素时,一直移动 cur = cur.next cur.next = node # 最后一个元素的next指向插入元素 node.previous = cur # 插入元素的previous指向指针指向的元素 # 在中间从插入元素 def insert(self,index,val): node = Node(val) cur = self._head # 移动指针 count = 0 # 计数器 while cur and count < index - 1: # 确定指针的指向,即插入位置的前一个 count += 1 cur = cur.next node.previous = cur # 插入元素的previous指向指针的位置 node.next = cur.next # 插入元素的next指向原来指针指向的next元素 cur.next.previous = node # 指针位置的后一个元素的previous指向插入元素 cur.next = node # 指针位置的元素的next指向插入元素 # 查找元素 def search(self, val): cur = self._head found = False # 状态初始为False # 条件为不是最后一个元素和found不是True就一直查询 while cur is not None and not found: if cur.item == val: found = True else: cur = cur.next return found # 删除指定元素 def remove_element(self,val): cur = self._head # 空表时 if self.is_empty(): return "链表中没有元素!" # 删除元素为链表首元素时 elif cur.item == val: cur.next.previous = None # 将指针指向元素的previous指向None self._head = cur.next # 将头元素更新为指针元素的下一个元素 # 当删除不是首元素时 else: while cur is not None and cur.item != val: cur = cur.next # 移动指针 # 当cur.next为None时,说明不存在这个数 if cur is None: print(f"{val}不存在!") # 当删除元素为最后一个元素时 elif cur.next is None: cur.previous.next = None # 将最后一个元素的previous即前一个元素的next指向None # 当删除元素在链表中间时 else: cur.previous.next = cur.next # 删除元素的前一个元素的next指向删除元素的next cur.next.previous = cur.previous # 删除元素的后一个元素的previous指向删除元素的previous # 删除指定位置 def remove_index(self,index): cur = self._head # 移动指针 count = 0 # 计数器 # 删除头节点 if index == 0: cur.next.previous = None # 则首元素的下一个元素的previous指向None self._head = cur.next # 更新头元素 # 删除尾节点 elif index == self.length()-1: # 链表长度减1即尾节点 # 用计数器来确定指针位置 while cur and count < self.length()-1: count += 1 cur = cur.next cur.previous.next = None # 将尾元素的上一个元素的next指向None # 删除中间位置 else: while cur and count < index: # 确定指针指向删除元素 count += 1 cur = cur.next cur.previous.next = cur.next # 删除元素的前一个元素的next指向删除元素的next cur.next.previous = cur.previous # 删除元素的后一个元素的previous指向删除元素的previous