一、列表/數組
列表(其他語言稱數組)是一種基本數據結構。
1、列表的元素是如何存儲的?
c的數組和python的列表有兩點不同:
(1)數組元素類型要相同,列表元素類型可以不一樣。
python存的不是真實的值而是存的內存地址。
32位機器上一個地址占4個字節,64位機器上一個地址占用8個字節。
(2)數組長度固定,python是長度不夠了就自動開新的內存地址,把原來的內容拷過來。
2、列表基本操作時間復雜度?
append:不考慮python做得復制操作,大概是O(1)
insert:時間復雜度是O(n),在插入后,后面的元素都要往后挪動。
pop\remove:pop最后一個是O(1),寫了參數則是O(n),前面的刪了后,后面的都要往前挪。
二、棧(Stack)
1、棧的定義和特點
棧的定義:棧是一個數據集合,可以理解為只能在一端進行插入或刪除操作的列表。
棧的特點:后進先出(last-in,first-out), 簡稱LIFO表。類似一摞書:
2、棧的概念和基本操作
棧的概念:
棧頂:允許插入和刪除的這一端稱為棧頂。
棧底:另外固定的這一端稱為棧底。
空棧:不含任何元素的棧稱為空棧。
棧的基本操作:
進棧(壓棧):push
出棧:pop
取棧頂:gettop(查看棧頂元素,但不取走) li[-1]
3、棧的python實現
使用一般的列表結構即可實現棧:
-
- 進棧:li.append
- 出棧:li.pop
- 取棧頂:li[-1]
class Stack: """棧""" def __init__(self): self.stack = [] def push(self, element): self.stack.append(element) def pop(self): if len(self.stack) > 0: return self.stack.pop() else: print("棧已經空了") def get_top(self): if len(self.stack) > 0: # 判斷棧是否為空 return self.stack[-1] else: return None stack = Stack() stack.push(1) stack.push(2) stack.push(6) print(stack.pop()) # 6
更簡單的方式實現棧的方法:創建一個列表,只使用append和pop方法進行操作。
4、棧的應用——括號匹配問題
括號匹配問題:給一個字符串,其中包含小括號、中括號、大括號,求該字符串中的括號是否匹配。
例如:
()()[]{} 匹配 ([{()}]) 匹配 []( 不匹配 [(]) 不匹配
代碼實現如下所示:
class Stack: """棧""" def __init__(self): self.stack = [] def push(self, element): self.stack.append(element) def pop(self): if len(self.stack) > 0: return self.stack.pop() else: print("棧已經空了") def get_top(self): if len(self.stack) > 0: # 判斷棧是否為空 return self.stack[-1] else: return None def is_empty(self): """判斷是否為空""" return len(self.stack) == 0 def brace_match(s): """括號匹配""" match = {'}':'{', ']':'[', ')':'('} # 右括號為鍵,左括號為值 stack = Stack() for ch in s: # 獲取一個個字符 if ch in {'(','[','{'}: stack.push(ch) else: # ch in {')',']','}'} if stack.is_empty(): # 如果棧為空 return False elif stack.get_top() == match[ch]: stack.pop() else: # stack.get_top() != match[ch] return False if stack.is_empty(): # 如果棧是空的了 return True else: return False print(brace_match('(){}[{()}]')) # True print(brace_match('(){}[{[(])}]')) # False
三、隊列(Queue)
1、隊列概念
隊列是一個數據集合,僅允許在列表的一端進行插入,另一端進行刪除。
進行插入的一端稱為隊尾(rear),插入動作稱為進隊或入隊。
進行刪除的一端稱為隊頭(front),刪除動作稱為出隊。
隊列的性質:先進先出(First-in,First-out)
2、思考隊列能否用列表簡單實現?
初步設想:列表+兩個下標指針;創建一個列表和兩個變量,front變量指向隊首,rear變量指向隊尾。初始時,front和rear都為0。
進隊操作:元素寫到li[rear]的位置,rear自增1。
出隊操作:返回li[front]的元素,front自減1。
這種實現方式不好,在一次次增減中,前面的大量內存空間都被浪費了。
3、隊列的實現方式——環形隊列
實現方式:取余數運算
注意:隊滿狀態下還空着一個位子,之所以不填上,是為了防止不能判別出來隊到底是空的還是滿的。
環形隊列:當隊尾指針front == Maxsize - 1時,再前進一個位置就自動到0。
- 隊首指針前進1:front = (front + 1) % MaxSize
- 隊尾指針前進1:rear = (rear + 1) % MaxSize
- 隊空條件:rear == front
- 隊滿條件:(rear + 1) % MaxSize == front
4、隊列代碼實現
class Queue: """隊列""" def __init__(self, size=100): self.queue = [0 for _ in range(size)] # 創建固定長的列表作為隊列 self.size = size self.rear = 0 # 隊尾指針 self.front = 0 # 隊首指針 def push(self, element): """進隊""" if not self.is_filled(): self.rear = (self.rear + 1) % self.size # 隊尾指針前進一 self.queue[self.rear] = element # 添加元素 else: raise IndexError("Queue is filled") def pop(self,): """出隊""" if not self.is_empty(): self.front = (self.front + 1) % self.size # 隊首指針前進1 return self.queue[self.front] # 返回新的front值 else: raise IndexError("Queue is empty") # 隊列為空拋出錯誤 def is_empty(self): """判斷隊空""" return self.rear == self.front # 隊空條件:rear == front def is_filled(self): """判斷隊滿""" return (self.rear + 1) % self.size == self.front # 隊滿條件:(rear + 1) % MaxSize == front q = Queue(5) for i in range(4): q.push(i) print(q.is_filled()) # True print(q.pop()) # 0 q.push(3) print(q) # <__main__.Queue object at 0x10401ae48>
5、雙向隊列
雙向隊列的兩端都支持進隊和出隊操作。
雙向隊列的基本操作:隊首進隊/隊首出隊、隊尾進隊/隊尾出隊。
6、python隊列內置模塊
之前學習過的queue是用來保證線程安全的,使用方法:from collections import deque,在collections中有一些數據結構,其中就包含了deque(雙向隊列)。
- 創建隊列:queue = deque(li)
- 進隊:append
- 出隊:popleft
- 雙向隊列隊首進隊:appendleft
- 雙向隊列隊尾進隊:pop
from collections import deque """ deque([iterable[, maxlen]]) 參數:列表、最大隊列 """ # q = deque() # 創建隊列 q = deque([1,2,3], 5) q.append(1) # 隊尾進隊 print(q.popleft()) # 1 隊首出隊 # 用於雙向隊列 q.appendleft(1) # 隊首進隊 q.pop() # 隊尾出隊
可以使用這個內置模塊來模擬一個linux系統的tail命令來讀取文件的最后幾行:
from collections import deque def tail(n): with open('test.txt', 'r') as f: q = deque(f, n) return q for line in tail(5): print(line, end='') """ 23e234 2342352 dfe232 dwwdwewew wedwewf """