小白專場-是否同一顆二叉搜索樹-python語言實現

更新、更全的《數據結構與算法》的更新網站,更有python、go、人工智能教學等着你:http://www.javashuo.com/article/p-zfinzipt-hh.htmlnode

1、二叉搜索樹的相同判斷

二叉搜索樹是一種特殊的二叉樹,在必定程度上是基於二分查找思想產生的,在它的任何一個節點node處,node的左子樹中的全部元素都比node自己的數值要小,而node的右子樹中的全部元素都比node自己要大。python

2、問題引入

與普通的二叉樹不一樣,任意給一串不重複的數字,就能夠肯定一棵二叉搜索樹,例如:當給定序列12,5,11,17,16,19,18時,能夠肯定的二叉搜索樹以下:算法

本質上,因爲二叉搜索樹的節點左右按大小分界的性質,肯定一棵二叉搜索樹最重要的仍是序列中數字出現的次序,一個小小的調換就可能致使二叉搜索樹改變,所以,有時候咱們須要找到一些方法來確認兩個序列所對應的二叉搜索樹是否爲同一棵二叉搜索樹。數據結構

3、舉例分析

咱們以最簡單的例子,由1,2,3構成的6種序列,及其對應的二叉搜索樹、先序、中序、後序、層序遍歷結果分別以下:app

4、方法探討

咱們可能會天然地想到用遍歷對兩顆二叉搜索樹進行比較,經常使用的遍歷方法:
先序遍歷、中序遍歷、後序遍歷、層序遍歷
下面咱們將分點探討他們的效果。函數

4.1 中序遍歷

中序遍歷老是先遍歷當前節點node的左子節點,而後遍歷自身元素、以後遍歷右子節點。於是,在二叉搜索樹中,中序遍歷的結果老是全部元素的升序排列(如上表中標紅的一行所示);換句話說,中序遍歷結果是不能幫助咱們判斷兩個序列是否對應同一棵二叉搜索樹的。網站

4.2 層序遍歷

  1. 因爲二叉搜索樹的構建方式與元素在每一層的分佈密切相關,對於出現元素集合徹底相同的兩個不一樣的序列,它們各自所對應的二叉搜索樹若是在某一層開始出現的元素不相同,那麼它們不是同一棵二叉搜索樹。
  2. 這也能夠由遞歸的思想來理解,對於特定的某一層來講,因爲前一層已經肯定,那麼將序列中剩下的元素按前後順序插入樹中的合適位置時,其位置也就自動被惟一肯定了,每一個元素是否能在某一層出現以及在該元素某一層出現的位置是肯定死了的,徹底由上一層的元素來決定,不存在其餘的位置來放置它。
  3. 再者,若是給咱們了一棵二叉搜索樹的層序遍歷結果,咱們會發現是能夠還原出一整棵二叉搜索樹的,這與普通二叉樹有些區別。
    所以能夠由層序遍歷結果完成咱們的判斷。

4.3 先序遍歷

根據一個先序遍歷結果(不妨仍以上面的那棵二叉搜索樹爲例,其先序遍歷結果是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

4.4 後序遍歷

後序遍歷與先序遍歷本質上同樣,只是在邏輯上進行了徹底翻轉(注意不是簡單的序列翻轉),思路和先序遍歷基本相同,仍然須要遞歸分組,只是須要從遍歷結果的最後一個元素開始反向構建。

5、總結

由前述分析討論可見,在二叉搜索樹的概念之下,中序遍歷損失的信息量是最大的,但因爲它獲得的結果的升序特性,這是咱們能夠用它來判斷一棵二叉樹是不是二叉搜索樹,這是其餘幾種遍歷沒法作到的,這也表示了中序遍歷與二叉搜索樹結合得很緊密。
而層序、先序、後序遍歷均可以用來判斷兩個給定序列是否爲同一棵二叉搜索樹(這裏以先序遍歷結果實現以下)。

6、代碼實現

# 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")
相關文章
相關標籤/搜索