1. 程式人生 > >1、Python 基本資料結構

1、Python 基本資料結構

一、線性資料結構

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())

六、參考資料