數據結構是以某種形式將數據組織在一塊兒的集合,它不只存儲數據,還支持訪問和處理數據的操做。node
數據的邏輯結構python
1.線性結構:數據元素之間存在一個對一個的關係。算法
2.樹形結構:結構中的數據元素存在一個對多個的關係。數據結構
3.圖形結構或網狀結構:結構中的數據元素存在多個對多個的關係。app
4.集合結構:結構中的數據元素之間除了同屬於一個集合關係外,無其餘數據關係。ide
數據類型,是一個值的集合和定義在此集合上的一組操做的總稱。函數
抽象數據類型,是指一個數學模型以及定義在此數據模型上的一組操做。spa
算法是爲求解一個問題須要遵循的、被清楚指定的簡單指令的集合。設計
一個算法必須知足五個重要特性:有窮性、肯定性、可行性、有輸入、有輸出。3d
設計算法要求:正確性、可讀性、健壯性、效率與低存儲量需求
時間複雜度與大O記法
「大O記法」:對於單調的整數函數f,若是存在一個整數函數g和實常數c>0,使得對於充分大的n總有f(n)<=c*g(n),就說函數g是f的一個漸近函數(忽略常數),記爲f(n)=O(g(n))。也就是說,在趨向無窮的極限意義下,函數f的增加速度受到函數g的約束,亦即函數f與函數g的特徵類似。
時間複雜度:假設存在函數g,使得算法A處理規模爲n的問題示例所用時間爲T(n)=O(g(n)),則稱O(g(n))爲算法A的漸近時間複雜度,簡稱時間複雜度,記爲T(n)
時間複雜度的幾條基本計算規則
常見時間複雜度之間的關係
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) <O(n2logn) < O(n3) < O(2n) < O(n!) < O(nn)
Python list操做
python dict操做
python中的list與tuple兩種類型採用的順序表實現技術。list就是採用分離式技術實現的動態順序表,若將數據區更換爲更大的存儲空間,則能夠不在改變表對象的前提下對其數據區進行擴充,全部使用這個表的地方都沒必要修改 只要在程序的運行環境(計算機系統)還有空間存儲,這種表結構就不會由於滿了而致使操做沒法進行 這種技術實現的順序表稱爲動態順序表
在Python的官方實現中,list實現採用了以下的策略:在創建空表(或者很小的表)時,系統分配一塊能容納8個元素的存儲區;在執行插入操做(insert或append)時,若是元素存儲區滿就換一塊4倍大的存儲區。但若是此時的表已經很大(目前的閥值爲50000),則改變策略,採用加一倍的方法。引入這種改變策略的方式,是爲了不出現過多空閒的存儲位置。
鏈表(linked list)是由一組被稱爲結點的數據元素組成的數據結構,每一個結點都包含結點自己的信息和指向下一個結點的地址。因爲每一個結點都包含了能夠連接起來的地址信息,因此用一個變量就可以訪問整個結點序列。也就是說,結點包含兩部分信息:一部分用於存儲數據元素的值,稱爲信息域;另外一部分用於存儲下一個數據元素地址的指針,稱爲指針域。鏈表中的第一個結點的地址存儲在一個單獨的結點中,稱爲頭結點或首結點。鏈表中的最後一個結點沒有後繼元素,其指針域爲空。
單鏈表的實現
class Node(object): """節點""" def __init__(self,elem): self.elem =elem self.next = None class SingleLinkList(object): """單鏈表""" def __init__(self,node=None): self._head = node def is_empty(self): """判斷是否爲空""" return self._head == None def length(self): """長度""" cur = self._head count = 1 while cur != None: count += 1 cur = cur.next return count def travel(self): """遍歷鏈表""" cur = self._head while cur != None: print(cur.elem,end=',') cur = cur.next print() def add(self,item): """頭部添加""" node =Node(item) node.next = self._head self._head = Node def append(self,item): """尾部添加""" node = Node(item) if self.is_empty(): self._head = node else: cur = self._head while cur.next != None: cur = cur.next cur.next = node def insert(self,pos,item): """指定位置添加""" if pos <= 0: self.add(item) elif pos > self.length()-1: self.append(item) else: pre = self._head count = 0 while count < (pos-1): count+=1 pre = pre.next node = Node(item) node.next = pre.next pre.next = node def remove(self,item): """刪除元素""" cur = self._head pre = None while cur != None: if cur.elem == item: if cur == self._head: self._head = cur.next else: pre.next = cur.next break else: pre = cur cur = cur.next def search(self,item): """判斷元素是否在鏈表中""" cur = self._head while cur != None: if cur.elem == item: return True else: cur = cur.next return False if __name__=="__main__": li = SingleLinkList() print(li.is_empty()) print(li.length()) li.append(1) print(li.is_empty()) print(li.length()) li.append(2) li.append(3) li.insert(2,100) li.travel() li.append(9) li.remove(2) li.travel() print(li.search(100)) 結果: True 1 False 2 1,2,100,3, 1,100,3,9, True
操做 | 鏈表 | 順序表 |
訪問元素 | O(n) | O(1) |
在頭部插入/刪除 | O(1) | O(n) |
在尾部安插入/刪除 | O(n) | O(1) |
在中間插入/刪除 | O(n) | O(n) |
單向循環鏈表:單鏈表的一個變形是單向循環鏈表,鏈表中最後一個節點的next域再也不爲None,而是指向鏈表的頭結點。
class Node: """節點""" def __init__(self, item): self.item = item self.next = None def __str__(self): return str(self.item) class SinCycLinkedList: """單向循環鏈表""" def __init__(self): self._head = None def is_empty(self): """判斷鏈表是否爲空""" return self._head is None def length(self): """鏈表長度""" if self.is_empty(): return 0 count = 1 cur = self._head while cur.next != self._head: # print("cur", cur.item) count += 1 cur = cur.next return count def travel(self): """遍歷""" if self.is_empty(): return cur = self._head print(cur.item) while cur.next != self._head: cur = cur.next print(cur.item) def add(self, item): """在頭部添加一個節點""" node = Node(item) if self.is_empty(): self._head = node node.next = self._head else: node.next = self._head cur = self._head while cur.next != self._head: cur = cur.next cur.next = node self._head = node def append(self, item): """在尾部添加一個節點""" node = Node(item) if self.is_empty(): self._head = node node.next = self._head else: cur = self._head # print(type(cur), cur.item, cur.next) while cur.next != self._head: cur = cur.next # print(cur.item) cur.next = node node.next = self._head def insert(self, pos, item): """指定位置pos添加節點""" if pos <= 0: self.add(item) elif pos > (self.length() - 1): self.append(item) else: node = Node(item) cur = self._head cur_pos = 0 while cur.next != self._head: if (pos - 1) == cur_pos: node.next = cur.next cur.next = node break cur_pos += 1 cur = cur.next def remove(self, item): """刪除一個節點""" if self.is_empty(): return pre = self._head # 刪除首節點 if pre.item == item: cur = pre while cur.next != self._head: cur = cur.next cur.next = pre.next # 刪除首節點(跳過該節點) self._head = pre.next # 從新指定首節點 # 刪除其餘的節點 else: cur = pre while cur.next != self._head: if cur.next.item == item: cur.next = cur.next.next cur = cur.next def search(self, item): """查找節點是否存在""" if self.is_empty(): return -1 cur_pos = 0 cur = self._head if cur.item == item: return cur_pos while cur.next != self._head: if cur.item == item: return cur_pos cur_pos += 1 cur = cur.next if cur_pos == self.length() - 1: return -1 if __name__ == "__main__": ll = SinCycLinkedList() ll.add(1) # 1 ll.add(2) # 2 1 # ll.travel() ll.append(3) # 2 1 3 ll.insert(2, 4) # 2 1 4 3 ll.insert(4, 5) # 2 1 4 3 5 ll.insert(0, 6) # 6 2 1 4 3 5 print("length:", ll.length()) # 6 ll.travel() # 6 2 1 4 3 5 print("search(3)", ll.search(3)) # 4 print("search(7)", ll.search(7)) # -1 print("search(6)", ll.search(6)) # 0 print("remove(1)") ll.remove(1) print("length:", ll.length()) # 6 2 4 3 5 print("remove(6)") ll.remove(6) ll.travel() 結果: length: 6 6 2 1 4 3 5 search(3) 4 search(7) -1 search(6) 0 remove(1) length: 5 remove(6) 2 4 3 5
雙向鏈表:一種更復雜的鏈表是 "雙向鏈表" 或 "雙面鏈表"。每一個節點有兩個連接:一個指向前一個節點,當次節點爲第一個節點時,指向空值;而另外一個指向下一個節點,當此節點爲最後一個節點時,指向空值。
class Node: """節點""" def __init__(self, item): self.item = item self.prev = None self.next = None class DLinkList: """雙向鏈表""" def __init__(self): self._head = None def is_empty(self): """判斷鏈表是否爲空""" return self._head is None def length(self): """獲取鏈表長度""" if self.is_empty(): return 0 else: cur = self._head count = 1 while cur.next is not None: count += 1 cur = cur.next return count def travel(self): """遍歷鏈表""" print("↓↓" * 10) if self.is_empty(): print("") else: cur = self._head print(cur.item) while cur.next is not None: cur = cur.next print(cur.item) print("↑↑" * 10) def add(self, item): """鏈表頭部添加節點""" node = Node(item) if self.is_empty(): self._head = node else: cur = self._head node.next = cur cur.prev = node self._head = node def append(self, item): """鏈表尾部添加節點""" node = Node(item) if self.is_empty(): self._head = node else: cur = self._head # 遍歷找到最後一個節點 while cur.next is not None: cur = cur.next # 在尾節點添加新的節點 cur.next = node node.prev = cur def insert(self, pos, item): """指定位置添加""" # 頭部添加 if pos <= 0: self.add(item) # 尾部添加 elif pos > (self.length() - 1): self.append(item) # 其餘位置添加 else: node = Node(item) cur = self._head cur_pos = 0 while cur.next is not None: if cur_pos == (pos - 1): # 與下一個節點互相指向 node.next = cur.next cur.next.prev = node # 與上一個節點互相指向 cur.next = node node.prev = cur cur_pos += 1 cur = cur.next def remove(self, item): """刪除節點""" if self.is_empty(): return else: cur = self._head # 刪除首節點 if cur.item == item: self._head = cur.next cur.next.prev = None # 刪除其餘節點 else: while cur.next is not None: if cur.item == item: # 刪除以前:1 ←→ [2] ←→ 3 # 刪除以後:1 ←→ 3 cur.prev.next = cur.next cur.next.prev = cur.prev cur = cur.next # 刪除尾節點 if cur.item == item: cur.prev.next = None def search(self, item): """查找節點是否存在""" if self.is_empty(): return -1 else: cur = self._head cur_pos = 0 while cur.next is not None: if cur.item == item: return cur_pos cur_pos += 1 cur = cur.next if cur_pos == (self.length() - 1): return -1 if __name__ == "__main__": ll = DLinkList() ll.add(1) # 1 ll.add(2) # 2 1 ll.append(3) # 2 1 3 ll.insert(2, 4) # 2 1 4 3 ll.insert(4, 5) # 2 1 4 3 5 ll.insert(0, 6) # 6 2 1 4 3 5 print("length:", ll.length()) # 6 ll.travel() # 6 2 1 4 3 5 print("search(3)", ll.search(3)) print("search(4)", ll.search(4)) print("search(10)", ll.search(10)) ll.remove(1) print("length:", ll.length()) ll.travel() print("刪除首節點 remove(6):") ll.remove(6) ll.travel() print("刪除尾節點 remove(5):") ll.remove(5) ll.travel() 結果: length: 6 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 6 2 1 4 3 5 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ search(3) 4 search(4) 3 search(10) -1 length: 5 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 6 2 4 3 5 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 刪除首節點 remove(6): ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 2 4 3 5 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 刪除尾節點 remove(5): ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 2 4 3 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
棧數據結構只容許在一端進行操做,按照後進先出(LIFO,Last In First Out)。
棧結構的實現
# Author:song class Stack(object): """棧""" def __init__(self): self._items = [] def is_empty(self): """判斷是否爲空""" return self._items == [] def push(self,item): """添加新元素到棧頂""" self._items.append(item) def pop(self): """彈出棧頂元素""" self._items.pop() def peek(self): """返回棧頂元素""" if self._items: return self._items[-1] else: return None pass def size(self): pass if __name__=="__main__": s=Stack() print(s.is_empty())
隊列(queue)是隻容許在一端進行插入操做,而在另外一端進行刪除操做的線性表。一種先進先出(FIFO,First In First Out)的線性表
隊列的實現
class Queue: """隊列""" def __init__(self): self.items = [] def is_empty(self): return self.items == [] def enqueue(self, item): """添加元素""" self.items.insert(0, item) def dequeue(self): """從隊列頭部刪除一個元素""" return self.items.pop() def size(self): return len(self.items) if __name__ == "__main__": q = Queue() q.enqueue("hello") q.enqueue("world") q.enqueue("queue") print(q.size()) print(q.dequeue()) # hello print(q.dequeue()) # world print(q.dequeue()) # queue
雙端隊列,是一種具備隊列和棧的性質的數據結構。
class Deque: """雙端隊列""" def __init__(self): self.items = [] def add_front(self, item): """從隊頭加入一個元素""" self.items.insert(0, item) def add_rear(self, item): """從隊尾加入一個元素""" self.items.append(item) def remove_front(self): """從隊頭刪除一個元素""" return self.items.pop(0) def remove_rear(self): """從隊尾刪除一個元素""" return self.items.pop() def is_empty(self): """是否爲空""" return self.items == [] def size(self): """隊列長度""" return len(self.items) if __name__ == "__main__": deque = Deque() deque.add_front(1) deque.add_front(2) deque.add_rear(3) deque.add_rear(4) print(deque.size()) # 4 print(deque.remove_front()) # 2 print(deque.remove_front()) # 1 print(deque.remove_rear()) # 4 print(deque.remove_rear()) # 3