01. 单链表基础与构造方法
1.1 实现
(1)根据面向对象的理论实现
class ListNode:
def __init__(self, data):
self.data = data
self.next = None
def get_data(self):
return self.data
def set_data(self, data):
self.data = data
def get_next(self):
return self.next
def set_next(self, next):
self.next = next
(2)在算法题中的实现
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
listnode = ListNode(1)
1.2 遍历链表
从头开始逐个向后访问,操作后找到表头十分重要
(1)链表长度和遍历
def length(self):
"""链表长度"""
current = self._head
count = 0
while current != None:
count += 1
current = current.next
return count
def items(self):
"""遍历链表"""
current = self._head
while current is not None:
yield current.value
current = current.next
(2)判空比较
对于空的判定,存在两种方法,!=
和 is not
通过以下测试发现
# 比对 is not 和 != 的比较速度
import time
test_head = None
time_1 = time.time()
for idx in range(100000):
if test_head != None:
continue
time_2 = time.time()
print(time_2 - time_1)
time_3 = time.time()
for idx in range(100000):
if test_head is not None:
continue
time_4 = time.time()
print(time_4 - time_3)
运行后的结果,进过多次测验,发现is not
的速度更快
1.3 链表插入
(1)在链表的表头插入
- 创建新节点newNode
- 连接到原来的链表上,newNode.next = head
- 从newNode开始一路向下,head = newNode
def add(self, value):
"""向链表头部添加元素"""
new_node = Node(value)
if self.is_empty():
self._head = new_node
else:
current = self._head
while current.next is not None:
current = current.next
current.next = new_node
(2)在中间插入
在目标结点的前一个位置停下来(使用cur.next的值来判断,而不是cur)
def append(self, value):
"""尾部添加元素"""
new_node = Node(value)
if self.is_empty():
self._head = new_node
else:
current = self._head
while current.next is not None:
current = current.next
current.next = new_node
(3)结尾插入
将尾结点指向新节点
def insert(self, pos, value):
"""指定位置添加元素"""
# 若指定位置pos为第一个元素之前,则执行头部插入
if pos <= 0:
self.add(value)
# 若指定位置超过链表尾部,则执行尾部插入
elif pos > (self.length() - 1):
self.append(value)
# 找到指定位置
else:
new_node = Node(value)
# pre用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
pre = self._head
for _ in range(pos - 1):
pre = pre.next
# 先将新节点node的next指向插入位置的节点
new_node.next = pre.next
# 将插入位置的前一个节点的next指向新节点
pre.next = new_node
1.4 删除
(1)头节点
head = head.next
(2)最后
判断cur.next是否等于最后值
如果是,cur.next=null
(3)中间
cur.next的值更新为cur.next.next
def remove(self, value):
"""删除节点"""
cur = self._head
pre = None
while cur is not None:
# 找到了指定元素
if cur.value == value:
# 如果第一个就是删除的节点
if not pre:
# 将头指针指向头节点的后一个节点
self._head = cur.next
else:
# 将删除位置前一个节点的next指向删除位置的后一个节点
pre.next = cur.next
break
else:
# 继续按链表后移节点
pre = cur
cur = cur.next
1.5 查找
def find(self, value):
"""查找元素是否存在"""
return value in self.items()
1.6 全部代码及测试
(1)全部代码
class Node():
"""定义结点"""
def __init__(self, value):
self.value = value
self.next = None
class SingleLinkList:
"""定义链表(单向链表)"""
def __init__(self):
self._head = None
def is_empty(self):
return self._head is None
def length(self):
"""链表长度"""
current = self._head
count = 0
while current is not None:
count += 1
current = current.next
return count
def items(self):
"""遍历链表"""
current = self._head
while current is not None:
yield current.value
current = current.next
def add(self, value):
"""向链表头部添加元素"""
new_node = Node(value)
if self.is_empty():
self._head = new_node
else:
current = self._head
while current.next is not None:
current = current.next
current.next = new_node
def append(self, value):
"""尾部添加元素"""
new_node = Node(value)
if self.is_empty():
self._head = new_node
else:
current = self._head
while current.next is not None:
current = current.next
current.next = new_node
def insert(self, pos, value):
"""指定位置添加元素"""
# 若指定位置pos为第一个元素之前,则执行头部插入
if pos <= 0:
self.add(value)
# 若指定位置超过链表尾部,则执行尾部插入
elif pos > (self.length() - 1):
self.append(value)
# 找到指定位置
else:
new_node = Node(value)
# pre用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
pre = self._head
for _ in range(pos - 1):
pre = pre.next
# 先将新节点node的next指向插入位置的节点
new_node.next = pre.next
# 将插入位置的前一个节点的next指向新节点
pre.next = new_node
def remove(self, value):
"""删除节点"""
cur = self._head
pre = None
while cur is not None:
# 找到了指定元素
if cur.value == value:
# 如果第一个就是删除的节点
if not pre:
# 将头指针指向头节点的后一个节点
self._head = cur.next
else:
# 将删除位置前一个节点的next指向删除位置的后一个节点
pre.next = cur.next
break
else:
# 继续按链表后移节点
pre = cur
cur = cur.next
def find(self, value):
"""查找元素是否存在"""
return value in self.items()
(2)测试
# 测试内容
link_list = SingleLinkList()
node1 = Node(1)
node2 = Node(2)
link_list._head = node1
node1.next = node2
print(link_list._head.value)
print(link_list._head.next.value)
print(link_list.is_empty())
print(link_list.length())
for i in range(7):
link_list.append(i)
link_list.add(10)
print(link_list.length())
print(list(link_list.items()))
link_list.insert(3, 20)
print(list(link_list.items()))
print(link_list.find(10))
link_list.remove(2)
print(list(link_list.items()))
02. 双向链表设计
2.1 基本功能
(1)创建结点
class Node():
# 初始化
def __init__(self, value):
self.value = value
self.next = None
self.pre = None
(2) 判空,长度和遍历
def is_empty(self):
"""判断链表是否为空"""
return self._head is None
def length(self):
"""链表长度"""
count = 0
current = self._head
while current is not None:
count = count + 1
current = current.next
return count
def items(self):
"""遍历链表"""
current = self._head
while current is not None:
yield current.value
current = current.next
2.2 添加元素
def add(self, value):
"""向链表头部添加元素"""
new_node = Node(value)
# 链表为空时
if self._head is None:
# 头部结点指针修改为新结点
self._head = new_node
else:
# 新节点指向原来的头部节点
new_node.next = self._head
# 原来头部节点pre指向新节点
self._head.pre = new_node
# head指向新节点
self._head = new_node
def append(self, value):
"""尾部添加元素"""
new_node = Node(value)
if self._head is None:
# 头部结点指针修改为新结点
self._head = new_node
else:
current = self._head
while current.next is not None:
current = current.next
current.next = new_node
new_node.pre = current
def insert(self, index, value):
"""指定位置插入元素"""
if index <= 0: # 指定位置小于等于0,头部添加
self.add(value)
elif index > self.length()-1:
self.append(value)
else:
current = self._head
new_node = Node(value)
for _ in range(index-1):
current = current.next
# 新节点的前一个节点指向当前节点的上一个节点
new_node.pre = current.pre
# 新节点的下一个节点指向当前节点
new_node.next = current
# 当前节点的上一个节点指向新节点
current.pre.next = new_node
# 当前结点的向上指针指向新结点
current.pre = new_node
2.3 删除元素
def remove(self, value):
"""删除节点"""
if self.is_empty():
return
current = self._head
# 删除的元素为第一个元素
if current.value == value:
# 链表中只有一个元素
if current.next is None:
self._head = None
return True
else:
self._head = current.next
current.next.pre = None
return True
while current.next is not None:
if current.value == value:
current.pre.next = current.next
current.next.pre = current.pre
return True
current = current.next
# 删除元素在最后一个
if current.value == value:
current.pre.next = None
return True
2.4 全部代码和测试
class Node():
# 初始化
def __init__(self, value):
self.value = value
self.next = None
self.pre = None
class BilateralLinkList():
"""定义链表(单向链表)"""
def __init__(self):
self._head = None
def is_empty(self):
"""判断链表是否为空"""
return self._head is None
def length(self):
"""链表长度"""
count = 0
current = self._head
while current is not None:
count = count + 1
current = current.next
return count
def items(self):
"""遍历链表"""
current = self._head
while current is not None:
yield current.value
current = current.next
def add(self, value):
"""向链表头部添加元素"""
new_node = Node(value)
# 链表为空时
if self._head is None:
# 头部结点指针修改为新结点
self._head = new_node
else:
# 新节点指向原来的头部节点
new_node.next = self._head
# 原来头部节点pre指向新节点
self._head.pre = new_node
# head指向新节点
self._head = new_node
def append(self, value):
"""尾部添加元素"""
new_node = Node(value)
if self._head is None:
# 头部结点指针修改为新结点
self._head = new_node
else:
current = self._head
while current.next is not None:
current = current.next
current.next = new_node
new_node.pre = current
def insert(self, index, value):
"""指定位置插入元素"""
if index <= 0: # 指定位置小于等于0,头部添加
self.add(value)
elif index > self.length()-1:
self.append(value)
else:
current = self._head
new_node = Node(value)
for _ in range(index-1):
current = current.next
# 新节点的前一个节点指向当前节点的上一个节点
new_node.pre = current.pre
# 新节点的下一个节点指向当前节点
new_node.next = current
# 当前节点的上一个节点指向新节点
current.pre.next = new_node
# 当前结点的向上指针指向新结点
current.pre = new_node
def remove(self, value):
"""删除节点"""
if self.is_empty():
return
current = self._head
# 删除的元素为第一个元素
if current.value == value:
# 链表中只有一个元素
if current.next is None:
self._head = None
return True
else:
self._head = current.next
current.next.pre = None
return True
while current.next is not None:
if current.value == value:
current.pre.next = current.next
current.next.pre = current.pre
return True![在这里插入图片描述](https://img-blog.csdnimg.cn/f33ea437de0844dea069bb899196d6fd.png#pic_center)
current = current.next
# 删除元素在最后一个
if current.value == value:
current.pre.next = None
return True
def find(self, value):
"""查找元素是否存在"""
return value in self.items()
测试内容
link_list = BilateralLinkList()
print(link_list.is_empty())
print(link_list.length())
link_list.add(10)
print(link_list.is_empty())
link_list.add(20)
link_list.add(1)
link_list.add(0)
print(list(link_list.items()))
for i in range(2, 9):
link_list.append(i)
print(list(link_list.items()))
print(link_list.find(10))
link_list.remove(0)
print(list(link_list.items()))
link_list.remove(3)
print(list(link_list.items()))
link_list.remove(8)
print(list(link_list.items()))
引用和参考内容:
- https://zhuanlan.zhihu.com/p/259833481