第三章:线性表
线性表(List):零个或多个元素的有限序列。
线性表的基本操作:获取长度、读取元素、插入元素、删除元素
线性边的存储结构:
顺序存储结构:用一段连续的存储单元依次存储线性表的数据元素。
时间复杂度:
- 存、取数据时:O(1)
- 删除、插入数据:O(n)
特点:无需为表示元素间逻辑关系为额外的增加存储空间,可快速存取任意位置元素,但插入和删除操作需要移动大量元素,当线性表长度变化较大时,难以确定存储空间的容量,可能会造成存储空间碎片。
线性表的链式存储结构:
链式存储:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。以结点(Node)来存储映射存储数据元素的信息的数据域(data)和存储逻辑关系的指针域(next)。
节点(Node) = 数据信息 + 指针
单链表:每个结点只包含一个指针。
双链表:每个结点包含两个指针,前驱+后继
头指针与头结点的异同:
- 头指针:是链表指向第一个结点的指针,若链表有结点点则指向头结点的指针;头指针具有标识作用,常以头指针冠以链表名字;无论链表是否为空,头指针均不能为空,头指针是链表的必要元素。
- 头结点:为了操作统一和方便,放在第一个元素的结点之前,其数据域一般无意义;有了头结点对第一个元素结点前插入结点和删除结点则与其他结点操作统一;头结点不是链表的必须要素。
![](https://i-blog.csdnimg.cn/blog_migrate/7ae368a9d05f6cee53c44661e93d13e5.png)
以下是用Python实现链表创建、插入、查询、删除操作:
class Node(object): # 定义一个结点类,有获取数据、指针、设置数据、设置指针的方法
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
def set_next(self, new_next):
self.next = new_next
class LinkedList(object): # 定义一个链表类
def __init__(self):
self.head = Node() # 初始化链表
self.tail = None
self.length = 0
def isEmpty(self): # 判断链表是否为空
return self.head == None
def head_add(self, value): # 在头部添加结点(头插法)
new_node = Node(value, None)
new_node.set_next(self.head)
self.head = new_node
def append(self, value): # 在尾部添加结点
new_node = Node(value)
if self.isEmpty():
self.head = new_node
else:
current = self.head
while current.get_next() != None:
current = current.get_next()
current.set_next(new_node) # 找到链表尾巴并加入新结点
def search(self, value): # 查询值是否在链表中
current = self.head
found_value = False
while current != None and not found_value:
if current.get_data() == value:
found_value = True
else:
current = current.get_next()
return found_value
def get_index(self, value): # 查找值是否在链表内并返回索引位置
current = self.head
count = 0
found = None
while current != None and not found:
count += 1
if current.get_data() == value:
found = True
else:
current = current.get_next()
if found:
return count
else:
print('{} is not in LinkedList'.format(value))
def insert_value(self, location, value): # 在链表中插入结点
if location <= 1:
self.head_add(value)
elif location > self.__sizeof__():
self.append(value)
else:
temp = Node(value)
count = 1
prior = None
current = self.head
while count < location: # 找到插入位置前一个元素位置
count += 1
prior = current
current = current.get_next()
prior.set_next(temp)
temp.set_next(current)
def remove_value(self, value): # 移除指定数据结点
current = self.head
prior = None
while current != None:
if current.get_data() == value:
if not prior:
self.head = current.get_next()
else:
prior.set_next(current.get_next()) # 获取删除元素下一节点并设置给上一结点
break
else:
prior = current # 保存删除元素前一个节点位置
current = current.get_next()
a = Node(10)
b = Node(11)
c = Node(12)
a.set_next(b)
b.set_next(c)
print(a.get_next().get_next().get_data())
list_a = LinkedList()
list_a.append(15)
list_a.append(16)
list_a.append(17)
print(list_a.search(16))
print(list_a.isEmpty())
print(list_a.get_index(11))
链式存储时间复杂度:
- 查询O(n)
- 插入删除O(1)
静态链表(static linked list):
把用数组描述的链表叫做静态链表,数组的元素都是有两个数据域组成data+cur,数组索引即为下一个元素cur。
循环链表(circular linked list):
将单链表的终端结点的指针由空指针改为指向头结点,使整个链表形成一个环。
双向链表(double linked list):
述的链表叫做静态链表,数组的元素都是有两个数据域组成data+cur,数组索引即为下一个元素cur。
循环链表(circular linked list):
将单链表的终端结点的指针由空指针改为指向头结点,使整个链表形成一个环。
双向链表(double linked list):
在单链表的每一个结点中,再设置一个指向前驱结点的指针域,用空间来换取时间。