<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
樹的一些屬性:
1.定義一:樹由節點及連線節點的邊構成。
樹的屬性:
2.定義二:一棵樹要麼為空,要麼由一個根節點和零棵或多棵子樹構成,子樹本身也是一棵樹。
每棵子樹的根節點通過一條邊連到父樹的根節點。
樹的根節點是myTree[0],左子樹是myTree[1],右子樹是myTree[2]。
# 列表函數 def BinaryTree(r): return [r,[],[]] # 根節點r,和兩個作為子節點的空列表 # 插入左子樹 def insertLeft(root,newBranch): t = root.pop(1) if len(t) > 1: root.insert(1,[newBranch,t,[]]) else: root.insert(1,[newBranch,[],[]]) return root ## 插入右子樹 def insertRight(root , newBranch): t = root.pop(2) if len(t) > 1: root.insert(2,[newBranch,[],t]) else: root.insert(2,[newBranch,[],[]]) return root ### 樹的存取函數 def getRootVal(root): return root[0] def setRootVal(root,newVal): root[0] = newVal def getLeftChild(root): return root[1] def getRightChild(root): return root[2] r = BinaryTree(3) insertLeft(r,4) print(r)
定義一個類,其中有根節點和左右子樹的屬性。
class BinaryTree: def __init__(self,rootObj): self.key = rootObj self.leftChild = None self.rightChild = None ## 插入左子節點 def insertLeft(self,newNode): if self.leftChild == None: self.leftChild = BinaryTree(newNode) else: t = BinaryTree(newNode) t.left = self.leftChild self.leftChild = t ## 插入右子節點 def insertRight(self,newNode): if self.rightChild == None: self.rightChild = BinaryTree(newNode) else: t = BinaryTree(newNode) t.right = self.rightChild self.rightChild = t ## 存取函數 def getRightChild(self): return self.rightChild def getLeftChild(self): return self.leftChild def setRootVal(self,obj): self.key = obj def getRootVal(self): return self.key
解析樹構建器:
import operator from pythonds.basic import Stack from pythonds.trees import BinaryTree def buildParseTree(fpexp): fplist = fpexp.split() pStack = Stack() eTree = BinaryTree("") pStack.push(eTree) currentTree = eTree for i in fplist: if i == "(": currentTree.insertLeft("") pStack.push(currentTree) currentTree = currentTree.getLeftChild() elif i not in "+-*/)": currentTree.setRootVal(eval(i)) parent = pStack.pop() currentTree = parent elif i in "+-*/": currentTree.setRootVal(i) currentTree.insertRight("") currentTree = currentTree.getRightChild() elif i == ")": currentTree = pStack.pop() else: raise ValueError("Unkown Operator :" + i ) return eTree ## 計算二叉解析樹的遞迴函數 def evaluate(parseTree): opers = { "+":operator.add,"-":operator.sub, "*":operator.mul,"/":operator.truediv } leftC = parseTree.getLeftChild() rightC = parseTree.getRightChild() if leftC and rightC: fn = opers[parseTree.getRootVal()] return fn(evaluate(leftC),evaluate(rightC)) else: return parseTree.getRootVal()
前序遍歷演演算法實現為外部函數:
def preorder(tree): if tree: print(tree.getRootVal()) preorder(tree.getLeftChild()) preorder(tree.getRightChild)
前序遍歷演演算法實現為BinaryTree類的方法
def preorder(self): print(self.key) if self.leftChild: self.leftChild.preorder() if self.rightChild: self.rightChild.preorder()
後序遍歷函數
def postorder(tree): if tree != None: postorder(tree.getLeftChild()) postorder(tree.getRightChild()) print(tree.getRootVal())
中序遍歷函數
def inorder(tree): if tree != None: inorder(tree.getLeftChild()) print(tree.getRootVal()) inorder(tree.getRightChild())
佇列一個重要的變體 → 優先順序佇列。和佇列一樣,優先順序佇列從頭部移除元素,不過元素的邏輯順序是由優先順序決定的,優先順序最高的元素在最前,最低的元素在最後。
實現優先順序佇列的經典方法 → 二元堆積。入隊和出隊操作均可達到O(logn)
結構屬性:
堆的有序性:對於堆中任意元素x及其父元素p,p都不大於x。
堆操作
程式碼實現:
class EchaDui: # 新建二元堆積 def __init__(self): self.heapList = [0] self.currentSize = 0 def percUp(self,i): while i // 2 > 0: if self.heapList[i] < self.heapList[i // 2]: tmp = self.heapList[i // 2] self.heapList[i // 2] = self.heapList[i] self.heapList[i] = tmp i = i // 2 # 新加元素 def insert(self,k): self.heapList.append(k) self.currentSize = self.currentSize + 1 self.percUp(self.currentSize) def percDown(self,i): while (i * 2) <= self.currentSize: mc = self.minChild(i) if self.heapList[i] > self.heapList[mc]: tmp = self.heapList[i] self.heapList[i] = self.heapList[mc] self.heapList[mc] = tmp i = mc def minChild(self,i): if i * 2 + 1 > self.currentSize: return i * 2 else: if self.heapList[i*2] < self.heapList[i*2 + 1]: return i * 2 else: return i * 2 + 1 ## 從二元堆積中刪除最小的元素 def delMin(self): retval = self.heapList[1] self.heapList[1] = self.heapList[self.currentSize] self.currentSize = self.currentSize - 1 self.heapList.pop() self.percDown(1) return retval ## 根據元素列表構建堆 def builgHeap(self,alist): i = len(alist) // 2 self.currentSize = len(alist) self.heapList = [0] + alist[:] while (i > 0): self.percDown(i) i = i - 1
二元搜尋樹依賴性質:小於父節點的鍵都在左子樹中,大於父節點的鍵則都在右子樹。
程式碼實現:
class BinarySearchTree: def __init__(self): self.root = None self.size = 0 def length(self): return self.size def __len__(self): return self.size def __iter__(self): return self.root.__iter__() # 插入新節點 def put(self,key,val): if self.root: self._put(key,val,self.root) else: self.root = TreeNode(key,val) self.size = self.size + 1 def _put(self,key,val,currentNode): if key < currentNode.key: if currentNode.hasLeftChild(): self._put(key,val,currentNode.leftChild) else: currentNode.leftChild = TreeNode(key,val,parent=currentNode) else: if currentNode.hasRightChild(): self._put(key,val,currentNode.rightChild) else: currentNode.rightChild = TreeNode(key,val,parent=currentNode) def __setitem__(self, key, value): self._put(key,value) ## 查詢鍵對應的值 def get(self,key): if self.root: res = self._get(key,self.root) if res: return res.payload else: return None else: return None def _get(self,key,currentNode): if not currentNode: return None elif currentNode.key == key: return currentNode elif key < currentNode.key: return self._get(key,currentNode.leftChild) else: return self._get(key,currentNode.rightChild) def __getitem__(self, key): return self.get(key) # 檢查樹中是否有某個鍵 def __contains__(self, key): if self._get(key,self.root): return True else: return False # 刪除 def delete(self,key): if self.size > 1: nodeToRemove = self._get(key,self.root) if nodeToRemove: self.remove(nodeToRemove) self.size = self.size - 1 else: raise KeyError("Error,key not in tree") elif self.size == 1 and self.root.key == key: self.root = None self.size = self.size - 1 else: raise KeyError("Error,key not in tree") def __delitem__(self, key): self.delete(key) """ 1. 待刪除節點沒有子節點 2. 待刪除節點只有一個子節點 3. 待刪除節點有兩個子節點 """ # 尋找後繼結點 def findSuccessor(self): succ = None if self.hasRightChild(): succ = self.rightChild.findMin() else: if self.parent: if self.isLeftChild(): succ = self.parent else: self.parent.rightChild = None succ = self.parent.findSuccessor() self.parent.rightChild = self return succ def findMin(self): current = self while current.hasLeftChild(): current = current.leftChild return current def spliceOut(self): if self.isLeaf(): if self.isLeftChild(): self.parent.leftChild = None else: self.parent.rightChild = None elif self.hasAnyChildren(): if self.hasLeftChild(): if self.isLeftChild(): self.parent.leftChild = self.leftChild else: self.parent.rightChild = self.leftChild self.leftChild.parent = self.parent else: if self.isLeftChild(): self.parent.leftChild = self.rightChild else: self.parent.rightChild = self.rightChild self.rightChild.parent = self.parent def remove(self,currentNode): if currentNode.isLeaf(): if currentNode == currentNode.parent.leftChild: currentNode.parent.leftChild = None else: currentNode.parent.rightChild = None elif currentNode.hasBothChildren(): succ = currentNode.findSuccessor() succ.spliceOut() currentNode.key = succ.key currentNode.payload = succ.payload else: if currentNode.hasLeftChild(): if currentNode.isLeftChild(): currentNode.leftChild.parent = currentNode.parent currentNode.parent.leftChild = currentNode.leftChild elif currentNode.isRightChild(): currentNode.leftChild.parent = currentNode.parent currentNode.parent.rightChild = currentNode.leftChild else: currentNode.replaceNodeData(currentNode.leftChild.key, currentNode.leftChild.payload, currentNode.leftChild.leftChild, currentNode.leftChild.rightChild ) else: if currentNode.isLeftChild(): currentNode.rightChild.parent = currentNode.parent currentNode.parent.leftChild = currentNode.rightChild elif currentNode.isRightChild(): currentNode.rightChild.parent = currentNode.parent currentNode.parent.rightChild = currentNode.rightChild else: currentNode.replaceNodeData(currentNode.rightChild.key, currentNode.rightChild.payload, currentNode.rightChild.leftChild, currentNode.rightChild.rightChild ) # 二元搜尋樹迭代器 def __iter__(self): if self: if self.hasLeftChild(): for elem in self.leftChild: yield elem yield self.key if self.hasRightChild(): for elem in self.rightChild: yield elem class TreeNode: def __init__(self,key,val,left = None,right = None,parent = None): self.key = key self.payload = val self.leftChild = left self.rightChild = right self.parent = parent def hasLeftChild(self): return self.leftChild def hasRightChild(self): return self.rightChild def isLeftChild(self): return self.parent and self.parent.leftChild == self def isRightChild(self): return self.parent and self.parent.rightChild == self def isRoot(self): return not self.parent def isLeaf(self): return not (self.rightChild or self.leftChild) def hasAnyChildren(self): return self.rightChild or self.leftChild def replaceNodeData(self,key,value,lc,rc): self.key = key self.payload = value self.leftChild = lc self.rightChild = rc if self.hasLeftChild(): self.leftChild.parent = self if self.hasRightChild(): self.rightChild.parent = self
實現AVL樹時,要記錄每個節點的平衡因子。
平衡因子 = 左右子樹的高度之差
→ 保證樹的平衡因子為-1,0,1,可以使得關鍵操作獲得更好的大O效能
#from 第6章樹.二元搜尋樹 import TreeNode def _put(self, key, val, currentNode): if key < currentNode.key: if currentNode.hasLeftchi1d(): self._put(key, val, currentNode.leftChild) else: currentNode.leftChild = TreeNode(key, val,parent=currentNode) self.updateBalance(currentNode.leftChild) else: if currentNode.hasRightChild(): self._put(key, val, currentNode.rightChild) else: currentNode.rightchild - TreeNode(key, val,parent=currentNode) self.updateBalance(currentNode.rightChild) def updateBalance(self, node): if node.balanceFactor > 1 or node.balanceFactor < -1: self.rebalance(node) return if node.parent != None: if node.isLeftChild(): node.parent.balanceFactor += 1 elif node.isRightChild(): node.parent.balanceFactor -= 1 if node.parent.balanceFactor != 0: self.updateBalance(node.parent) # 實現左旋 def rotateLeft (self, rotRoot) : newRoot = rotRoot .rightchild rotRoot .rightChild = newRoot.leftChild if newRoot . leftChild !=None : newRoot . leftChild. parent = rotRoot newRoot.parent =rotRoot.parent if rotRoot .isRoot( ): self.root = newRoot else: if rotRoot .isLeftChild(): rotRoot.parent .leftChild = newRoot else: rotRoot.parent .rightChild = newRoot newRoot . leftChild = rotRoot rotRoot.parent = newRoot rotRoot. balanceFactor = rotRoot . balanceFactor + 1 - min(newRoot . balanceFactor,0) newRoot . balanceFactor = newRoot . balanceFactor + 1 +max(rotRoot . balanceFactor,o ) # 實現再平衡 def rebalance(self, node) : if node. balanceFactor < 0: if node .rightChild .balanceFactor > 0: self.rotateRight (node.rightChild)self.rotateLeft (node) else: self.rotateLeft (node) elif node. balanceFactor > 0 : if node . leftChild. balanceFactor < 0: self.rotateLeft (node. leftChild) self.rotateRight (node) else: self.rotateRight (node) nceFactor + 1 - min(newRoot . balanceFactor,0) newRoot . balanceFactor = newRoot . balanceFactor + 1 +max(rotRoot . balanceFactor,o ) # 實現再平衡 def rebalance(self, node) : if node. balanceFactor < 0: if node .rightChild .balanceFactor > 0: self.rotateRight (node.rightChild)self.rotateLeft (node) else: self.rotateLeft (node) elif node. balanceFactor > 0 : if node . leftChild. balanceFactor < 0: self.rotateLeft (node. leftChild) self.rotateRight (node) else: self.rotateRight (node)
到此這篇關於Python資料結構樹與演演算法分析的文章就介紹到這了,更多相關Python資料結構樹內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45