链式存储
由于顺序结构逻辑上相邻的元素在存储空间也是相邻的,因此顺序结构的插入和删除需要移动大量元素。
定义 :线性表的链式存储是指通过一组任意的存储单元来存储线性表中的数据元素,为了建立起数据元素之间的线性关系,对每个链表结点除了存放自身的信息外,还需要存放一个执行后继的指针。
"""定义一个单链表结点"""
class Node(object):
def __init__(self, value):
# 数据域
self.value = value
# 指针域
self.__next = None
因为每个结点只有一个指针指向下一个结点,故这种结点组成的线性表也叫单链表。通常用“头指针”来标识一个单链表。
单链表第一个结点之前附加一个结点,称为头结点。头结点的数据域部分可以为空,也可以记录表长等相关信息。头指针指向第一个元素结点。
头结点和头指针的区别:
不管有没有头结点,头指针始终指向链表的第一个结点。而头结点是带有头结点链表中的第一个结点,结点内通常不存储信息,它为了方便做的一种处理。
为什么需要头结点?
- 处理操作方便,对一个元素的插入、删除与其他结点统一。
- 无论链表是否为空,其头指针是指向头结点的非空指针,因此空表和非空表处理也可以统一。
单链表操作
一 插入
1.头插法建表
建立新的结点分配内存空间,将新结点插入到当前链表的表头。
2.尾插法建表
建立新的结点分配空间,将新的结点插入到当前链表的表尾。
二 查找
从单链表第一个结点开始,由前往后依次比较表中各结点数据域的值,若某节点数据域的值等于给定值e,则返回True。若整个单链表中没有这样的结点,则返回False。
三 插入
插入操作是将值为x的新结点插入到单链表的第pos个位置上。先检查插入位置的合法性,然后找到带插入位置的前驱结点,即第pos-1个结点,在其后插入新结点。
算法思路:
- 验证插入位置的合法性
- 找到插入位置的前面一位:pos-1
- 将pos-1的next赋给插入node的next,将node赋给pos-1的next
四 删除
删除操作是将链表的某个数值删除。
算法思路:
- 找到该值所在位置
- 判断是否为头结点,头结点则将头结点指向头结点的next
- 不为头结点,则将前取的next指向当前节点的next
算法实现:
“”“Python实现单链表的增删改查”“”
class SingleList(object):
"""单链表"""
# 初始化
def __init__(self, node=None):
self.__head = node
# 判断是否为空
def is_empty(self):
return self.__head is None
# 链表长度
def length(self):
count = 0
cur = self.__head
if cur.next:
cur = cur.next
count += 1
return count
# 头插法
def add(self, value):
node = Node(value)
node.next = self.__head
self.__head = node
# 尾插法
def append(self, value):
node = Node(value)
cur = self.__head
# 为空节点时
if self.is_empty():
self.__head = node
# 其它情况
else:
# 找到尾结点
while cur.next:
cur = cur.next
cur.next = node
# 查找
def search(self, value):
cur = self.__head
while cur.next:
if cur.value == value:
return True
else:
cur = cur.next
return False
# 插入
def insert(self, pos, value):
# 判断插入位置是否合法
if not isinstance(pos, int): # 判断i是否为整数,不为整数返回错误
raise TypeError
if pos < 0:
self.add(value)
if pos > self.length()-1:
self.append(value)
# 找到插入位置pos-1
count = 0
cur = self.__head
while count < (pos - 1):
count += 1
cur = cur.next
# 退出循环时,cur指向的是pos-1的位置
node = Node(value)
node.next = cur.next
cur.next = node
# 删除
def remove(self, value):
cur = self.__head
prior = None
while cur.next:
if value == cur.value:
# 判断此节点是否是头节点
if cur == self.__head:
self.__head = cur.next
else:
prior.next = cur.next
break
# 还没找到节点,有继续遍历
else:
prior = cur
cur = cur.next