數據結構按照其邏輯結構可分爲線性結構、樹結構、圖結構node
class Stack: def __init__(self): self.stack = [] def push(self, element): self.stack.append(element) def pop(self): return self.stack.pop() 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('[{()}(){()}[]({}){}]')) print(brace_match('[]}'))
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 return self.queue[self.front] else: raise IndexError("Queue is empty.") # 判斷隊空 def is_empty(self): return self.rear == self.front # 判斷隊滿 def is_filled(self): return (self.rear + 1) % self.size == self.front q = Queue(5) for i in range(4): q.push(i) print(q.pop()) q.push(4)
from collections import deque # q = deque([1,2,3,4,5], 5) # q.append(6) # 隊尾進隊 # print(q.popleft()) # 隊首出隊 # 用於雙向隊列 # q.appendleft(1) # 隊首進隊 # q.pop() # 隊尾出隊 def tail(n): with open('test.txt', 'r') as f: q = deque(f, n) return q for line in tail(5): print(line, end='')
class Node: def __init__(self, item): self.item = item self.next = None def create_linklist_head(li): head = Node(li[0]) for element in li[1:]: node = Node(element) node.next = head head = node return head def create_linklist_tail(li): head = Node(li[0]) tail = head for element in li[1:]: node = Node(element) tail.next = node tail = node return head def print_linklist(lk): while lk: print(lk.item, end=',') lk = lk.next lk = create_linklist_tail([1,2,3,6,8]) print_linklist(lk)
#單鏈表 class Node(object): def __init__(self, item): self.item = item self.next = None #雙鏈表 class Node(object): def __init__(self, item=None): self.item = item self.next = None self.prior = None
class LinkList: class Node: def __init__(self, item=None): self.item = item self.next = None class LinkListIterator: def __init__(self, node): self.node = node def __next__(self): if self.node: cur_node = self.node self.node = cur_node.next return cur_node.item else: raise StopIteration def __iter__(self): return self def __init__(self, iterable=None): self.head = None self.tail = None if iterable: self.extend(iterable) def append(self, obj): s = LinkList.Node(obj) if not self.head: self.head = s self.tail = s else: self.tail.next = s self.tail = s def extend(self, iterable): for obj in iterable: self.append(obj) def find(self, obj): for n in self: if n == obj: return True else: return False def __iter__(self): return self.LinkListIterator(self.head) def __repr__(self): return "<<"+", ".join(map(str, self))+">>" # 相似於集合的結構 class HashTable: def __init__(self, size=101): self.size = size self.T = [LinkList() for i in range(self.size)] def h(self, k): return k % self.size def insert(self, k): i = self.h(k) if self.find(k): print("Duplicated Insert.") else: self.T[i].append(k) def find(self, k): i = self.h(k) return self.T[i].find(k) ht = HashTable() ht.insert(0) ht.insert(1) ht.insert(3) ht.insert(102) ht.insert(508) #print(",".join(map(str, ht.T))) print(ht.find(203))
class BiTreeNode: def __init__(self, data): self.data = data self.lchild = None self.rchild = None
from collections import deque class BiTreeNode: def __init__(self, data): self.data = data self.lchild = None self.rchild = None a = BiTreeNode('A') b = BiTreeNode('B') c = BiTreeNode('C') d = BiTreeNode('D') e = BiTreeNode('E') f = BiTreeNode('F') g = BiTreeNode('G') e.lchild = a e.rchild = g a.rchild = c c.lchild = b c.rchild = d g.rchild = f root = e #前序遍歷 def pre_order(root): if root: print(root.data, end='') pre_order(root.lchild) pre_order(root.rchild) #EACBDGF #中序遍歷 def in_order(root): if root: in_order(root.lchild)#a print(root.data, end='') in_order(root.rchild) #ABCDEGF #後序遍歷 def post_order(root): if root: post_order(root.lchild) post_order(root.rchild) print(root.data, end='') #BDCAFGE def level_order(root): queue = deque() queue.append(root) while len(queue) > 0: node = queue.popleft() print(node.data,end='') if node.lchild: queue.append(node.lchild) if node.rchild: queue.append(node.rchild) #EAGCFBD pre_order(root) print("") in_order(root) print("") post_order(root) print("") level_order(root) ''' EACBDGF ABCDEGF BDCAFGE EAGCFBD '''
二叉搜索樹:是一顆二叉樹且知足性質:設x是二叉樹的一個節點。若是y是x左子樹的一個節點,那麼y.key ≤ x.key;若是y是x右子樹的一個節點,那麼y.key ≥ x.key.python
AVL樹是一棵自平衡的二叉搜索樹。算法
AVL樹具備如下性質:數據庫
AVL的實現方式:編程
B樹是一棵自平衡的多路搜索樹。經常使用於數據庫的索引。數組
class Node: def __init__(self, name, type='dir'): self.name = name self.type = type #"dir" or "file" self.children = [] self.parent = None # 鏈式存儲 def __repr__(self): return self.name class FileSystemTree: def __init__(self): self.root = Node("/") self.now = self.root def mkdir(self, name): # name 以 / 結尾 if name[-1] != "/": name += "/" node = Node(name) self.now.children.append(node) node.parent = self.now def ls(self): return self.now.children def cd(self, name): # "/var/python/" if name[-1] != "/": name += "/" if name == "../": self.now = self.now.parent return for child in self.now.children: if child.name == name: self.now = child return raise ValueError("invalid dir") tree = FileSystemTree() tree.mkdir("var/") tree.mkdir("bin/") tree.mkdir("usr/") tree.cd("bin/") tree.mkdir("python/") tree.cd("../") print(tree.ls())
from collections import deque class BiTreeNode: def __init__(self, data): self.data = data self.lchild = None # 左孩子 self.rchild = None # 右孩子 a = BiTreeNode("A") b = BiTreeNode("B") c = BiTreeNode("C") d = BiTreeNode("D") e = BiTreeNode("E") f = BiTreeNode("F") g = BiTreeNode("G") e.lchild = a e.rchild = g a.rchild = c c.lchild = b c.rchild = d g.rchild = f root = e def pre_order(root): if root: print(root.data, end=',') pre_order(root.lchild) pre_order(root.rchild) def in_order(root): if root: in_order(root.lchild) print(root.data, end=',') in_order(root.rchild) def post_order(root): if root: post_order(root.lchild) post_order(root.rchild) print(root.data, end=',') def level_order(root): queue = deque() queue.append(root) while len(queue) > 0: # 只要隊不空 node = queue.popleft() print(node.data, end=',') if node.lchild: queue.append(node.lchild) if node.rchild: queue.append(node.rchild) level_order(root)
import random class BiTreeNode: def __init__(self, data): self.data = data self.lchild = None # 左孩子 self.rchild = None # 右孩子 self.parent = None class BST: def __init__(self, li=None): self.root = None if li: for val in li: self.insert_no_rec(val) def insert(self, node, val): if not node: node = BiTreeNode(val) elif val < node.data: node.lchild = self.insert(node.lchild, val) node.lchild.parent = node elif val > node.data: node.rchild = self.insert(node.rchild, val) node.rchild.parent = node return node def insert_no_rec(self, val): p = self.root if not p: # 空樹 self.root = BiTreeNode(val) return while True: if val < p.data: if p.lchild: p = p.lchild else: # 左孩子不存在 p.lchild = BiTreeNode(val) p.lchild.parent = p return elif val > p.data: if p.rchild: p = p.rchild else: p.rchild = BiTreeNode(val) p.rchild.parent = p return else: return def query(self, node, val): if not node: return None if node.data < val: return self.query(node.rchild, val) elif node.data > val: return self.query(node.lchild, val) else: return node def query_no_rec(self, val): p = self.root while p: if p.data < val: p = p.rchild elif p.data > val: p = p.lchild else: return p return None def pre_order(self, root): if root: print(root.data, end=',') self.pre_order(root.lchild) self.pre_order(root.rchild) def in_order(self, root): if root: self.in_order(root.lchild) print(root.data, end=',') self.in_order(root.rchild) def post_order(self, root): if root: self.post_order(root.lchild) self.post_order(root.rchild) print(root.data, end=',') def __remove_node_1(self, node): # 狀況1:node是葉子節點 if not node.parent: self.root = None if node == node.parent.lchild: #node是它父親的左孩子 node.parent.lchild = None else: #右孩子 node.parent.rchild = None def __remove_node_21(self, node): # 狀況2.1:node只有一個左孩子 if not node.parent: # 根節點 self.root = node.lchild node.lchild.parent = None elif node == node.parent.lchild: node.parent.lchild = node.lchild node.lchild.parent = node.parent else: node.parent.rchild = node.lchild node.lchild.parent = node.parent def __remove_node_22(self, node): # 狀況2.2:node只有一個右孩子 if not node.parent: self.root = node.rchild elif node == node.parent.lchild: node.parent.lchild = node.rchild node.rchild.parent = node.parent else: node.parent.rchild = node.rchild node.rchild.parent = node.parent def delete(self, val): if self.root: # 不是空樹 node = self.query_no_rec(val) if not node: # 不存在 return False if not node.lchild and not node.rchild: #1. 葉子節點 self.__remove_node_1(node) elif not node.rchild: # 2.1 只有一個左孩子 self.__remove_node_21(node) elif not node.lchild: # 2.2 只有一個右孩子 self.__remove_node_22(node) else: # 3. 兩個孩子都有 min_node = node.rchild while min_node.lchild: min_node = min_node.lchild node.data = min_node.data # 刪除min_node if min_node.rchild: self.__remove_node_22(min_node) else: self.__remove_node_1(min_node) # # # tree = BST([1,4,2,5,3,8,6,9,7]) # tree.in_order(tree.root) # print("") # # tree.delete(4) # tree.delete(1) # tree.delete(8) # tree.in_order(tree.root)
from bst import BiTreeNode, BST class AVLNode(BiTreeNode): def __init__(self, data): BiTreeNode.__init__(self, data) self.bf = 0 class AVLTree(BST): def __init__(self, li=None): BST.__init__(self, li) def rotate_left(self, p, c): s2 = c.lchild p.rchild = s2 if s2: s2.parent = p c.lchild = p p.parent = c p.bf = 0 c.bf = 0 return c def rotate_right(self, p, c): s2 = c.rchild p.lchild = s2 if s2: s2.parent = p c.rchild = p p.parent = c p.bf = 0 c.bf = 0 return c def rotate_right_left(self, p, c): g = c.lchild s3 = g.rchild c.lchild = s3 if s3: s3.parent = c g.rchild = c c.parent = g s2 = g.lchild p.rchild = s2 if s2: s2.parent = p g.lchild = p p.parent = g # 更新bf if g.bf > 0: p.bf = -1 c.bf = 0 elif g.bf < 0: p.bf = 0 c.bf = 1 else: # 插入的是g p.bf = 0 c.bf = 0 return g def rotate_left_right(self, p, c): g = c.rchild s2 = g.lchild c.rchild = s2 if s2: s2.parent = c g.lchild = c c.parent = g s3 = g.rchild p.lchild = s3 if s3: s3.parent = p g.rchild = p p.parent = g # 更新bf if g.bf < 0: p.bf = 1 c.bf = 0 elif g.bf > 0: p.bf = 0 c.bf = -1 else: p.bf = 0 c.bf = 0 return g def insert_no_rec(self, val): # 1. 和BST同樣,插入 p = self.root if not p: # 空樹 self.root = AVLNode(val) return while True: if val < p.data: if p.lchild: p = p.lchild else: # 左孩子不存在 p.lchild = AVLNode(val) p.lchild.parent = p node = p.lchild # node 存儲的就是插入的節點 break elif val > p.data: if p.rchild: p = p.rchild else: p.rchild = AVLNode(val) p.rchild.parent = p node = p.rchild break else: # val == p.data return # 2. 更新balance factor while node.parent: # node.parent不空 if node.parent.lchild == node: # 傳遞是從左子樹來的,左子樹更沉了 #更新node.parent的bf -= 1 if node.parent.bf < 0: # 原來node.parent.bf == -1, 更新後變成-2 # 作旋轉 # 看node哪邊沉 g = node.parent.parent # 爲了鏈接旋轉以後的子樹 x = node.parent # 旋轉前的子樹的根 if node.bf > 0: n = self.rotate_left_right(node.parent, node) else: n = self.rotate_right(node.parent, node) # 記得:把n和g連起來 elif node.parent.bf > 0: # 原來node.parent.bf = 1,更新以後變成0 node.parent.bf = 0 break else: # 原來node.parent.bf = 0,更新以後變成-1 node.parent.bf = -1 node = node.parent continue else: # 傳遞是從右子樹來的,右子樹更沉了 #更新node.parent.bf += 1 if node.parent.bf > 0: # 原來node.parent.bf == 1, 更新後變成2 # 作旋轉 # 看node哪邊沉 g = node.parent.parent # 爲了鏈接旋轉以後的子樹 x = node.parent # 旋轉前的子樹的根 if node.bf < 0: # node.bf = 1 n = self.rotate_right_left(node.parent, node) else: # node.bf = -1 n = self.rotate_left(node.parent, node) # 記得連起來 elif node.parent.bf < 0: # 原來node.parent.bf = -1,更新以後變成0 node.parent.bf = 0 break else: # 原來node.parent.bf = 0,更新以後變成1 node.parent.bf = 1 node = node.parent continue # 連接旋轉後的子樹 n.parent = g if g: # g不是空 if x == g.lchild: g.lchild = n else: g.rchild = n break else: self.root = n break tree = AVLTree([9,8,7,6,5,4,3,2,1]) tree.pre_order(tree.root) print("") tree.in_order(tree.root)
給一個二維列表,表示迷宮(0表示通道,1表示圍牆)。給出算法,求一條走出迷宮的路徑。數據結構
思路:從上一個節點開始,任意找下一個能走的節點,當找到不能走的節點時,退回到上一個節點,尋找是否有其餘方向的點app
方法:建立一個棧,首先將入口的位置進棧,當棧不空時候循環,獲取棧頂元素,尋找下一個可走的相鄰方塊,若是找不到可走的相鄰方塊,說明當前是死路,進行回溯(將當前的點出棧,查看前面的點是否還有其餘出路),體現深度優先的思想dom
maze = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 0, 0, 0, 1, 0, 1], [1, 0, 0, 1, 0, 0, 0, 1, 0, 1], [1, 0, 0, 0, 0, 1, 1, 0, 0, 1], [1, 0, 1, 1, 1, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 0, 1], [1, 1, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] dirs = [ lambda x,y: (x+1,y), lambda x,y: (x-1,y), lambda x,y: (x,y-1), lambda x,y: (x,y+1) ] def maze_path(x1,y1,x2,y2): stack = [] stack.append((x1, y1)) while(len(stack)>0): curNode = stack[-1] # 當前的節點 if curNode[0] == x2 and curNode[1] == y2: # 走到終點了 for p in stack: print(p) return True # x,y 四個方向 x-1,y; x+1,y; x,y-1; x,y+1 for dir in dirs: nextNode = dir(curNode[0], curNode[1]) # 若是下一個節點能走 if maze[nextNode[0]][nextNode[1]] == 0: stack.append(nextNode) maze[nextNode[0]][nextNode[1]] = 2 # 2表示爲已經走過 break else: maze[nextNode[0]][nextNode[1]] = 2 stack.pop() else: print("沒有路") return False maze_path(1,1,8,8)
思路:從一個節點開始尋找,尋找下面能繼續走的點,繼續尋找直到能找出出口ide
方法:建立一個空隊列,將起點位置入隊,在隊列不空時循環,出隊一次,若是相鄰的位置爲出口,則結束.不然找出4個相鄰方塊中可走的方塊,所有入隊,體現廣度優先的思想
from collections import deque maze = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 0, 0, 0, 1, 0, 1], [1, 0, 0, 1, 0, 0, 0, 1, 0, 1], [1, 0, 0, 0, 0, 1, 1, 0, 0, 1], [1, 0, 1, 1, 1, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0, 0, 0, 0, 1], [1, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1, 0, 1], [1, 1, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] dirs = [ lambda x, y: (x + 1, y), lambda x, y: (x - 1, y), lambda x, y: (x, y - 1), lambda x, y: (x, y + 1) ] def print_r(path): curNode = path[-1] realpath = [] while curNode[2] == -1: realpath.append(curNode[0:2]) curNode = path[curNode[2]] realpath.append(curNode[0:2]) # 起點 realpath.reverse() for node in realpath: print(node) def maze_path_queue(x1, y1, x2, y2): queue = deque() queue.append((x1, y1, -1)) path = [] while len(queue) > 0: curNode = queue.pop() path.append(curNode) if curNode[0] == x2 and curNode[1] == y2: # 終點 print_r(path) return True for dir in dirs: nextNode = dir(curNode[0], curNode[1]) if maze[nextNode[0]][nextNode[1]] == 0: queue.append((nextNode[0], nextNode[1], len(path) - 1)) # 後續節點進隊,記錄哪一個節點帶他來的 maze[nextNode[0]][nextNode[1]] = 2 # 標記爲已經走過 else: print("沒有路") return False maze_path_queue(1, 1, 8, 8)
n我的圍成一個圈,每一個人分別標註爲一、二、...、n,要求從1號從1開始報數,報到k的人出圈,接着下一我的又從1開始報數,如此循環,直到只剩最後一我的時,該人即爲勝利者。例如當n=10,k=4時,依次出列的人分別爲四、八、二、七、三、10,九、一、六、5,則5號位置的人爲勝利者。給定n我的,請你編程計算出最後勝利者標號數。
#n表示總人數,m表示報到的數 def yuesefu_1(n,m): #1.將全部元素放進列表中,並定義初始的下標爲0 people = [i for i in range(1,n+1)] x = 0 #2.在列表不空的時候循環 while len(people) > 0: #3.計算報數的人的下標, # 1,2,3,4,5,6,7,8 報數 # 0,1,2,3,4,5,6,7 下標,每次取出對總人數的餘數就是要找的人 dead_location = (x+(m-1))%len(people) yield people.pop(dead_location) #將找到的人移除出列表 x = dead_location #從移除出去的人的位置上,繼續執行 print(list(yuesefu_1(9,4)))
class LinkList: #自定義鏈表實現類 class Node: def __init__(self,item=None): self.item = item self.next = None class LinkListIterator: def __init__(self,node): self.node = node def __next__(self): if self.node: cur_node = self.node self.node = cur_node.next return cur_node.item def __iter__(self): return self def __init__(self,iteratbe=None): self.head = LinkList.Node(0) self.tail = self.head self.extend(iteratbe) #鏈表添加 def append(self,obj): s = LinkList.Node(obj) self.tail.next = s self.tail = s #鏈表擴展 def extend(self,iterable): for obj in iterable: self.append(obj) self.head.item += len(iterable) def remove_nth_node(self,node,m): #刪除鏈表第n個元素 for i in range(m-2): node = node.next p = node.next node.next = p.next self.head.item -= 1 return p def __iter__(self): return self.LinkListIterator(self.head.next) def __len__(self): return self.head.item def __str__(self): return '<<'+", ".join(map(str,self)) +">>" def yuesefu_link(n,m): people = LinkList([i for i in range(1,n+1)]) people.tail.next = people.head.next x = people.head.next while len(people)>0: p = people.remove_nth_node(x,m) x = p.next yield p.item print(list(yuesefu_link(9,4)))