二叉樹(三十五)

        上節博客我們介紹了通用樹到二叉樹的轉換,今天我們就來看看二叉樹的實現。我們先來看看它的組成結構,如下

圖片.png

        設計要點:

            1、BTree 爲二叉樹結構,每個結點最多隻有兩個後繼結點;

            2、BTreeNode 只包含 4 個固定的公有成員(左樹、右樹、構造函數、工廠模式創建新結點函數);

            3、實現樹結構的所有操作(增、刪、查等);

        下來我們來看看 BTreeNode 和 BTree 的設計與實現,如下

圖片.png

圖片.png

        下來我們來看看 BTree(二叉樹結構)的實現框架,如下圖所示

圖片.png

        我們來看看具體的 BTree 和 BTreeNode 的源碼實現


BTreeNode.h 源碼

#ifndef BTREENODE_H
#define BTREENODE_H

#include "Tree.h"

namespace DTLib
{

template < typename T >
class BTreeNode : public TreeNode<T>
{
public:
    BTreeNode<T>* left;
    BTreeNode<T>* right;

    BTreeNode()
    {
        left = NULL;
        right = NULL;
    }

    static BTreeNode<T>* NewNode()
    {
        BTreeNode<T>* ret = new BTreeNode<T>();

        if( ret != NULL )
        {
            ret->m_flag = true;
        }

        return ret;
    }
};

}

#endif // BTREENODE_H


BTree.h 源碼

#ifndef BTREE_H
#define BTREE_H

#include "Tree.h"
#include "BTreeNode.h"

namespace DTLib
{

template < typename T >
class BTree : public Tree<T>
{
public:
    bool insert(TreeNode<T>* node)
    {
        bool ret = true;
        
        return ret;
    }

    virtual bool insert(TreeNode<T>* node, BTNodePos pos)
    {
        bool ret = true;

        return ret;
    }

    bool insert(const T& value, TreeNode<T>* parent)
    {
        bool ret = true;

        return ret;
    }

    SharedPointer< Tree<T> > remove(const T& value)
    {
        return NULL;
    }

    SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    {
        return NULL;
    }

    BTreeNode<T>* find(const T& value) const
    {
        return NULL;
    }

    BTreeNode<T>* find(TreeNode<T>* node) const
    {
        return NULL;
    }

    BTreeNode<T>* root() const
    {
        return dynamic_cast<BTreeNode<T>*>(this->m_root);
    }

    int degree() const
    {
        return 0;
    }

    int count() const
    {
        return 0;
    }

    int height() const
    {
        return 0;
    }

    void clear()
    {
        this->m_root = NULL;
    }

    ~BTree()
    {
        clear();
    }
};

}

#endif // BTREE_H

        我們看到它的框架和我們之前實現的通用樹差不多,下來我們來一一的實現它的所有操作

        1、查找操作

            a> 基於數據元素值的查找:BTreeNode<T>* find(const T& value) const;b> 基於結點的查找:BTreeNode<T>* find(TreeNode<T>* node) const

        a> 基於數據元素值的查找,定義功能:find(node, value)。在 node 爲根結點的二叉樹中查找 value 所在的結點,如下

圖片.png

        b> 基於結點的查找,定義功能:find(node, obj)。在 node 爲根結點的二叉樹中查找是否存在 obj 結點,如下

圖片.png

        具體源碼實現如下

#ifndef BTREE_H
#define BTREE_H

#include "Tree.h"
#include "BTreeNode.h"
#include "Exception.h"
#include "LinkQueue.h"
#include "DynamicArray.h"

namespace DTLib
{

template < typename T >
class BTree : public Tree<T>
{
protected:
    virtual BTreeNode<T>* find(BTreeNode<T>* node, const T& value) const    
    {
        BTreeNode<T>* ret = NULL;

        if( node != NULL )
        {
            if( node->value == value )
            {
                ret = node;
            }
            else
            {
                if( ret == NULL )
                {
                    ret = find(node->left, value);
                }

                if( ret == NULL )
                {
                    ret = find(node->right, value);
                }
            }
        }

        return ret;
    }

    virtual BTreeNode<T>* find(BTreeNode<T>* node, BTreeNode<T>* obj) const
    {
        BTreeNode<T>* ret = NULL;

        if( node != NULL )
        {
            if( node == obj )
            {
                ret = node;
            }
            else
            {
                if( ret == NULL )
                {
                    ret = find(node->left, obj);
                }

                if( ret == NULL )
                {
                    ret = find(node->right, obj);
                }
            }
        }

        return ret;
    }
public:
  BTreeNode<T>* find(const T& value) const    
  {
        return find(root(), value);
    }

    BTreeNode<T>* find(TreeNode<T>* node) const
    {
        return find(root(), dynamic_cast<BTreeNode<T>*>(node));
    }

    BTreeNode<T>* root() const
    {
        return dynamic_cast<BTreeNode<T>*>(this->m_root);
    }
};

}

#endif // BTREE_H

        2、插入操作

        我們在進行插入操作的時候不是二叉樹的任意結點都能插入,必須得指明插入新結點的位置,是左子樹還是右子樹,不指明便是從左向右的進行插入。因此我們得定義一個枚舉,用來表示二叉樹結點的位置。插入操作也分爲兩種:a> 插入新結點:bool insert(TreeNode<T>* node); bool insert(TreeNode<T>* node, BTNodePos pos); b> 插入數據元素:bool insert(const T& value, TreeNode<T>* parent); bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)。

        新結點的插入如圖所示

圖片.png

        a> 指定位置的結點插入,如下圖所示

圖片.png

        插入新結點,如下圖所示

圖片.png

        b> 插入數據元素

圖片.png

        我們來看看源碼具體是怎麼實現的

namespace DTLib
{

enum BTTraversal
{
    PreOrder,
    Inorder,
    PostOrder,
    LeverOrder
};

template < typename T >
class BTree : public Tree<T>
{
protected:
    virtual bool insert(BTreeNode<T>* n, BTreeNode<T>* np, BTNodePos pos)
    {
        bool ret = true;

        if( pos == ANY )
        {
            if( np->left == NULL )
            {
                np->left = n;
            }
            else if( np->right == NULL )
            {
                np->right = n;
            }
            else
            {
                ret = false;
            }
        }
        else if( pos == LEFT )
        {
            if( np->left == NULL )
            {
                np->left = n;
            }
            else
            {
                ret = false;
            }
        }
        else if( pos == RIGHT )
        {
            if( np->right == NULL )
            {
                np->right = n;
            }
            else
            {
                ret = false;
            }
        }
        else
        {
            ret = false;
        }

        return ret;
    }
public:    
    bool insert(TreeNode<T>* node)
    {
        return insert(node, ANY);
    }

    virtual bool insert(TreeNode<T>* node, BTNodePos pos)
    {
        bool ret = true;

        if( node != NULL )
        {
            if( this->m_root == NULL )
            {
                node->parent = NULL;
                this->m_root = node;
            }
            else
            {
                BTreeNode<T>* np = find(node->parent);

                if( np != NULL )
                {
                    ret = insert(dynamic_cast<BTreeNode<T>*>(node), np, pos);
                }
                else
                {
                    THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree ndoe ....");
                }
            }
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterException, "Parameter node can not be NULL ...");
        }

        return ret;
    }

    bool insert(const T& value, TreeNode<T>* parent)
    {
        return insert(value, parent, ANY);
    }

    virtual bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
    {
        bool ret = true;
        BTreeNode<T>* node = BTreeNode<T>::NewNode();

        if( node == NULL )
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new node ...");
        }
        else
        {
            node->value = value;
            node->parent = parent;

            ret = insert(node, pos);

            if( !ret )
            {
                delete node;
            }
        }

        return ret;
    }
};

}

        3、結點刪除與清除

            a> 基於數據元素值的刪除:SharedPointer< Tree<T> > remove(const T& value); b> 基於結點的刪除:SharedPointer< Tree<T> > remove(TreeNode<T>* node)。

        二叉樹中結點的刪除如下圖所示

圖片.png

        刪除操作功能的定義:virtual void remove(BTreeNode<T>* node, BTree<T>*& ret); 將在 node 爲根結點的子樹從原來的二叉樹中刪除,ret 作爲子樹返回(ret 指向堆空間中的二叉樹對象),下來我們來看看刪除功能函數的實現流程,如下圖所示

圖片.png

        清除操作的定義:void clear(),將二叉樹中的所有結點清除(釋放堆中的結點),如下所示

圖片.png

        功能定義:free(node),清除 node 爲根結點的二叉樹,釋放二叉樹中的每一個結點,如下

圖片.png

        我們來看看具體源碼的實現

namespace DTLib
{

template < typename T >
class BTree : public Tree<T>
{
protected:
    virtual void remove(BTreeNode<T>* node, BTree<T>*& ret)    
    {
        ret = new BTree<T>();

        if( ret == NULL )
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memroy to create new tree ...");
        }
        else
        {
            if( root() == node )
            {
                this->m_root = NULL;
            }
            else
            {
                BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);

                if( parent->left == node )
                {
                    parent->left = NULL;
                }
                else if( parent->right == node )
                {
                    parent->right = NULL;
                }

                node->parent = NULL;
            }

            ret->m_root = node;
        }
    }
    
    virtual void free(BTreeNode<T>* node)    
    {
            if( node != NULL )
            {
                free(node->left);
                free(node->right);
    
                if( node->flag() )
                {
                    delete node;
                }
            }
        }
public:    
    SharedPointer< Tree<T> > remove(const T& value)
    {
        BTree<T>* ret = NULL;
        BTreeNode<T>* node = find(value);

        if( node == NULL )
        {
            THROW_EXCEPTION(InvalidParameterException, "Can not find the tree node via value ...");
        }
        else
        {
            remove(node, ret);
            m_queue.clear();
        }

        return ret;
    }

    SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    {
        BTree<T>* ret = NULL;

        node = find(node);

        if( node == NULL )
        {
            THROW_EXCEPTION(InvalidParameterException, "Parament node is invalid ...");
        }
        else
        {
            remove(dynamic_cast<BTreeNode<T>*>(node), ret);
            m_queue.clear();
        }

        return ret;
    }
    
    void clear()    
    {
            free(root());

            this->m_root = NULL;
        }
};

}

        4、屬性操作

        在二叉樹中,它的屬性操作有三種:a> 結點數目;b> 高度;c> 度數。

        a> 二叉樹中結點的數目,定義功能:count(node)。在 node 爲根結點的二叉樹中統計結點數目,如下圖所示

圖片.png

        b> 二叉樹的高度,定義功能:height(node)。獲取 node 爲根結點的二叉樹的高度,如下圖所示

圖片.png

        c> 二叉樹的度數,定義功能:degree(node)。獲取 node 爲根結點的二叉樹的度數,如下圖所示

圖片.png

        下來我們來看看具體源碼是怎麼實現的

namespace DTLib
{

template < typename T >
class BTree : public Tree<T>
{
protected:
    int count(BTreeNode<T>* node) const    
    {
        return (node != NULL) ? (count(node->left) + count(node->right) + 1) : 0;
    }

    int height(BTreeNode<T>* node) const
    {
        int ret = 0;

        if( node != NULL )
        {
            int lh = height(node->left);
            int rh = height(node->right);

            ret = ((lh > rh) ? lh : rh) + 1;
        }

        return ret;
    }

    int degree(BTreeNode<T>* node) const
    {
        int ret = 0;

        if( node != NULL )
        {
            BTreeNode<T>* child[] = { node->left, node->right };

            ret = !!node->left + !!node->right;

            for(int i=0; (i<2) && (ret<2); i++)
            {
                int d = degree(child[i]);

                if( ret < d )
                {
                    ret = d;
                }
            }
        }

        return ret;
    }
public:    
    int degree() const    
    {
        return degree(root());
    }

    int count() const
    {
        return count(root());
    }

    int height() const
    {
        return height(root());
    }
};

}

        5、層次遍歷

        二叉樹的遍歷是指從根結點出發,按照某種次序訪問二叉樹中的所有結點,使得每個結點被訪問一次,且僅被訪問一次。設計思路(遊標),提供一組遍歷相關的函數,按層次訪問二叉樹中的數據元素,如下

圖片.png

        層次遍歷算法:a> 原料:class LinkQueue<T>; b> 遊標:LinkQueue<T>::front();

        思想:a> begin() --> 將根結點壓入隊列中;

                  b> current() --> 訪問隊頭元素指向的數據元素;

                  c> next() --> 隊頭元素彈出,將隊頭元素的蓋子壓入隊列中(核心);

                  d> end() --> 判斷隊列是否爲空。

        層次遍歷算法示例如下

圖片.png

        具體源碼實現如下

namespace DTLib
{

template < typename T >
class BTree : public Tree<T>
{
protected:
    LinkQueue<BTreeNode<T>*> m_queue;
public:    
    bool begin()    
    {
        bool ret = (root() != NULL);

        if( ret )
        {
            m_queue.clear();
            m_queue.add(root());
        }

        return ret;
    }

    bool end()
    {
        return (m_queue.length() == 0);
    }

    bool next()
    {
        bool ret = (m_queue.length() > 0);

        if( ret )
        {
            BTreeNode<T>* node = m_queue.front();

            m_queue.remove();

            if( node->left != NULL )
            {
                m_queue.add(node->left);
            }

            if( node->right != NULL )
            {
                m_queue.add(node->right);
            }
        }

        return ret;
    }

    T current()
    {
        if( !end() )
        {
            return m_queue.front()->value;
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterException, "No value at current position ...");
        }
    }
};

}

        6、典型遍歷方式

               典型的遍歷方式:a> 先序遍歷;b> 中序遍歷;c> 後序遍歷。

        a> 先序遍歷:二叉樹爲空,則直接返回;若不爲空:1、訪問根結點中的數據元素,2、先序遍歷左子樹,3、先序遍歷右子樹。如下圖所示

圖片.png

        先序遍歷功能定義如下

圖片.png

        b> 中序遍歷:二叉樹爲空,則直接返回;若不爲空:1、中序遍歷左子樹,2、訪問根結點中的數據元素,3、中序遍歷右子樹。如下圖所示

圖片.png

        中序遍歷功能定義如下

圖片.png

        c> 後序遍歷:二叉樹爲空,則直接返回;若不爲空:1、後序遍歷左子樹,2、後序遍歷右子樹,3、訪問根結點中的數據元素。如下圖所示

圖片.png

        後序遍歷功能定義如下

圖片.png

        我們可以將二叉樹的典型遍歷算法集成到 BTree 中,設計要點:不能與層次遍歷函數衝突,必須設計新的函數接口;算法執行完成後,能夠方便的獲得遍歷結果;遍歷結果能夠反映結點訪問的先後次序。

        函數接口設計:SharedPointer< Array<T> > traversal(BTTraversal order);根據參數 order 選擇執行遍歷算法(先序、中序、後序),返回值爲堆中的數組對象(生命週期由智能指針管理),數組元素的次序反映遍歷的先後次序。典型的遍歷示例如下所示

圖片.png

        下來我們來看看具體的源碼實現

namespace DTLib
{

template < typename T >
class BTree : public Tree<T>
{
protected:
    void perOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)    
    {
        if( node != NULL )
        {
            queue.add(node);
            perOrderTraversal(node->left, queue);
            perOrderTraversal(node->right, queue);
        }
    }

    void inOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)
    {
        if( node != NULL )
        {
            inOrderTraversal(node->left, queue);
            queue.add(node);
            inOrderTraversal(node->right, queue);
        }
    }

    void postOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)
    {
        if( node != NULL )
        {
            postOrderTraversal(node->left, queue);
            postOrderTraversal(node->right, queue);
            queue.add(node);
        }
    }
    
    void traversal(BTTraversal order, LinkQueue<BTreeNode<T>*>& queue)    
    {
        switch (order)
        {
            case PreOrder:
                perOrderTraversal(root(), queue);
                break;
            case Inorder:
                inOrderTraversal(root(), queue);
                break;
            case PostOrder:
                postOrderTraversal(root(), queue);
                break;
            default:
                THROW_EXCEPTION(InvalidParameterException, "Parameter order is invalid ...");
                break;
        }
    }
public:    
    SharedPointer< Array<T> > traversal(BTTraversal order)    
    {
        DynamicArray<T>* ret = NULL;
        LinkQueue<BTreeNode<T>*> queue;

        traversal(order, queue);

        ret = new DynamicArray<T>(queue.length());

        if( ret != NULL )
        {
            for(int i=0; i<ret->length(); i++, queue.remove())
            {
                ret->set(i, queue.front()->value);
            }
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create return tree ...");
        }

        return ret;
    }
};

}

        7、比較與相加

        要進行比較與相加,首先必須得進行克隆。我們先來看看二叉樹的克隆:SharedPointer< BTree<T> > clone() const;克隆當前樹的一份拷貝,返回值爲堆空間中的一顆新二叉樹(與當前樹相等)。定義功能:clone(node),拷貝 node 爲根結點的二叉樹(數據元素在對應位置相等),如下圖所示

圖片.png

        二叉樹比較操作的定義,判斷兩顆二叉樹中的數據元素是否對應相等:bool operator == (const BTree<T>& btree);bool operator != (const BTree<T>& btree)。如下

圖片.png

        二叉樹的比較,定義功能:equal(lh, rh)。判斷 lh 爲根結點的二叉樹與 rh 爲根結點的二叉樹是否相等,如下

圖片.png

        二叉樹的相加操作:SharedPointer< BTree<T> > add(const BTree<T>& btree) const;將當前二叉樹與參數 btree 中的數據元素在對應位置處相加,返回值(相加的結果)爲堆空間中的一顆新二叉樹。如下

圖片.png

        二叉樹的加法,定義功能:add(lh, rh)。將 lh 爲根結點的二叉樹與 rh 爲根結點的二叉樹相加,如下

圖片.png

        具體源碼實現如下

namespace DTLib
{

template < typename T >
class BTree : public Tree<T>
{
protected:
    BTreeNode<T>* clone(BTreeNode<T>* node) const    
    {
        BTreeNode<T>* ret = NULL;

        if( node != NULL )
        {
            ret = BTreeNode<T>::NewNode();

            if( ret != NULL )
            {
                ret->value = node->value;

                ret->left = clone(node->left);
                ret->right = clone(node->right);

                if( ret->left != NULL )
                {
                    ret->left->parent = ret;
                }

                if( ret->right != NULL )
                {
                    ret->right->parent = ret;
                }
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException, "No memory to clone old tree ...");
            }
        }

        return ret;
    }

    bool equal(BTreeNode<T>* rh, BTreeNode<T>* lh) const
    {
        if( lh == rh )
        {
            return true;
        }
        else if( (lh != NULL) && (rh != NULL) )
        {
            return (lh->value == rh->value) && equal(lh->left, rh->left) && equal(lh->right, rh->right);
        }
        else
        {
            return false;
        }
    }

    BTreeNode<T>* add(BTreeNode<T>* lh, BTreeNode<T>* rh) const
    {
        BTreeNode<T>* ret = NULL;

        if( (lh == NULL) && (rh != NULL) )
        {
            ret = clone(rh);
        }
        else if( (lh != NULL) && (rh == NULL) )
        {
            ret = clone(lh);
        }
        else if( (lh != NULL) && (rh != NULL) )
        {
            ret = BTreeNode<T>::NewNode();

            if( ret != NULL )
            {
                ret->value = lh->value + rh->value;

                ret->left = add(lh->left, rh->left);
                ret->right = add(lh->right, rh->right);

                if( ret->left != NULL )
                {
                    ret->left->parent = ret;
                }

                if( ret->right != NULL )
                {
                    ret->right->parent = ret;
                }
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new node ...");
            }
        }

        return ret;
    }
public:    
    SharedPointer< BTree<T> > clone() const    
    {
        BTree<T>* ret = new BTree<T>();

        if( ret != NULL )
        {
            ret->m_root = clone(root());
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new btree ...");
        }

        return ret;
    }

    bool operator == (const BTree<T>& btree)
    {
        return equal(root(), btree.root());
    }

    bool operator != (const BTree<T>& btree)
    {
        return !(*this == btree);
    }

    SharedPointer< BTree<T> > add(const BTree<T>& btree) const
    {
        BTree<T>* ret = new BTree<T>();

        if( ret != NULL )
        {
            ret->m_root = add(root(), btree.root());
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree ...");
        }

        return ret;
    }
};

}

        8、二叉樹的線索優化實現

        什麼叫線索優化?將二叉樹轉換爲雙向鏈表的過程(非線性 --> 線性);能夠反映某種二叉樹的遍歷次序(結點的先後訪問次序),利用結點的 right 指針指向遍歷中的後繼結點,利用結點的 left 指針指向遍歷中的前驅節點。

        如何對二叉樹進行線索化呢?過程如下

圖片.png

        二叉樹的線索化,如下

圖片.png

        層次遍歷算法如下:

            1、將根結點壓入隊列中;

            2、訪問隊頭元素指向的二叉樹結點;

            3、隊頭元素彈出,將隊頭元素的孩子壓入隊列中;

            4、判斷隊列是否爲空(非空:轉 2,空:結束)。

        層次遍歷算法示例如下

圖片.png

圖片.png

        函數接口設計:BTreeNode<T>* thread(BTTraversal order);根據參數 order 選擇線索化的次序(先序、中序、後序、層次),返回值線索化之後指向鏈表首結點的指針,線索化執行結束後對應的二叉樹變爲空樹。線索化流程如下所示

圖片.png

        隊列中結點的連接算法如下所示 [connect(queue)]

圖片.png

        具體源碼實現如下

namespace DTLib
{

template < typename T >
class BTree : public Tree<T>
{
protected:
    void levelOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)    
    {
        if( node != NULL )
        {
            LinkQueue<BTreeNode<T>*> tmp;

            tmp.add(root());

            while( tmp.length() > 0 )
            {
                BTreeNode<T>* n = tmp.front();

                if( n->left != NULL )
                {
                    tmp.add(n->left);
                }

                if( n->right != NULL )
                {
                    tmp.add(n->right);
                }

                tmp.remove();
                queue.add(n);
            }
        }
    }
    
    void traversal(BTTraversal order, LinkQueue<BTreeNode<T>*>& queue)    
    {
        switch (order)
        {
            case PreOrder:
                perOrderTraversal(root(), queue);
                break;
            case Inorder:
                inOrderTraversal(root(), queue);
                break;
            case PostOrder:
                postOrderTraversal(root(), queue);
                break;
            case LeverOrder:
                levelOrderTraversal(root(), queue);
                break;
            default:
                THROW_EXCEPTION(InvalidParameterException, "Parameter order is invalid ...");
                break;
        }
    }

    BTreeNode<T>* connect(LinkQueue<BTreeNode<T>*>& queue)
    {
        BTreeNode<T>* ret = NULL;

        if( queue.length() > 0 )
        {
            ret = queue.front();

            BTreeNode<T>* slider = queue.front();

            queue.remove();

            slider->left = NULL;

            while( queue.length() > 0 )
            {
                slider->right = queue.front();
                queue.front()->left = slider;
                slider = queue.front();
                queue.remove();
            }

            slider->right = NULL;
        }

        return ret;
    }
public:    
    BTreeNode<T>* thread(BTTraversal order)    
    {
        BTreeNode<T>* ret = NULL;
        LinkQueue<BTreeNode<T>*> queue;

        traversal(order, queue);

        ret = connect(queue);

        this->m_root = NULL;

        m_queue.clear();

        return ret;
    }
};

}

        通過對二叉樹的學習,總結如下:1、二叉樹的插入操作必須指明其插入的位置,正確處理指向父結點的指針;2、插入數據元素時需要從堆空間中創建結點,當數據元素插入失敗時需要釋放結點空間;3、刪除操作將目標結點所代表的子樹移除,必須完善處理父結點和子結點的關係;4、清除操作作用於銷燬樹中的每個結點,銷燬結點時判斷是否釋放對應的內存空間(工廠模式);5、二叉樹的典型遍歷都是以遞歸方式執行的,BTree 以不同的函數接口支持典型遍歷;6、層次遍歷與典型遍歷互不衝突,遍歷結果能夠反映樹結點訪問的先後次序;7、比較操作判斷兩棵二叉樹中的數據元素是否對應相等,克隆操作將當前二叉樹在堆空間中進行復制;8、相加操作將兩顆二叉樹中的數據元素在對應位置處相加,結果保存在堆空間的一顆二叉樹中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章