常用資料結構之線索二叉樹

楊天超發表於2020-10-02

1.線索二叉樹

        上一篇二叉樹中,我們介紹了基本的二叉樹的結構。每一個父節點對應兩個子節點,左子節點和右子節點。其中我們會看到,很多節點的左右節點都為null,為了更高效的儲存和遍歷,我們考慮一種方式將這些為null的節點利用起來。這就是線索二叉樹的思想,將為null的左子節點指向遍歷時的前驅節點,為null的右子節點指向遍歷時的後續節點。如此一來,在遍歷的過程中,我們便可以直接通過左右子節點,找到葉子節點的前驅和後驅,使用一條線完整的將整刻樹串起來。

                                                                        

2.程式碼實現python

          在實現的過程中,我們原來的Node類中需要新增兩個標誌位leftType和rightType.分別表示對應的節點是普通的子節點還是前驅後驅節點。實現過程如下:首先我們構建一棵樹,然後使用中序遍歷這樹,使用pre變數記錄前一個節點。對於當前節點左子節點為null的,將其左子節點指向pre節點;如果pre的右子節點也為null,將pre的右子節點指向當前節點;

          然後進行遍歷,先找到最下面的左子節點,如果該節點後後驅節點,則不斷遍歷其後驅節點。否則的話按照普通的中序遍歷尋找下一個節點(),不斷遍歷直到找不到任何節點。則完成整棵樹的遍歷。

#-*- coding:utf-8 -*-
class Node(object):
    def __init__(self,val):
        self.val = val
        self.left = None
        self.right=None
        # 左節點型別 0表示左子節點 1表示後驅
        self.leftType = 0
        # 右節點型別 0表示右子節點 1表示後驅
        self.rightType = 0
    def show(self):
        print("遍歷--當前節點為 = {}".format(self.val),end='\t')
        if self.left != None and self.leftType == 0:
            print("左子節點為 = {}".format(self.left.val),end='\t')
        if self.right != None and self.rightType == 0:
            print("右子節點為 = {}".format(self.right.val))
        if self.left != None and self.leftType == 1:
            print("前驅節點為 = {}".format(self.left.val),end='\t')
        if self.right != None and self.rightType == 1:
            print("後驅節點為 = {}".format(self.right.val))
class ThreadTree(object):
    def __init__(self):
        self.root = None
        self.pre = None
    #構建一棵基本的樹
    def build(self,values):
        # 將每個元素轉換為node節點
        nodes = [None if V is None else Node(V) for V in values]
        # 給根節點新增左右子節點
        for index in range(1, len(nodes)):
            parent_index = (index - 1) // 2
            parent = nodes[parent_index]
            if parent is None:
                raise Exception('parent node missing at index{}'.format(index))
            if index % 2 == 0:
                parent.right = nodes[index]
            else:
                parent.left = nodes[index]
        self.root = nodes[0]
        return nodes[0]
    #在中序遍歷的過程中對每個節點中left,right為null的進行復制前驅後驅節點
    def threadedNode(self,node):
        if node == None:
            return
        self.threadedNode(node.left)
        # 處理當前節點的的前驅節點
        if node.left == None:
            node.left = self.pre
            node.leftType = 1
            print("當前節點={}".format(node.val))
            if self.pre != None:
                print("前驅結點為 = {}".format(self.pre.val))
        if self.pre != None and self.pre.right == None:
            # 前驅節點的右指標指向當前節點
            self.pre.right = node
            self.pre.rightType = 1
            print("當前節點={},後驅結點為 = {}".format(self.pre.val, node.val))
        self.pre = node
        self.threadedNode(node.right)
    def mid_order(self,node):
        while node != None:
            while node.leftType == 0:
                node = node.left
            if node != None:
                node.show()
            while node.rightType == 1:
                node = node.right
                node.show()
            node = node.right
threadTree = ThreadTree()
node = threadTree.build([1,2,3,4,5,6,7,8])
threadTree.threadedNode(node)
threadTree.mid_order(node)

3.總結

          本文介紹了線索二叉樹的原理已經使用python實現的過程,最核心的思想就是利用了二叉樹中為null的空指標,使這些指標指向前驅和後驅節點。

4.閒言

           我連著熬了兩天兩夜,終於把琉璃看完了。真的太喜歡璇璣小姐姐了。作為一個人工智慧演算法工程師,我的理想就是人工智慧快速的發展。當人們在看電視劇的時候,能夠忘記現實的存在,我就是男主角。這樣就可以和璇璣小姐姐談戀愛了。我覺得以後的生活就是這麼的公平,每個人都可以在自己的虛擬現實中享受整個世界,人人都是皇帝。

相關文章