二叉樹c++實現


!!版權聲明:本文為博主原創文章,版權歸原文作者和博客園共有,謝絕任何形式的 轉載!!

作者:mohist

 

 

--- 歡迎指正---

 

二叉樹特點:

 要么為空樹;要么,當前結點的左孩子比當前結點值小,當前結點的右孩子比當前結點的值大。

1、插入:

  1.1 插入結點的值比當前結點的值小,繼續找當前結點的左子樹,

  1.2 插入結點的值比當前結點的值大,繼續找當前結點的右子樹,

  1.3 找到合適的位置了,插入樹。

2、刪除:

  2.1 刪除結點是葉子結點,直接將其刪除即可

  2.2 刪除結點只有左孩子或者只有右孩子,將其孩子結點刪除,並將指向孩子結點的分支設置為空,c++是設置為NULL。不過更好的做法是,將孩子結點的值替換到當前結點,再刪除孩子結點即可。

  2.3 刪除的結點同時含有左孩子與右孩子,需要找到刪除結點的后繼結點,將后繼結點作為當前結點。

 

完整源碼:

#include <iostream>
using namespace std;

struct node 
{
    // 數據域
    int data;

    // 左節點
    node *lc;

    // 右結點
    node *rc;

    // 構造函數
    node()
        : data(0)
        , lc(NULL)
        , rc(NULL)
    {
    }
};


// bst
class bstree
{
public:
    enum
    {
        hmax_size_32767     = 32767,
        hmin_size_0         = 0,
    };

public:

    // 構造函數
    bstree()
        : root(NULL)
        , size(0)
    {
    }

    // 析構函數
    virtual ~bstree(){}
    
    int get_size()
    {
        return size;
    }

    // 插入結點
    void insert_node(int data)
    {
        int cur_size = get_size();
        if (hmax_size_32767 == cur_size)
        {
            cout << "insert node error, the size of the tree is max" << endl;
            return ;
        }
        root = insert(root, data);
    }

    // 先序遍歷(前序遍歷)
    void pre_order()
    {
        pre_order_traverse(root);
    }

    // 中序遍歷
    void in_order()
    {
        in_order_traverse(root);
    }

    // 后序遍歷
    void post_order()
    {
        post_order_traverse(root);
    }

    /*
        查找某個結點
        int key - 查找結果

        返回值:
            NULL : 可能為root為空 或者 沒有找到
            != NULL, 找到結點
    */
    node* query(int key)
    {
        if (NULL == root)
        {
            cout << "query error, root = null" << endl;
            return NULL;
        }

        return query_node(root, key);
    }

    // 刪除樹
    void remove_all()
    {
        if (NULL == root)
        {
            cout << "remove all failed, root = null" << endl;
            return;
        }
        
        remove_all(root);

        int cur_size = get_size();
        if (0 == cur_size)
            root = NULL;
    }

    // 刪除某個結點
    void remove_node(int del_data)
    {
        if (NULL == root)
        {
            cout << "remove node error, root = null" << endl;
            return;
        }

        node *parent_node   = NULL;
        node *del_node      = root;

        // 找到刪除結點的父節點與刪除結點
        while (del_node)
        {
            if (del_data == del_node->data)
                break;
            else if (del_data > del_node->data)
            {
                parent_node = del_node;
                del_node    = del_node->rc;
            }
            else if (del_data < del_node->data)
            {
                parent_node = del_node;
                del_node = del_node->lc;
            }
        }

        // 若沒有找到要刪除的結點
        if (NULL == del_node)
        {
            cout << "remove node error, " << del_data << " was not find" << endl;
            return;
        }

        // 1、若刪除的結點沒有左子樹和右子樹
        if ( (NULL == del_node->lc) && (NULL == del_node->rc)  )
        {
            // 為什么要先判斷根結點,因為根結點的父節點找不到,結果為NULL,
            // 1.1 可能只有一個根結點, 將root釋放值為空
            if (del_node == root)
            {
                root = NULL;
                delete del_node;
                del_node = NULL;

                dec_size();
                return;
            }

            // 1.2 非根結點,那就是葉子結點了, 將父節點指向刪除結點的分支指向NULL
            if  (del_node == parent_node->lc)
                parent_node->lc = NULL;
            else if (del_node == parent_node->rc)
                parent_node->rc  = NULL;

            // 釋放結點
            delete del_node;
            del_node = NULL;
            dec_size();
        }

        // 2、若刪除結點只有左孩子,沒有右孩子
        else if ( (NULL != del_node->lc) && (NULL == del_node->rc) )
        {
            // 2.1 刪除結點為根結點,則將刪除結點的左孩子替代當前刪除結點
            if (del_node == root)
            {
                root = root->lc;
            }
            // 2.2 其他結點,將刪除結點的左孩子作為父節點的左孩子
            else
            {
                if (parent_node->lc == del_node)
                    parent_node->lc = del_node->lc;
                else if (parent_node->rc == del_node)
                    parent_node->rc = del_node->lc;
            }

            delete del_node;
            del_node = NULL;

            dec_size();
        }

        // 3、若刪除結點只有右孩子
        else if ( (NULL == del_node->lc) && (NULL != del_node->rc) )
        {
            // 3.1 若為根結點
            if (root == del_node)
            {
                root = root->rc;
            }
            else
            {
                if (del_node == parent_node->lc)
                    parent_node->lc = del_node->rc;
                else if (del_node == parent_node->rc)
                    parent_node->rc = del_node->rc;
            }

            delete del_node;
            del_node = NULL;

            dec_size();
        }

        // 4、若刪除結點既有左孩子,又有右孩子,需要找到刪除結點的后繼結點作為根結點
        else if ( (NULL != del_node->lc) && (NULL != del_node->rc) )
        {
            node *successor_node = del_node->rc;
            parent_node = del_node;

            while (successor_node->lc)
            {
                parent_node = successor_node;
                successor_node = successor_node->lc;
            }

            // 交換后繼結點與當前刪除結點的數據域
            del_node->data = successor_node->data;
            // 將指向后繼結點的父節點的孩子設置后繼結點的右子樹
            if (successor_node == parent_node->lc)
                parent_node->lc = successor_node->rc;
            else if (successor_node == parent_node->rc)
                parent_node->rc = successor_node->rc;

            // 刪除后繼結點
            del_node = successor_node;
            delete del_node;
            del_node = NULL;

            dec_size();
        }
    }

    // 返回以proot為根結點的最小結點
    node *get_min_node(node *proot)
    {
        if (NULL == proot->lc)
            return proot;

        return get_min_node(proot->lc);
    }

    // 返回以proo為根節點的最大結點
    node *get_max_node(node *proot)
    {
        if (NULL == proot->rc)
            return proot;
        
        return get_max_node(proot->rc);
    }

    // 返回根節點
    node *get_root_node()
    {
        return root;
    }

    // 返回proot結點的父節點
    node *get_parent_node(int key)
    {
        // 當前結點
        node *cur_node = NULL;
        // 父節點
        node *parent_node = NULL;

        cur_node = root;

        // 標記是否找到
        bool is_find = false;
        while (cur_node)
        {
            if (key == cur_node->data)
            {
                is_find = true;
                break;
            }

            // 因為比當前結點的值還要小,所以需要查找當前結點的左子樹
            else if (key < cur_node->data)
            {
                parent_node = cur_node;
                cur_node = cur_node->lc;
            }
            // 同上, 查找當前結點的右子樹
            else if (key > cur_node->data)
            {
                parent_node = cur_node;
                cur_node    = cur_node->rc;
            }
        }

        return (true == is_find)?  parent_node :  NULL; 
    }

   






private:


    //查找某個值
    node *query_node(node *proot, int key)
    {
        if (NULL == proot)
        {
            return proot;
        }

        if (proot->data == key)
            return proot;
        else if (proot->data > key)
        {
            return query_node(proot->lc, key);
        }
        else if (proot->data < key)
        {
            return query_node(proot->rc, key);
        }
        
        return NULL;
    }

    // 后序遍歷刪除所有結點
    void remove_all(node *proot)
    {
        if (NULL != proot)
        {
            remove_all(proot->lc);
            remove_all(proot->rc);
            delete proot;

            dec_size();
        }
    }

    // 先序遍歷
    void pre_order_traverse(node *proot)
    {
        if (NULL != proot)
        {
            cout << proot->data << ",   "; 
            pre_order_traverse(proot->lc);
            pre_order_traverse(proot->rc);
        }
    }

    // 中序遍歷
    void in_order_traverse(node *proot)
    {
        if (NULL != proot)
        {
            in_order_traverse(proot->lc);
            cout << proot->data << ",   "; 
            in_order_traverse(proot->rc);
        }
    }

    // 后續遍歷
    void post_order_traverse(node *proot)
    {
        if (NULL != proot)
        {
            post_order_traverse(proot->lc);
            post_order_traverse(proot->rc);
            cout << proot->data << ",   ";
        }
    }

    // 插入結點
    node *insert(node *proot, int data)
    {
        // 結點不存在, 則創建
        if (NULL == proot)
        {
            node *new_node = new(std::nothrow) node;
            if (NULL != new_node)
            {
                new_node->data = data;
                proot = new_node;
                
                // 結點+1;
                add_size();
            }

            return proot;
        }

        //  插入值比當前結點值還要小, 則應該插入到當前節點的左邊
        if (proot->data > data)
        {
            proot->lc = insert(proot->lc, data);
        }
        // 插入之比當前結點值還要打,則應該插入到當前結點的右邊
        else if (proot->data < data)
        {
            proot->rc = insert(proot->rc, data);
        }

        // 相等,則不插入結點。

        return proot;
    }

    // size + 1
    void add_size()
    {
        if (hmax_size_32767 == size)
            return ;
        size++;
    }

    // size - 1
    void dec_size()
    {
        if ( hmin_size_0 == size)
        {
            return ;
        }

        size--;
    }




private:
    // 根結點
    node *root;

    // 當前樹的結點個數
    int size;
};



// 測試代碼
int main()
{

    bstree tree;

    //
    tree.insert_node(50);

    tree.insert_node(30);
    tree.insert_node(10);
    tree.insert_node(0);
    tree.insert_node(20);
    tree.insert_node(40);

    tree.insert_node(70);
    tree.insert_node(90);
    tree.insert_node(100);
    tree.insert_node(60);
    tree.insert_node(80);

    // 前序遍歷
    cout << "前序遍歷" << endl;
    tree.pre_order();
    cout << endl;

    // 中序遍歷
    cout << "中序遍歷" << endl;
    tree.in_order();
    cout << endl;

    // 后序遍歷
    cout << "后序遍歷" << endl;
    tree.post_order();
    cout << endl;

    cout << "刪除結點開始,結束請輸入10086" << endl;

    int del_key = 0;

    while (true)
    {
        cout << "輸入刪除結點值 = ";
        cin >> del_key;
        if (10086 == del_key)
            break;

        tree.remove_node(del_key);

        cout << "刪除后,結點個數 = " << tree.get_size() << endl;
        cout << "刪除后, 中序遍歷結果:" ;// << endl;
        tree.in_order();
        cout << endl << endl;
    }

    tree.remove_all();

    return 0;
}

 

測試結果:

 


免責聲明!

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



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