c++编写算法判断二叉树是否为完全二叉树_[校招-算法题] 二叉树基础算法1
二叉樹是面試中??嫉臄祿Y構,因為涉及大量指針操作,因此可以考察思維的嚴謹性和靈活性。但是校招中的二叉樹題規律性很強,因此需要總結一下。
各種常見的二叉樹概念
二叉樹:每個結點最多有兩個子樹(左子樹和右子樹)的樹結構。
節點的層次:一個結點的層次直觀上來說就是其所在的行,其中根結點層次為1。
二叉樹的深度:二叉樹的深度指二叉樹的最大葉子結點所在的層。二叉樹的深度求解可用遞歸方式實現,等于max(左子樹深度,右子樹深度)+1。
結點的度:二叉樹結點的度指該結點分支的個數,取值為0、1或2。
結點種類:
- 根結點:第一層的結點
- 葉子結點:度為0的結點
- 分支結點:度不為0的結點
- 孩子結點:結點的子樹的根稱為該結點的孩子結點
- 兄弟結點:同一雙親的孩子結點
- 祖先結點:從根到該結點上所經分支的所有結點
- 子孫節點:以某結點為根的子樹中任一結點都稱為該結點的子孫節點
建立一棵二叉樹
class Node:"""節點類"""def __init__(self, value=None, left=None, right=None):self.val = valueself.left = leftself.right = rightclass Tree:"""樹類"""def __init__(self):self.root = Node()self.queue = []def add(self, val):"""為樹添加節點"""node = Node(value=val)if self.root.val is None: # 如果樹是空的,則對根節點賦值self.root = nodeself.queue.append(self.root)else:treeNode = self.queue[0] # 此節點的子樹還沒有齊if treeNode.left is None:treeNode.left = nodeself.queue.append(treeNode.left)else:treeNode.right = nodeself.queue.append(treeNode.right)self.queue.pop(0) # 如果該節點存在左右子樹,將此節點丟棄if __name__ == '__main__':vals = range(10) # 生成十個數據作為樹節點tree = Tree() # 新建一個樹對象for val in vals:tree.add(val) # 逐個添加樹的節點代碼構造的二叉樹二叉樹的分類
滿二叉樹:除葉結點外每一個結點都有左右子結點并且葉子結點都處在最底層的二叉樹。
完全二叉樹:除最后一層外,其他各層的結點數都達到最大,最后一層的葉子結點都是從左往右依次排布。
二叉排序樹(BST):或者是一棵空樹,或者具有如下性質:(1)若左子樹不為空,則左子樹上所有結點的值均小于它的根結點的值;(2)若右子樹不為空,則右子樹上所有結點的值均大于它的根結點的值;(3)左右子樹也分別為二叉排序樹;(4)沒有值相等的結點。
平衡二叉樹(AVL):一種二叉排序樹,其中每個結點的左子樹和右子樹的高度差至多等于1。要么它是一棵空樹,要么它的左子樹和右子樹都是平衡二叉樹,且左子樹和右子樹的深度之差的絕對值不超過1。
二叉樹的遍歷
二叉樹最重要的是四種遍歷算法:前序遍歷(遞歸和非遞歸)、中序遍歷(遞歸和非遞歸)、后序遍歷(遞歸和非遞歸)和層次遍歷。
前序遍歷(根左右)
先訪問根結點,然后訪問左子樹,再訪問右子樹。
遞歸算法:
def pre_order(root):if root:print(root.val, end=" ")pre_order(root.left)pre_order(root.right)非遞歸算法:
使用棧來臨時存儲節點:(1)打印根結點數據;(2)把根結點的right入棧,遍歷左子樹;(3)遍歷完左子樹返回時,棧頂元素應為right,出棧,遍歷以該結點為根的子樹
def pre_order_stack(root):p = roots = [] # stackwhile p or s:while p:print(p.val, end=" ")s.append(p.right)p = p.leftif s: # 注意這里是if,不是whilep = s.pop(-1)中序遍歷(左根右)
遞歸算法:
def in_order(root):if root:in_order(root.left)print(root.val, end=" ")in_order(root.right)非遞歸算法:
使用棧來存儲臨時節點,(1)先將根節點入棧,遍歷左子樹;(2)遍歷完左子樹返回時,棧頂元素應為根節點,此時出棧,并打印節點數據;(3)再中序遍歷右子樹。
def in_order_stack(root):p = roots = [] # stackwhile p or s:while p:s.append(p)p = p.leftif s:p = s.pop(-1)print(p.val, end=" ")p = p.right后序遍歷(左右根)
遞歸算法:
def post_order(root):if root:post_order(root.left)post_order(root.right)print(root.val, end=" ")非遞歸算法:
使用棧來存儲臨時節點,使用哈希表來記錄狀態。
假設root時遍歷樹的根指針,后序遍歷要求在遍歷完左、右子樹后再訪問根,需要判斷根結點的左、右子樹是否均遍歷過。使用標記法,節點入棧時,將該結點存入哈希表,值為0表示遍歷左子樹前的現場保護,值為1表示遍歷右子樹前的現場保護。
首先將root,遍歷左子樹;返回后,修改哈希表中該結點的值為1,遍歷右子樹,最后訪問根節點。
def post_order_stack(root):p = roots = [] # stackd = {}while p or s:while p:s.append(p)d[p] = 0p = p.leftif s:p = s[-1]if d[p] == 1: # 如果該結點的右子樹遍歷過了,則打印該結點的值print(p.val, end=" ")s.pop(-1)p = Noneelse:d[p] = 1p = p.right層次遍歷
層次遍歷需要使用一個輔助隊列,初始元素是根結點。當隊列不為空時,每次打印隊列最前端結點的值,然后判斷該結點左子結點是否存在,存在就壓入隊列;再判斷該結點右子節點是否存在,存在就壓入隊列。
def level_order(root):if root is None:return Nonemy_queue = [root]node = rootwhile my_queue:node = my_queue.pop(0)print(node.val, end=" ")if node.left:my_queue.append(node.left)if node.right:my_queue.append(node.right)二叉樹遍歷的應用
分層打印二叉樹
在層次遍歷的基礎上,使用兩個額外的變量分別保存當前層需要打印的結點數和下一層的結點數。
def level_print(root):if root is None:return Nonemy_queue = [root]node = rootto_be_printed = 1next_level = 0while my_queue:node = my_queue.pop(0)if to_be_printed:print(node.val, end=" ")to_be_printed -= 1else:to_be_printed = next_levelnext_level = 0print()print(node.val, end=" ")to_be_printed -= 1if node.left:my_queue.append(node.left)next_level += 1if node.right:my_queue.append(node.right)next_level += 1之字形打印二叉樹
def level_print2(root):"""之字形打印二叉樹,在分行打印的基礎上添加一個記錄本層順序的值,之前打印的地方換成壓到一個列表"""if root is None:return Nonemy_queue = []node = rootmy_queue.append(node)to_be_printed = 1next_level_num = 0all = [[], ]level_num = 0while my_queue:node = my_queue.pop(0)if to_be_printed > 0:# print(node.elem, end=" ")all[level_num].append(node.val)to_be_printed -= 1else:print()to_be_printed = next_level_numnext_level_num = 0level_num += 1all.append([])all[level_num].append(node.val)to_be_printed -= 1if node.left is not None:my_queue.append(node.left)next_level_num += 1if node.right is not None:my_queue.append(node.right)next_level_num += 1for i in range(len(all)):if i % 2 == 0:for j in all[i]:print(j, end=" ")if i != len(all) - 1:print()else:all[i].reverse()for j in all[i]:print(j, end=" ")if i != len(all) - 1:print()判斷二叉樹是否為完全二叉樹
算法:
總結
以上是生活随笔為你收集整理的c++编写算法判断二叉树是否为完全二叉树_[校招-算法题] 二叉树基础算法1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: basler相机参数简要中文说明_你知道
- 下一篇: jni直接转byte_JNI再探之JNI