二叉搜索樹(遞歸實(shí)現(xiàn))

#include <iostream>
#include <queue>
#include <cassert>

using namespace std;

template <typename Key, typename Value>
class BST{

private:
    struct Node{
        Key key;
        Value value;
        Node *left;
        Node *right;

        Node(Key key, Value value){
            this->key = key;
            this->value = value;
            this->left = this->right = NULL;
        }

        Node(Node *node){
            this->key = node->key;
            this->value = node->value;
            this->left = node->left;
            this->right = node->right;
        }
    };

    Node *root;
    int count;

public:
    BST(){
        root = NULL;
        count = 0;
    }
    ~BST(){
        destroy( root );
    }

    int size(){
        return count;
    }

    bool isEmpty(){
        return count == 0;
    }


int main() {

    srand(time(NULL));
    BST<int,int> bst = BST<int,int>();

    int n = 10000;
    for( int i = 0 ; i < n ; i ++ ){
        int key = rand()%n;
        // 為了后續(xù)測(cè)試方便,這里value值取和key值一樣
        int value = key;
        //cout<<key<<" ";
        bst.insert(key,value);
    }

    // test remove
    // remove elements in random order
    int order[n];
    for( int i = 0 ; i < n ; i ++ )
        order[i] = i;
    shuffle( order , n );

    for( int i = 0 ; i < n ; i ++ )
        if( bst.contain( order[i] )){
            bst.remove( order[i] );
            cout<<"After remove "<<order[i]<<" size = "<<bst.size()<<endl;
        }

    return 0;
}

1. 插入insert

public:
void insert(Key key, Value value){
     root = insert(root, key, value);
}

private:
// 向以node為根的二叉搜索樹中,插入節(jié)點(diǎn)(key, value)
// 返回插入新節(jié)點(diǎn)后的二叉搜索樹的根
Node* insert(Node *node, Key key, Value value){

    if( node == NULL ){      // 如果節(jié)點(diǎn)為空,就在此節(jié)點(diǎn)處加入x信息
        count ++;
        return new Node(key, value);
    }

    if( key == node->key )  
        node->value = value;  //如果相等,就把頻率加1
    else if( key < node->key )
        node->left = insert( node->left , key, value);  // 如果x小于節(jié)點(diǎn)的值,就繼續(xù)在節(jié)點(diǎn)的左子樹中插入x
    else    // key > node->key    
        node->right = insert( node->right, key, value);  // 如果x大于節(jié)點(diǎn)的值,就繼續(xù)在節(jié)點(diǎn)的右子樹中插入x

    return node;
}

2. 包含contain

bool contain(Key key){
    return contain(root, key);
}

// 查看以node為根的二叉搜索樹中是否包含鍵值為key的節(jié)點(diǎn)
bool contain(Node* node, Key key){

    if( node == NULL )
        return false;

    if( key == node->key )
        return true;
    else if( key < node->key )
        return contain( node->left , key );
    else // key > node->key
        return contain( node->right , key );
}

3. 搜索search

Value* search(Key key){
    return search( root , key );
}

// 在以node為根的二叉搜索樹中查找key所對(duì)應(yīng)的value
Value* search(Node* node, Key key){

    if( node == NULL )
        return NULL;

    if( key == node->key )
        return &(node->value);
    else if( key < node->key )
        return search( node->left , key );
    else // key > node->key
        return search( node->right, key );
}

4. 遍歷

  • 前序遍歷preOrder
void preOrder(){
    preOrder(root);
}

// 對(duì)以node為根的二叉搜索樹進(jìn)行前序遍歷
void preOrder(Node* node){

    if( node != NULL ){
        cout<<node->key<<endl;
        preOrder(node->left);
        preOrder(node->right);
    }
}
  • 中序遍歷inOrder
void inOrder(){
    inOrder(root);
}

// 對(duì)以node為根的二叉搜索樹進(jìn)行中序遍歷
void inOrder(Node* node){

    if( node != NULL ){
        inOrder(node->left);
        cout<<node->key<<endl;
        inOrder(node->right);
    }
}
  • 后序遍歷postOrder
void postOrder(){
    postOrder(root);
}

// 對(duì)以node為根的二叉搜索樹進(jìn)行后序遍歷
void postOrder(Node* node){

    if( node != NULL ){
        postOrder(node->left);
        postOrder(node->right);
        cout<<node->key<<endl;
    }
}
  • 層序遍歷levelOrder
void levelOrder(){

    queue<Node*> q;
    q.push(root);
    while( !q.empty() ){

        Node *node = q.front();
        q.pop();

        cout<<node->key<<endl;

        if( node->left )
            q.push( node->left );
        if( node->right )
            q.push( node->right );
    }
}

5. 尋找最小/大鍵值

Key minimum(){
    assert( count != 0 );
    Node* minNode = minimum( root );
    return minNode->key;
}

// 在以node為根的二叉搜索樹中,返回最小鍵值的節(jié)點(diǎn)
Node* minimum(Node* node){
    if( node->left == NULL )
        return node;

    return minimum(node->left);
}
Key maximum(){
    assert( count != 0 );
    Node* maxNode = maximum(root);
    return maxNode->key;
}

// 在以node為根的二叉搜索樹中,返回最大鍵值的節(jié)點(diǎn)
Node* maximum(Node* node){
    if( node->right == NULL )
        return node;

    return maximum(node->right);
}

6. 從二叉樹中刪除最小/大值所在節(jié)點(diǎn)

void removeMin(){
    if( root )
        root = removeMin( root );
}

// 刪除掉以node為根的二分搜索樹中的最小節(jié)點(diǎn)
// 返回刪除節(jié)點(diǎn)后新的二分搜索樹的根
Node* removeMin(Node* node){

    if( node->left == NULL ){

        Node* rightNode = node->right;
        delete node;
        count --;
        return rightNode;
    }

    node->left = removeMin(node->left);
    return node;
}
void removeMax(){
    if( root )
        root = removeMax( root );
}

// 刪除掉以node為根的二分搜索樹中的最大節(jié)點(diǎn)
// 返回刪除節(jié)點(diǎn)后新的二分搜索樹的根
Node* removeMax(Node* node){

    if( node->right == NULL ){

        Node* leftNode = node->left;
        delete node;
        count --;
        return leftNode;
    }

    node->right = removeMax(node->right);
    return node;
}

7. 刪除remove

void remove(Key key){
    root = remove(root, key);
}

// 刪除掉以node為根的二分搜索樹中鍵值為key的節(jié)點(diǎn)
// 返回刪除節(jié)點(diǎn)后新的二分搜索樹的根
Node* remove(Node* node, Key key){

    if( node == NULL )
        return NULL;

    if( key < node->key ){
        node->left = remove( node->left , key );
        return node;
    }
    else if( key > node->key ){
        node->right = remove( node->right, key );
        return node;
    }
    else{   // key == node->key

        if( node->left == NULL ){
            Node *rightNode = node->right;
            delete node;
            count --;
            return rightNode;
        }

        if( node->right == NULL ){
            Node *leftNode = node->left;
            delete node;
            count--;
            return leftNode;
        }

        // node->left != NULL && node->right != NULL
        Node *successor = new Node(minimum(node->right));
        count ++;

        successor->right = removeMin(node->right);
        successor->left = node->left;

        delete node;
        count --;

        return successor;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗(yàn)。 張土汪:刷leetcod...
    土汪閱讀 12,929評(píng)論 0 33
  • 二叉查找樹(Binary Sort Tree) 我們之前所學(xué)到的列表,棧等都是一種線性的數(shù)據(jù)結(jié)構(gòu),今天我們將學(xué)習(xí)計(jì)...
    Cryptic閱讀 5,134評(píng)論 1 19
  • 概述 在分析樹形結(jié)構(gòu)之前,先看一下樹形結(jié)構(gòu)在整個(gè)數(shù)據(jù)結(jié)構(gòu)中的位置 當(dāng)然,沒有圖,現(xiàn)在還沒有足夠的水平去分析圖這種太...
    wustor閱讀 2,171評(píng)論 0 3
  • 基本概念:每個(gè)節(jié)點(diǎn)的子樹最多為2個(gè)的樹。 幾個(gè)基本性質(zhì): 1、二叉樹第i層上的結(jié)點(diǎn)數(shù)目最多為 2^(i-1) (i...
    知城閱讀 410評(píng)論 0 0
  • 小白兔因?yàn)閻圩兂闪诵⌒?從前有一個(gè)小熊,撿到了一個(gè)貝殼。他說:“這是我的耳朵?!彼刻於及沿悮煸陬^上,叮鈴鈴,叮...
    思茲念茲閱讀 595評(píng)論 0 1

友情鏈接更多精彩內(nèi)容