链表
为什么需要链表?
因为在我们的计算机中内存空间不一定是连续的,而顺序表是一整块连续的内存空间,这样就不够灵活,还会造成内存的浪费。
链表的定义
链表是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址)。
链表的分类
- 单向链表
- 双向链表
- 单向循环链表
单向链表
单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含了两个域,一个信息域和一个链接域
结点的实现
class Node(object):
"""结点的实现"""
def __init__(self):
self.item = item # 存放元素
self.next = None # next 是指向下一个节点的标识
单链表的操作
- is_empty() 链表是否为空
- length() 链表长度
- travel() 遍历整个链表
- add(item) 链表头部添加元素
- append(item) 链表尾部添加元素
- insert(pos, item) 指定位置添加元素
- remove(item) 删除节点
- search(item) 查找节点是否存在
class SingleLinkList(object):
"""单向链表"""
def __init__(self, none=None):
self._head = None
def is_empty(self):
"""链表是否为空"""
return self._head == None
travel / length
def length(self):
"""链表长度"""
count = 0 # 记录列表长度的count
cur = self.__head # 游标
while cur != None:
cur = cur.next # 游标右移
count += 1
# cur == None 表示指向到最后一个节点的next区域
reutnr count
def travel(self):
"""遍历链表"""
cur = self.__head
while cur != None:
print(cur.itme, end='')
cur = cur.next
print("")
def add(self, item):
"""链表头部添加元素"""
# 创建新结点
node = Node(item)
# 新结点的next指向旧的头结点
node.next = self.__head
# 头指针指向新的结点
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 == None cur指向最后一个结点
# 最后一个结点next指向新的结点
cur.next = node
node.next = None
def insert(self, pos, item):
"""指定位置添加元素"""
# 头部添加
if pos <= 0:
self.add(item)
# 尾部添加
elif pos >= self.length():
self.append(item)
# 指定pos位置添加元素
else:
# 新结点
node = Node(item)
# 计数
count = 0
# 游标
cur = self.__head
# 寻找pos前一个结点
while count < (pos - 1):
cur = cur.next
count += 1
# count == pos -1 cur游标指向pos结点的前一个结点
# 新结点next指向pos位置的结点
node.next = cur.next
# pos前一个结点的next指向新结点
cur.next = node
def remove(self, item):
"""链表删除指定item的元素"""
# 游标
cur = self.__head
# cur的前一个游标
pre = None
while cur != None:
# 找到了要删除的元素
if cur.item == item:
# 1.要删除的元素是头结点
if cur == self.__head:
# 头指针指向1号结点
self.__head = cur.next
# 2.要删除的元素不是头结点
else:
pre.next = cur.next
return
else:
# 在cur移动之前将值赋值pre 形成一前一后的关系
pre = cur
# 游标右移动
cur = cur.next
def search(self, item):
"""判断传入的元素是否在链表内 bool"""
cur = self.__head
while cur != None:
# 表示传入的元素找到了
if cur.item == item:
return True
else:
# 循环未退出 继续移动比较
cur = cur.next
# 循环退出了还未找到
return False
双向链表
操作
- is_empty() 链表是否为空
- length() 链表长度
- travel() 遍历链表
- add(item) 链表头部添加
- append(item) 链表尾部添加
- insert(pos, item) 指定位置添加
- remove(item) 删除节点
- search(item) 查找节点是否存在
单向循环链表
单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。
操作
- is_empty() 判断链表是否为空
- length() 返回链表的长度
- travel() 遍历
- add(item) 在头部添加一个节点
- append(item) 在尾部添加一个节点
- insert(pos, item) 在指定位置pos添加节点
- remove(item) 删除一个节点
- search(item) 查找节点是否存在