数据结构按照其逻辑结构可分为线性结构、树结构、图结构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)))