线性结构是一种有序数据项的集合,其中每个数据项都有唯一的前驱和后继。除了第一个没有前驱,最后一个没有后继,
新的数据项加入到数据集中时,只会加入到原有某个数据项之前或之后,具有这种性质的数据集,就称为线性结构。
顺序表和链表是两种最基本的线性表(数据)结构。顺序表是指采用顺序存储的方式来存储数据元素的线性表,它通常在内存中开辟一段连续的存储空间,将结点依次存放在这组地址连续的存储空间中。因为存储空间连续且每个数据元素占用的空间相同,所以可计算得出每结点元素的存储地址,使元素索引取值(或赋值)的时间复杂度减小至 O(1)。链表是指采用链式结构来存储数据元素的线性表,它通常在每个结点创建时主动向系统申请一个本结点的存储空间,并通过指针来链接各个包含数据元素的结点。链表中元素的逻辑顺序是由指针的链接次序决定的,与存储空间的物理位置无关,因此使用时仅能被顺序存取,其元素索引取值(或赋值)的时间复杂度为 O(n)。
编程开发中,常用的线性结构有栈(Stack)、 队列(Queue)、双端队列(Deque)和列表(List)四种。他们的区别在于数据项增减的方式,且都有基于顺序表或链表的两种不同实现方式,具体对比如下表所示:
栈(Stack)是一个有次序的数据集,每个数据项仅从“栈顶”一端加入到数据集中、从数据集中移除,栈具有后进先出LIFO的特性。
栈(Stack)定义的操作如下:
代码实现:
# 栈
class Stack(object):
"""
Stack():创建一个空栈,不包含任何数据项
push(item):将item加入栈顶,无返回值
pop():将栈顶数据项移除,并返回,栈被修改
peek():“窥视”栈顶数据项,返回栈顶的数据项但不移除,栈不被修改
isEmpty():返回栈是否为空栈 size():返回栈中有多少个数据项
"""
def __init__(self):
super().__init__()
self.stack = []
def push(self, item):
self.stack.append(item)
def pop(self):
return self.stack.pop()
def peek(self):
return self.stack[-1]
def isEmpty(self):
return self.stack==[]
队列(Queue)是一个有次序的数据集合,数据项仅添加到“尾rear”端,而且仅从“首front”端移除;Queue具有FIFO的操作次序。
队列(Queue)定义的操作如下:
代码实现:
# 队列
class Queue(object):
"""
queue():创建一个空队列对象,返回值为Queue对象
enqueue(item):将数据项item添加到队尾,无返回值
dequeue():从队首移除数据项,返回值为队首数据项,队列被修改
isEmpty():测试是否空队列,返回值为布尔值
size():返回队列中数据项的个数
"""
def __init__(self):
super().__init__()
self.queue = []
def enqueue(self, item):
self.queue.append(item)
def dequeue(self):
""" 时间复杂度:O(n) """
return self.queue.pop(0)
def isEmpty(self):
return self.queue==[]
def size(self):
return len(self.queue)
优先队列(Priority Queue)是一种特殊的队列结构,其出队规则跟队列一样,都从队首出队;但在优先队列内部,数据项的次序却是由“优先级”来确定,即:高优先级的数据项排在队首,而低优先级的数据项则排在后面。
这样,优先队列的入队操作就比较复杂,需要将数据项根据其优先级尽量挤到队列前方;实现优先队列的经典方案是采用二叉堆数据结构,二叉堆能够将优先队列的入队和出队复杂度都保持在 O(log n)。新数据项入队后,根据优先级“上浮”(二叉堆的新增结点方法中的一步操作)到对应位置;最高优先级数据项出队后,通过“下沉”(二叉堆的移出最值项方法中的一步操作),次高优先级数据项排列到队列首位。
代码实现:
双端队列(Deque)是一种有次序的数据集,跟队列相似,其两端可以称作“首”“尾”端;但deque中数据项既可以从队首加入,也可以从队尾加入,且数据项也可以从两端移除。
某种意义上说,双端队列集成了栈和队列的能力。但双端队列并不具有内在的LIFO或者FIFO特性,如果用双端队列来模拟栈或队列,需要由使用者自行维护操作的一致性。
双端队列(Deque)定义的操作如下:
代码实现:
# 双端队列
class Deque(object):
""""
Deque():创建一个空双端队列
addFront(item):将item加入队首
addRear(item):将item加入队尾
removeFront():从队首移除数据项,返回值为移除的数据项
removeRear():从队尾移除数据项,返回值为移除的数据项
isEmpty():返回deque是否为空 size():返回deque中包含数据项的个数
"""
def __init__(self):
super().__init__()
self.deque = []
def addFront(self, item):
""" 时间复杂度:O(n) """
self.deque.insert(0, item)
def addRear(self, item):
self.deque.append(item)
def removeFront(self):
""" 时间复杂度:O(n) """
return self.deque.pop(0)
def removeRear(self):
return self.deque.pop()
def isEmpty(self):
return self.deque==[]
列表可分为无序列表和有序列表,无序列表(Unordered List)是一种数据项按照相对位置存放的数据集,其中数据项只按照存放位置来索引,与各项数据间的大小关系无关;有序列表(Ordered List)是一种数据项依照其某可比性质(如整数大小、字母表先后)来决定其在列表中位置的数据集,越“小”的数据项越靠近列表的头(越靠“前”)。
列表一般是无序列表(使用有序列表时,名称前半部分的有序二字不应省略),在Python语言中,内置列表(list)数据类型已很好地实现了基于顺序表的无序列表数据结构,一般我们可直接使用。下文中,我们进一步简述基于(单向)链表实现的无序列表和有序列表数据结构。
无序列表(Unordered List)定义的操作如下:
基于链表的无序列表代码实现:
# 链表结点
class SingleNode(object):
"""
创建单链表的一个结点
"""
def __init__(self, data, next_node=None):
super().__init__()
self.data = data
self.next_node = next_node
# 列表
class List(object):
"""
List():创建一个空列表
add(item):从头部添加一个数据项到列表中
remove(item):从列表中移除item,列表被修改
search(item):在列表中查找item,返回布尔类型值
isEmpty():返回列表是否为空
size():返回列表包含了多少数据项
append(item):添加一个数据项到表末尾
index(item):返回数据项在表中的位置
insert(pos, item):将数据项插入到位置pos
pop(pos):默认从列表开头移除数据项,若给定pos,则移除该位置为的数据项
"""
def __init__(self, alist=None):
super().__init__()
self.head = None
self.size = 0
if alist is not None:
for item in alist:
self.append(item)
def append(self, item):
"""添加一个数据项到表末尾,时间复杂度是 O(1)"""
temp_node = SingleNode(item)
temp_node.next_node = self.head
self.head = temp_node
self.size += 1
def remove(self, item):
"""从列表中移除item,列表被修改,时间复杂度是 O(n)"""
#
if self.isEmpty():
print('list is Empty')
return False
# 列表非空
pre_node = None
cur_node = self.head
while cur_node is not None:
if cur_node.data == item:
if pre_node is None:
"""当先结点是链首结点"""
self.head = cur_node.next_node
else:
"""当先结点非链首结点"""
pre_node.next_node = cur_node.next_node
self.size -= 1
return True
else:
cur_node = cur_node.next_node
print("This item is' not in list")
def search(self, item):
"""
在列表中查找item,返回布尔类型值;
仅能实现顺序查找,时间复杂度是 O(n)
"""
cur_node = self.head
while cur_node:
if cur_node.data == item:
return True
else:
cur_node = cur_node.next_node
return False
def isEmpty(self):
"""返回列表是否为空"""
return self.head is None
def _size(self):
"""
可顺序遍历每结点后得出,时间复杂度是 O(n)
或在类中添加一个属性来保存列表大小,时间复杂度是 O(1)
"""
# cur_node = self.head
# n = 0
# while cur_node is not None:
# n += 1
# cur_node = cur_node.next_node
# return n
return self.size
def index(self, item):
"""返回数据项在表中的位置,时间复杂度是 O(n)"""
cur_node = self.head
n = 0
while cur_node:
if cur_node.data == item:
return self.size - 1 - n
else:
cur_node = cur_node.next_node
n += 1
print("This item is' not in list")
def insert(self, pos, item):
"""将数据项插入到位置pos,时间复杂度是 O(n)"""
if pos == self.size:
"""尾插"""
self.append(item)
self.size += 1
elif 0 <= pos < self.size:
cur_node = self.head.next_node
for i in range(self.size-1, -1, -1):
if i == pos:
temp = SingleNode(item)
temp.next_node = cur_node.next_node
cur_node.next_node = temp
self.size += 1
else:
cur_node = cur_node.next_node
else:
raise IndexError('list index out of range')
def pop(self, pos=None):
"""
默认从列表开头移除数据项,时间复杂度是 O(1);
若给定pos,则移除该位置为的数据项 ,时间复杂度是 O(n)
"""
if self.isEmpty():
print('list is Empty')
return False
#
if pos is None:
temp = self.head
self.head = self.head.next_node
self.size -= 1
return temp.data
elif pos == self.size - 1:
"""尾删"""
temp = self.head
self.head = temp.next_node
self.size -= 1
return temp.data
elif 0 <= pos < self.size - 1:
pre_node = self.head
cur_node = self.head.next_node
for i in range(self.size-2, -1, -1):
if i == pos:
pre_node.next_node = cur_node.next_node
self.size -= 1
return cur_node.data
else:
pre_node = cur_node
cur_node = cur_node.next_node
else:
raise IndexError('list index out of range')
# test
temp = List([1, 4, 5, 6])
有序列表(Ordered List)定义的操作如下:
代码实现:
class OrderedList(List):
"""
append(item):在表中添加一个数据项,并保持整体顺序
remove(item):从有序表中移除一个数据项,此项应存在
search(item):在有序表中查找数据项,返回是否存在
isEmpty():是否空表
_size():返回表中数据项的个数
index(item):返回数据项在表中的位置
pop(pos):默认从列表开头移除数据项,若给定pos,则移除该位置为的数据项
"""
def __init__(self, alist=None):
super().__init__(alist)
def append(self, item):
if self.isEmpty():
"""添加一个数据项到表末尾,时间复杂度是 O(1)"""
temp_node = SingleNode(item)
temp_node.next_node = self.head
self.head = temp_node
self.size += 1
return True
elif self.head.data < item:
temp = SingleNode(item)
temp.next_node = self.head
self.head = temp
self.size += 1
return True
else:
pre_node = self.head
cur_node = self.head.next_node
while cur_node is not None:
if cur_node.data < item:
temp = SingleNode(item)
temp.next_node = cur_node
pre_node.next_node = temp
self.size += 1
return True
else:
pre_node = cur_node
cur_node = cur_node.next_node
return False
def insert(self, pos, item):
print('无效方法')
# test
temp = OrderedList([1, 5, 3, 7, 10, 15])