資料結構與演算法——二叉查詢樹類的C++實現

readyao發表於2016-04-07
二叉樹的平均深度為O(logN);
二叉查詢樹在二叉樹的基礎上,增加的性質為:對於樹中每一個結點X,它的左子樹中所有項的值小於X中的項,而它的右子樹中所有項的值大於X中的項。

該二叉查詢樹結點的資料結構:


struct BinaryNode{
    Comparable element;//結點的值
    BinaryNode * left;//結點的左孩子
    BinaryNode * right;//結點的右孩子
    int num;//相同值的結點出現的次數,如果不考慮重複元素的話,該成員可以省去
    BinaryNode(const Comparable & e, BinaryNode* lt, BinaryNode* rt, int n):element(e), left(lt), right(rt), num(n){}
};

該結點資料結構其實是一個結點類。

該二叉查詢樹的主要成員函式:

BinarySearchTree(){root = NULL;}//建構函式
BinarySearchTree(vector<int> & v);//建構函式
BinarySearchTree(const BinarySearchTree & rhs);//複製建構函式
const BinarySearchTree & operator=(const BinarySearchTree & rhs);//賦值運算子過載
~BinarySearchTree();//解構函式

void preOrderPrintTree() const;//從小到大列印該二叉查詢樹
void inOrderPrintTree() const;//從大到小列印該二叉查詢樹

Comparable findMin() const;//查詢最小值
Comparable findMax() const;//查詢最大值
bool contains(const Comparable & x) const;//判斷該二叉查詢樹是否包含值為x的結點
bool isEmpty() const;//判斷該二叉查詢樹是否為空 
void makeEmpty();//清空該二叉查詢樹

void insert(const Comparable & x);//插入結點
void remove(const Comparable & x);//移除結點值為x的結點

主要成員函式介紹:

void remove(const Comparable & x);//移除結點值為x的結點

/****************************************************************
*   函式名稱:remove(const Comparable & x) 
*   功能描述: 移除結點
*   引數列表: x -- 要移除的結點的值 
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable & x)
{
    remove(x, root);    
}

template<typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable & x, BinaryNode * &t) const
{
    if(t == NULL)
        return;

    if(x < t->element)
        remove(x, t->left);
    else if(x > t->element)
        remove(x, t->right);
    else if((t->left != NULL) && (t->right != NULL)){//該結點有兩個兒子的時候,將該結點右子樹的最小結點覆蓋該結點的值,然後再刪除那個最小結點
        t->element = findMin(t->right);
        remove(t->element, t->right);
    }
    else {//該結點只有一個兒子的時候,將兒子放在當前結點的位置。用另一個指標儲存當前結點,然後刪除該結點;此時也包括該結點為葉子結點的情況
        BinaryNode * oldCurrentNode = t;
        t = (t->left == NULL) ? t->right : t->left;
        delete oldCurrentNode;
    }
}






下面的main函式是對remove成員函式的測試,用的就是上面兩個圖:

int main()
{
    BinarySearchTree<int> tree;
    tree.insert(6);
    tree.insert(2);
    tree.insert(1);
    tree.insert(4);
    tree.insert(3);
    tree.insert(8);

    tree.preOrderPrintTree();
    tree.remove(4);
    tree.preOrderPrintTree();

    BinarySearchTree<int> tree2;
    tree2.insert(6);
    tree2.insert(2);
    tree2.insert(1);
    tree2.insert(5);
    tree2.insert(3);
    tree2.insert(4);
    tree2.insert(8);
    tree2.preOrderPrintTree();
    tree2.remove(2);
    tree2.preOrderPrintTree();


    return 0;
}


下面是該二叉查詢樹類的原始碼:


/*************************************************************************
	> File Name: BinarySearchTree.cpp
	> Author: 
	> Mail: 
	> Created Time: 2016年04月06日 星期三 17時19分47秒
 ************************************************************************/

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;

template<typename Comparable>
class BinarySearchTree{
    public:
        BinarySearchTree(){root = NULL;}
        BinarySearchTree(vector<int> & v);
        BinarySearchTree(const BinarySearchTree & rhs);
        ~BinarySearchTree();
        
        const BinarySearchTree & operator=(const BinarySearchTree & rhs);//賦值運算子過載

        void preOrderPrintTree() const;//從小到大列印該二叉查詢樹
        void inOrderPrintTree() const;//從大到小列印該二叉查詢樹

        Comparable findMin() const;//查詢最小值
        Comparable findMax() const;//查詢最大值

        bool contains(const Comparable & x) const;//判斷該二叉查詢樹是否包含值為x的結點

        void makeEmpty();//清空該二叉查詢樹
        bool isEmpty() const;//判斷該二叉查詢樹是否為空 

        void insert(const Comparable & x);//插入結點
        void remove(const Comparable & x);//移除結點值為x的結點


    private:
        //樹結點的資料結構
        struct BinaryNode{
            Comparable element;
            BinaryNode * left;
            BinaryNode * right;
            int num;//相同值的結點出現的次數
            BinaryNode(const Comparable & e, BinaryNode* lt, BinaryNode* rt, int n):element(e), left(lt), right(rt), num(n){}
        };

        BinaryNode* root;

        void insert(const Comparable & x, BinaryNode * &t) const;
        void remove(const Comparable & x, BinaryNode * &t) const;

        void preOrder(BinaryNode * t) const;//前序遍歷
        void inOrder(BinaryNode * t) const;//中序遍歷
        void deleteNode(BinaryNode * t);//釋放結點t
        Comparable &findMin(BinaryNode * node) const;
        Comparable &findMax(BinaryNode * node) const;
        bool contains(const Comparable & x, BinaryNode * t) const;//判斷該二叉查詢樹是否包含值為x的結點
        BinaryNode *clone(BinaryNode * t) const{
            if(t == NULL)
                return NULL;

            return new BinaryNode(t->element, clone(t->left), clone(t->right), t->num);
        }

};

/****************************************************************
*   函式名稱:BinarySearchTree(const BinarySearchTree & rhs)
*   功能描述: 該二叉查詢樹的複製建構函式
*   引數列表: rhs 要複製的二叉查詢樹 
*   返回結果:無
*****************************************************************/
template<typename Comparable>
BinarySearchTree<Comparable>::BinarySearchTree(const BinarySearchTree & rhs)
{
    root = clone(rhs.root);
}

/****************************************************************
*   函式名稱:BinarySearchTree(const BinarySearchTree & rhs)
*   功能描述: 該二叉查詢樹的複製建構函式
*   引數列表: rhs 要複製的二叉查詢樹 
*   返回結果:無
*****************************************************************/
template<typename Comparable>
const BinarySearchTree<Comparable> & BinarySearchTree<Comparable>::operator=(const BinarySearchTree & rhs)//賦值運算子過載
{
    if(this != &rhs){
        makeEmpty();
        root = clone(rhs.root);
    }

    return *this;
}

/****************************************************************
*   函式名稱:contains(const Comparable & x)const
*   功能描述: 判斷該二叉查詢樹是否含有值為x的結點 
*   引數列表: 無
*   返回結果:如果有值為x的結點,則返回true;
*             如果沒有值為x的結點,則返回false;
*****************************************************************/
template<typename Comparable>
bool BinarySearchTree<Comparable>::contains(const Comparable & x) const
{
    if(isEmpty())
        return false;
    else
        return contains(x, root); 
}

template<typename Comparable>
bool BinarySearchTree<Comparable>::contains(const Comparable & x, BinaryNode * t) const
{
    if(t == NULL)
        return false;

    if(x == t->element)
        return true;
    else if(x > t->element)
        return contains(x, t->right);
    else if(x < t->element)
        return contains(x, t->left);
}

/****************************************************************
*   函式名稱:findMax()const
*   功能描述: 查詢樹的最大值 
*   引數列表: 無
*   返回結果:結點值的引用
*****************************************************************/
template<typename Comparable>
Comparable BinarySearchTree<Comparable>::findMax() const
{
    if(!isEmpty())
        return findMax(root); 
}

/****************************************************************
*   函式名稱:findMax(BinaryNode *node)const
*   功能描述: 查詢樹的最大值 
*   引數列表: 無
*   返回結果:結點值的引用
*****************************************************************/
template<typename Comparable>
Comparable & BinarySearchTree<Comparable>::findMax(BinaryNode * node) const
{
    if(node->right== NULL)
        return node->element;
    else 
        return findMax(node->right);
}

/****************************************************************
*   函式名稱:findMin()const
*   功能描述: 查詢樹的最小值 
*   引數列表: 無
*   返回結果:結點值的引用
*****************************************************************/
template<typename Comparable>
Comparable BinarySearchTree<Comparable>::findMin() const
{
    if(!isEmpty())
        return findMin(root); 
}

/****************************************************************
*   函式名稱:findMin(BinaryNode *node)const
*   功能描述: 查詢樹的最小值 
*   引數列表: 無
*   返回結果:結點值的引用
*****************************************************************/
template<typename Comparable>
Comparable & BinarySearchTree<Comparable>::findMin(BinaryNode * node) const
{
    if(node->left == NULL)
        return node->element;
    else 
        return findMin(node->left);
}

/****************************************************************
*   函式名稱:BinarySearchTree(vector<int> &)
*   功能描述: 建構函式
*   引數列表: v 用於構造二叉查詢樹的資料序列
*   返回結果:無
*****************************************************************/
template<typename Comparable>
BinarySearchTree<Comparable>::BinarySearchTree(vector<int> & v)
{
    root = NULL;//必須初始化,否則析構的時候會出錯

    for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
        insert(*it); 
}

/****************************************************************
*   函式名稱:~BinarySearchTree()
*   功能描述: 解構函式 
*   引數列表: 無 
*   返回結果:無
*****************************************************************/
template<typename Comparable>
BinarySearchTree<Comparable>::~BinarySearchTree()
{
   //deleteNode(root); 
    makeEmpty();//兩種方式都可以
}

/****************************************************************
*   函式名稱:deleteNode(BinaryNode *t)
*   功能描述: 釋放結點 
*   引數列表: 要釋放結點的指標 
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::deleteNode(BinaryNode * t)
{
    //後序遍歷的方式釋放所有結點 
    if(t != NULL){
        deleteNode(t->left);
        deleteNode(t->right);
        //cout << "t->element = " << t->element << endl;
        delete t;
    }
}


/****************************************************************
*   函式名稱:isEmpty() const
*   功能描述: 判斷該二叉查詢樹是否為空 
*   引數列表: 無 
*   返回結果:如果該樹為空,則返回true;
*             如果該樹為不為空,則返回false
*****************************************************************/
template<typename Comparable>
bool BinarySearchTree<Comparable>::isEmpty()const
{
    return (root == NULL) ? true : false;
}


/****************************************************************
*   函式名稱:makeEmpty() 
*   功能描述: 將該二叉查詢樹清空 
*   引數列表: 無 
*   返回結果:無
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::makeEmpty()
{
    deleteNode(root);//移除所有結點
    root = NULL;
}


/****************************************************************
*   函式名稱:preOrderPrintTree() const
*   功能描述: 按從小到大的順序輸出該二叉查詢樹
*   引數列表: 無 
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::preOrderPrintTree() const
{
    cout << "按從小到大的順序輸出該二叉查詢樹: ";
    preOrder(root); 
    cout << endl;
}

/****************************************************************
*   函式名稱:preOrder(BinaryNode * t) const
*   功能描述: 按從小到大的順序輸出該二叉查詢樹,前序遍歷
*   引數列表: 當前結點的指標 
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::preOrder(BinaryNode * t) const
{
    if(t != NULL){
        preOrder(t->left);//列印左子樹

        for(int i = 0; i < t->num; ++i)
            cout << t->element << " ";//列印父結點,可能有多個值

        preOrder(t->right);//列印右子樹
    }
}

/****************************************************************
*   函式名稱:inOrderPrintTree() const
*   功能描述: 按從大到小的順序列印該二叉樹
*   引數列表: 無 
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::inOrderPrintTree() const
{
    cout << "按從大到小的順序輸出該二叉查詢樹: ";
    inOrder(root); 
    cout << endl;
}

/****************************************************************
*   函式名稱:inOrder(BinaryNode * t) const
*   功能描述: 按從小到大的順序輸出該二叉查詢樹,前序遍歷
*   引數列表: 當前結點的指標 
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::inOrder(BinaryNode * t) const
{
    if(t != NULL){
        inOrder(t->right);//列印右子樹

        for(int i = 0; i < t->num; ++i)
            cout << t->element << " ";//列印父結點,可能有多個值

        inOrder(t->left);//列印左子樹
    }
}


/****************************************************************
*   函式名稱:remove(const Comparable & x) 
*   功能描述: 移除結點
*   引數列表: x -- 要移除的結點的值 
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable & x)
{
    remove(x, root);    
}

template<typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable & x, BinaryNode * &t) const
{
    if(t == NULL)
        return;

    if(x < t->element)
        remove(x, t->left);
    else if(x > t->element)
        remove(x, t->right);
    else if((t->left != NULL) && (t->right != NULL)){//該結點有兩個兒子的時候,將該結點右子樹的最小結點覆蓋該結點的值,然後再刪除那個最小結點
        t->element = findMin(t->right);
        remove(t->element, t->right);
    }
    else {//該結點只有一個兒子的時候,將兒子放在當前結點的位置。用另一個指標儲存當前結點,然後刪除該結點
        BinaryNode * oldCurrentNode = t;
        t = (t->left == NULL) ? t->right : t->left;
        delete oldCurrentNode;
    }
}
/****************************************************************
*   函式名稱:insert(const Comparable & x) 
*   功能描述: 插入值為x的結點 
*   引數列表: x 要插入的值 
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::insert(const Comparable & x)
{
    insert(x, root);
}

/****************************************************************
*   函式名稱:insert(const Comparable & x, BinaryNode * & t) const
*   功能描述: 在結點t上插入值為x的結點 
*   引數列表: x 要插入的值 
*             t 要插入到結點t上
*   返回結果:void
*****************************************************************/
template<typename Comparable>
void BinarySearchTree<Comparable>::insert(const Comparable & x, BinaryNode * & t) const
{
    if(t == NULL)
        t = new BinaryNode(x, NULL, NULL, 1);
    else if(x > t->element)
        insert(x, t->right);
    else if(x < t->element)
        insert(x, t->left);
    else if(x == t->element)//如果要插入的值和當前結點的值相同,則將當前結點的個數加1
        t->num++;
}



//測試該二叉查詢樹的成員函式 
int main0()
{

//    srand(unsigned (time(0)));

    vector<int> v;

    //隨機生成一個資料序列
    for(int i = 0; i < 10; ++i)
        v.push_back(rand()%10); 

    cout << "隨機產生的資料序列: ";
    for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
        cout << *it << " ";
    cout << endl;

    //用第一個建構函式生成該二叉查詢樹
    BinarySearchTree<int> tree;

    if(tree.isEmpty())
        cout << "該樹此時為空." << endl;
    else
        cout << "該樹此時為不為空." << endl;

    for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
        tree.insert(*it); 

    if(tree.isEmpty())
        cout << "該樹此時為空." << endl;
    else
        cout << "該樹此時為不為空." << endl;


    cout << "tree1: " << endl;
    tree.preOrderPrintTree();//從小到大輸出該二叉查詢樹
    tree.inOrderPrintTree();//從大到小輸出該二叉查詢樹

    int min = tree.findMin();
    cout << "min = " << min << endl;
    int max = tree.findMax();
    cout << "max = " << max << endl;

    if(tree.contains(5))
        cout << "contains(5))" << endl;
    else
        cout << "not contains(5)" << endl;

    BinarySearchTree<int> tree3 = tree;
    tree3.preOrderPrintTree();
    tree3.inOrderPrintTree();

    BinarySearchTree<int> tree4;
    tree4 = tree;
    tree4.preOrderPrintTree();
    tree4.inOrderPrintTree();
/*
    tree.makeEmpty();
    if(tree.isEmpty())
        cout << "該樹此時為空." << endl;
    else
        cout << "該樹此時為不為空." << endl;
*/



    //用第二個建構函式生成該二叉查詢樹
    cout << "tree2: " << endl;
    BinarySearchTree<int> tree2(v);
    tree2.preOrderPrintTree();//從小到大輸出該二叉查詢樹
    tree2.inOrderPrintTree();//從大到小輸出該二叉查詢樹

    return 0;
}


//test the functiona of remove
int main()
{
    BinarySearchTree<int> tree;
    tree.insert(6);
    tree.insert(2);
    tree.insert(1);
    tree.insert(4);
    tree.insert(3);
    tree.insert(8);

    tree.preOrderPrintTree();
    tree.remove(4);
    tree.preOrderPrintTree();

    BinarySearchTree<int> tree2;
    tree2.insert(6);
    tree2.insert(2);
    tree2.insert(1);
    tree2.insert(5);
    tree2.insert(3);
    tree2.insert(4);
    tree2.insert(8);
    tree2.preOrderPrintTree();
    tree2.remove(2);
    tree2.preOrderPrintTree();


    return 0;
}



相關文章