更新、更全的《數據結構與算法》的更新網站,更有python、go、人工智能教學等着你:http://www.javashuo.com/article/p-zfinzipt-hh.htmlnode
二叉搜索樹是一種特殊的二叉樹,在必定程度上是基於二分查找思想產生的,在它的任何一個節點node處,node的左子樹中的全部元素都比node自己的數值要小,而node的右子樹中的全部元素都比node自己要大。python
與普通的二叉樹不一樣,任意給一串不重複的數字,就能夠肯定一棵二叉搜索樹,例如:當給定序列12,5,11,17,16,19,18時,能夠肯定的二叉搜索樹以下:算法
本質上,因爲二叉搜索樹的節點左右按大小分界的性質,肯定一棵二叉搜索樹最重要的仍是序列中數字出現的次序,一個小小的調換就可能致使二叉搜索樹改變,所以,有時候咱們須要找到一些方法來確認兩個序列所對應的二叉搜索樹是否爲同一棵二叉搜索樹。數據結構
咱們以最簡單的例子,由1,2,3構成的6種序列,及其對應的二叉搜索樹、先序、中序、後序、層序遍歷結果分別以下:app
咱們可能會天然地想到用遍歷對兩顆二叉搜索樹進行比較,經常使用的遍歷方法:
先序遍歷、中序遍歷、後序遍歷、層序遍歷
下面咱們將分點探討他們的效果。函數
中序遍歷老是先遍歷當前節點node的左子節點,而後遍歷自身元素、以後遍歷右子節點。於是,在二叉搜索樹中,中序遍歷的結果老是全部元素的升序排列(如上表中標紅的一行所示);換句話說,中序遍歷結果是不能幫助咱們判斷兩個序列是否對應同一棵二叉搜索樹的。網站
根據一個先序遍歷結果(不妨仍以上面的那棵二叉搜索樹爲例,其先序遍歷結果是12,5,11,17,16,19,18),從根節點12開始,根據與12的大小關係,12後面的5和11確定在左子樹中,而17,16,19,18確定在12的右子樹中;在5和11中,根據順序,5應做爲12左子樹的根節點,而後11比5大,因此11是5的右子節點,這樣左子樹判斷完畢;在左子樹17,16,19,18中,17是根節點,16是17的左子節點、19和18是17的右子樹,其中19是17的右子節點,18是19的左子節點。這樣咱們就完成了整個二叉搜索樹的構建。人工智能
整合一下,咱們看到,在二叉搜索樹的概念下,先序遍歷的結果能夠逐步「二分」,分紅比node小和比node大的兩部分,分別構成node的左右子樹;而後以相同的思路進行二分,便可完成構建。code
後序遍歷與先序遍歷本質上同樣,只是在邏輯上進行了徹底翻轉(注意不是簡單的序列翻轉),思路和先序遍歷基本相同,仍然須要遞歸分組,只是須要從遍歷結果的最後一個元素開始反向構建。
由前述分析討論可見,在二叉搜索樹的概念之下,中序遍歷損失的信息量是最大的,但因爲它獲得的結果的升序特性,這是咱們能夠用它來判斷一棵二叉樹是不是二叉搜索樹,這是其餘幾種遍歷沒法作到的,這也表示了中序遍歷與二叉搜索樹結合得很緊密。
而層序、先序、後序遍歷均可以用來判斷兩個給定序列是否爲同一棵二叉搜索樹(這裏以先序遍歷結果實現以下)。
# python語言實現 # Judge the same binary search tree # 因爲二叉搜索樹不一樣於二叉樹,僅根據二叉搜索樹的先序遍歷結果就能斷定二叉樹的惟一形狀; # 所以咱們能夠經過比較兩個二叉搜索樹的先序遍歷結果來判斷他們是否爲同一個二叉搜索樹; class node: def __init__(self, elem=None, lchild=None, rchild=None): self.elem = elem self.lchild = lchild self.rchild = rchild class tree: def __init__(self, root=node()): self.root = root def bi_search_tree_establish(List): # 根據輸入的列表創建二叉搜索樹 if List: mytree = tree(node(List[0])) for i in range(1, len(List)): temp_node = mytree.root while temp_node: if List[i] < temp_node.elem: if temp_node.lchild: temp_node = temp_node.lchild else: temp_node.lchild = node(List[i]) break else: if temp_node.rchild: temp_node = temp_node.rchild else: temp_node.rchild = node(List[i]) break return mytree else: return None def preorder_probing(now_node, pre_L): # 先序遍歷——遞歸實現 # print(now_node.elem) pre_L.append(now_node.elem) if now_node.lchild: preorder_probing(now_node.lchild, pre_L) if now_node.rchild: preorder_probing(now_node.rchild, pre_L) def cmp(a, b): # 比較序列函數,Python3的經常使用函數庫裏已經沒有cmp函數了 leng = len(a) if leng == len(b): for i in range(0, leng): if a[i] != b[i]: # print("False") return -1 # print("True") return 0 else: # print("False") return -1 if __name__ == "__main__": N = int(input()) # 輸入n表示須要檢測的組數 S_List = [int(i) for i in input()] # 輸入一個二叉搜索樹序列做爲標準,與下面的進行比較 S_Tree = bi_search_tree_establish(S_List) # 構建標準二叉搜索樹 if S_Tree: S_pre_list = [] preorder_probing(S_Tree.root, S_pre_list) for i in range(0, N): List = [int(i) for i in input()] # 輸入待比較的二叉搜索樹序列 MyTree = bi_search_tree_establish(List) # 構建待比較二叉搜索樹 if MyTree: pre_list = [] preorder_probing(MyTree.root, pre_list) if cmp(S_pre_list, pre_list) == 0: print("YES") else: print("NO")