一,线性数据结构
1.线性数据结构的特点
- 数据项之间只存在先后的次序关系,新的数据项加入到数据集中时,只会加入到原有某个数据项之前或之后
- 线性结构总有两端:左右端、前后端、顶端底端等,但两端的称呼并不是关键,不同线性结构的关键区别在于数据项增减的方式
- 有的结构只允许数据项从一端添加,而有的结构则允许数据项从两端移除
2. 线性数据结构分类
- 栈(stack)
- 队列(queue)
- 双端队列(deque)
- 链表(LinkedList)
二、栈(stack)
1. 栈的特点
- 栈是一种
有次序
的数据项集合,在栈中,数据项的加入和移除
都仅发
生在栈顶
- 后进先出:
Last in First out(LIFO),eg: word 中的 undo
- 反转次序
2. 使用列表来模拟栈
- 假设栈要实现如下功能:
- 代码实现
# 选用 List 的尾端(index=-1)作为栈顶,此时push/pop的复杂度为O(1)
# 若选用 List 的首端(index=0)作为栈顶,其push/pop的复杂度为O(n),因为要用pop(0),insert(0,item)等来模拟出栈和入栈
class Stack:
"""使用 list 来模拟栈"""
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
if not self.isEmpty():
return self.items.pop()
def peek(self):
if not self.isEmpty():
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
s = Stack()
s.isEmpty() = True
s.push(4)
s.push('dog')
s.peek() = 'dog'
s.size() = 2
s.pop() = 'dog'
s.pop() = 4
三、队列(queue)
1. 队列的特点
队列是一种有次序的数据集合,新数据项的添加总发生在尾端(rear),而现存数据项的移除总发生在首端(front)
先进先出:First in First out(FIFO),eg: 打印队列
队列仅有一个入口和一个出口,不允许数据项直接插入队中,也不允许从中
间移除数据项
2. 使用列表来模拟队列
- 假设队列要实现如下功能:
- 代码实践
# 将 list 的首端作为双端队列的尾端,list 的末端作为双端队列的首端
class Deque:
"""使用 list 来模拟双端队列"""
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def addFront(self, item):
self.items.append(item)
def addRear(self, item):
self.items.insert(0,item)
def removeFront(self):
if not self.isEmpty():
return self.items.pop()
def removeRear(self):
if not self.isEmpty():
return self.items.pop(0)
def size(self):
return len(self.items)
d=Deque()
d.addRear(4) = [4]
d.addRear('dog') = ['dog', 4]
d.addFront('cat') = ['dog', 4, 'cat']
d.size() = 3
d.removeRear() # 移除'dog', 还剩[4, 'cat']
d.removeFront() # 移除'cat', 还剩[4]
五、链表(LinkedList)
1. 链表简介
链表是实现了数据之间保持逻辑顺序(通过引用实现),但存储空间不必按顺序的方法
- 链表中的基本要素:
- 节点:每一个节点有两个域,左边部份叫值域,用于存放用户数据;右边叫指针域,一般是存储着到下一个元素的指针(python 中使用引用来实现)
- head 节点:没有值域,只有指针域且永远指向第一个节点
- tail 节点:有值域,有指针域但永远指向 None
- 使用链表的好处
- 插入删除速度很快,不用对整个链表进行调整
- 能够动态的进行存储分配
- 移除链表中某元素示例
2. 使用类来模拟链表(待扩展…)
- 假设链表要实现如下功能:
- 代码实践
# 节点类
class Node:
def __init__(self, init_data):
self.data = init_data
self.next = None
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:
def __init__(self):
self.head = None
def is_empty(self):
return self.head == None
# 从链表头插入对象
def add(self,item):
temp = Node(item)
temp.set_next(self.head) # 将链表头指向的下一个对象的地址赋给待插入对象
self.head = temp # 将待插入对象的地址赋给链表头
# 遍历链表,取得其长度
def size(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.get_next()
return count
# 判断某元素是否在链表中
def search(self,item):
current = self.head
found = False
while current != None and not found:
if current.get_data() == item:
found = True
else:
current = current.get_next()
return found
# 移除链表中的某个元素
def remove(self,item):
current = self.head
previous = None
found = False
while not found:
if current.get_data() == item:
found = True
else:
previous = current
current = current.get_next()
if previous == None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
六、参考资料