1、Python 基本資料結構
阿新 • • 發佈:2019-02-13
一、線性資料結構
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 Queue:
"""使用 list 來模擬佇列"""
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def enqueue(self, item):
self.items.insert(0, item)
def dequeue(self):
if not self.isEmpty():
return self.items.pop()
def size(self):
return len(self.items)
q=Queue()
q.enqueue(4) = [4]
q.enqueue('dog') = ['dog', 4]
q.size() = 2
q.isEmpty() = False
q.dequeue() # 4 出隊,list 中還剩['dog']
四、雙端佇列(deque)
1. 雙端佇列的特點
- 雙端佇列是一種
有次序
的資料集,其首端和尾端
都可以加入資料和移除資料 - 某種意義上說,雙端佇列集成了棧和佇列的能力,但雙端佇列並不具有內在的
LIFO
或者FIFO
特性,如果用雙端佇列來模擬棧或佇列,需要由使用者自行維護操作的一致性
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())