二叉樹存儲及遍歷


1、樹的存儲:

 

注意:樹的深度是從根節點開始(其深度為1)自頂向下逐層累加的,而高度是從葉節點開始(其高度為1)自底向上逐層累加的。雖然樹的深度和高度一樣,但是具體到樹的某個節點,其深度和高度是不一樣的。我的理解是:非根非葉結點的深度是從根節點數到它的,高度是從葉節點數到它的。

二叉樹的存儲:1、數組存儲(此方法適合完全二叉樹的存儲)

                   2、鏈表存儲(可分為二叉鏈表,三叉鏈表)結構如下:

 

2、 使用二叉鏈表實現二叉樹

 測試用例:

int a[10] = { 1, 2, '#', '#', 3, 4, '#', '#', 5, 6 };//其中用'表示空'

按前序遍歷的算法重建出二叉樹為:(先創建根節點,再創建左子樹,后創建右子樹)

                                            

代碼實現:

BinaryTree<T>* _CreateBinaryTree(const T *a,size_t size, size_t&index)
    {
        assert(a);
        BinaryTreeNode<T> *node = new BinaryTreeNode<T> (a[index]);
        if (index < size&&a[index++] != '#')
        {
            node->_left = _CreateBinaryTree(a, size, ++index);
           node->_right = _CreateBinaryTree(a, size, ++index);

        }
        else
{
return NULL;
}
return node; }

 3、二叉樹的遍歷

以上圖的二叉樹為例:

1-a、先序遍歷(由於二叉樹的結構具有遞歸的特性可以采用遞歸的方式遍歷)

void _PrevOrder(BinaryTreeNode<T>* root)
    {
        if (root)
        {
            cout<<root->_data<<" ";
            _PrevOrder(root->_left);
            _PrevOrder(root->_right);
        }
        else
             return;
        
    }

1-b、二叉樹的非遞歸先序遍歷
思想:1、可以采用棧先進先出的原則:先使根節點入棧,棧不為空打印棧頂元素,彈出棧頂元素,

         2、在使棧頂元素的不為空右子樹入棧,再使棧頂元素的不為空左子樹入棧

         3、 再按1、2進行判斷直至棧為空退出

void PrevOrder_NonR(BinaryTreeNode<T> *_root)
    {
        if (_root==NULL)
        {
            return;
        }
        stack<BinaryTreeNode<T>*> s1;
        s1.push(_root);
        while (!s1.empty())
        {
            BinaryTreeNode<T> *top=s1.top();
            cout<<top->_data<<" ";
            s1.pop();
            if (top->_right)
            {
                s1.push(top->_right);
            }
            if (top->_left)
            {
                s1.push(top->_left);
            }
        }
        cout<<endl;
    }

2-a、二叉樹的中序遍歷(遞歸)

void _InOrder(BinaryTreeNode<T>* root)
    {
        if (root)
        {
            _InOrder(root->_left);
            cout<<root->_data<<" ";
            _InOrder(root->_right);
        }
        else
        {
            return;
        }
    }

2-b、二叉樹的中序遍歷非遞歸

思想:中序遍歷是先遍歷左子樹,再遍歷根節點,后遍歷右子樹

        1、使cur指向根節點,使cur->_left入棧直至cur為空(定義cur是為了指向當前遍歷的節點)

        2、若棧不為空,打印棧頂元素,使cur指向棧頂元素的右子樹(當前的棧頂元素也就是某一個樹的根節點,但其右子樹還未遍歷所以使cur指向其右子樹)

        3-a、若棧不為空,前一步棧頂元素的右子樹為空,直接打印當前棧頂元素也就是前一步棧頂元素的根節點

        3-b、若棧不為空,前一步棧頂元素的右子樹不為空,使cur指向的右子樹入棧

        4、在按照2,3的步驟循環,直至cur和棧為空時結束

//非遞歸中序
    void InOrder_NonR(BinaryTreeNode<T> *root)
    {
        stack<BinaryTreeNode<T>*> s1;
        BinaryTreeNode<T>* cur=_root;
        while (cur||!s1.empty())
        {
            while (cur)
            {
                s1.push(cur);
                cur=cur->_left;
            }
            if (!s1.empty())
            {
                BinaryTreeNode<T>* top=s1.top();
                cout<<top->_data<<" ";
                s1.pop();
                cur=top->_right;
            }

        }
        cout<<endl;
    }

3-a二叉樹的后續遍歷(遞歸)

void _PostOrder(BinaryTreeNode<T>* root)
    {
        if (root)
        {
            _PostOrder(root->_left);
            _PostOrder(root->_right);
            cout<<root->_data<<" ";
        }
        else
        {
            return;
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM