1. 程式人生 > >二叉排序樹C++實現

二叉排序樹C++實現

簡介

學習了演算法導論12章關於二叉排序樹的內容,自己利用C++實現了二叉排序樹的封裝。由此對二叉樹這種資料結構理解更加深刻了,對於遞迴在樹中的應用之廣更是有深切體會,例如遞迴建立,遞迴前,中,後序遍歷,返回樹高(個人最喜歡這個樹高遞迴函式,一句話返回樹高確實酷),遞迴刪除等……因為很多樹本身就是遞迴定義的。(刪除某節點比較難,有3,4種情況要分別考慮,暫時沒有實現,後續再補吧)
有什麼不足之處希望不吝賜教!

具體實現

標頭檔案二叉排序樹類的定義

註釋比較清楚,就不再贅述了:

#pragma once

#include<iostream>
using namespace std;

//樹節點定義,包含父節點指標(便於回溯前驅與後繼)
typedef struct Node { int data; struct Node *leftchild; struct Node *rightchild; struct Node *parent; }Node_t; /* 二叉排序樹類定義 */ class BSearchTree{ public: BSearchTree(void); ~BSearchTree(void); inline Node_t* getRoot() const { return this->root;} void createBSTree(int
*dataset, int size); //建立二叉排序樹 bool insertNode(Node_t **root, int value); //插入新節點,需要傳入二級指標(改變根指標的值) void inorderTraverse(Node_t *root) const; //中序遍歷 void visitMiddleOrder() const; //對上一函式繼續封裝 Node_t* searchNode(Node_t *root,int value) const; //按值查詢 void searchByValue(int value) const; //對上一函式繼續封裝
//最大與最小程式碼對稱 void getMax(Node_t *root) const; //獲取最大值 void getMin(Node_t *root) const; //獲取最小值 //前驅與後繼程式碼對稱 void getPredecessor(Node_t *node); //獲取節點前驅 void getSuccessor(Node_t *node); //獲取節點後繼 int getHeight(Node_t *root) const; //返回樹高 private: Node_t *root; //根節點 };

成員函式的實現:

#include "BSearchTree.h"


BSearchTree::BSearchTree(void)
{
    root = NULL;
}


BSearchTree::~BSearchTree(void)
{
    //to do sth
}

//建立二叉排序樹(匯入陣列內元素,逐一插入)
void BSearchTree:: createBSTree(int *dataset, int size) {
    for ( int i=0; i<size; i++ ) {
        insertNode(&root,dataset[i]);
    }
}


//插入新節點
//注意因為要修改root根指標的值,所以需要傳入二級指標
bool BSearchTree:: insertNode(Node_t **root, int value) {
    //初始化將插入的新節點
    Node_t *new_node = new Node_t;
    if ( new_node == NULL ) {
        return false;   
    }
    new_node->data = value;
    new_node->leftchild = new_node->rightchild = new_node->parent = NULL; 

    //空樹時,直接讓根指標指向新節點
    if( (*root) == NULL ) {
        *root = new_node;
        return true;
    }

     //插入到當前結點(*root)的左孩子  
    if ((*root)->leftchild == NULL && (*root)->data > value ) {
        new_node->parent = (*root);
        (*root)->leftchild = new_node;
        return true;
    }

     //插入到當前結點(*root)的右孩子  
    if((*root)->rightchild == NULL && (*root)->data < value){  
        new_node->parent = (*root);  
        (*root)->rightchild = new_node;  
        return true;  
    }  

    //遞迴法插入新節點
    if ( (*root)->data > value ) {  //新節點的值小於根節點,遞迴尋找左邊空位
        insertNode( &(*root)->leftchild,value);  //關鍵點

    }
    else if ( (*root)->data < value ) {  //新節點的值大於根節點,遞迴尋找右邊空位
        insertNode( &(*root)->rightchild,value); 

    } else {
        return true;
    }
}

//中序遍歷
void BSearchTree:: inorderTraverse(Node_t *root) const {
    //遞迴出口
    if ( root == NULL ) {
        return;
    }
    inorderTraverse( root->leftchild );
    cout<< root->data <<" ";
    inorderTraverse( root->rightchild );
}
void BSearchTree::visitMiddleOrder() const {
    inorderTraverse(this->root);
}

//按值查詢,返回節點的地址
Node_t* BSearchTree:: searchNode(Node_t *root,int value) const {
    if ( root == NULL ) {
        return NULL;
    }

    if ( root->data > value ) {
        searchNode( root->leftchild,value);

    }
    else if ( root->data < value ) {
        searchNode( root->rightchild,value);

    } else {
        return root;
    }
}
void BSearchTree:: searchByValue(int value) const{
    Node_t *p_findnode = this->searchNode(root,value);
    if ( p_findnode == NULL ) {
        cout<<"沒有找到該節點"<<endl;
    } else {
        cout<< "該節點存在" <<endl;
    }
}

//獲取最大值
void BSearchTree:: getMax(Node_t *root) const {
    while( root->rightchild ) {
        root = root->rightchild;
    }
    cout<<root->data<<endl;
}

//獲取最小值
void BSearchTree:: getMin(Node_t *root) const {
    while( root->leftchild ) {
        root = root->leftchild;
    }
    cout<<root->data<<endl;
}

//獲取節點前驅
void BSearchTree:: getPredecessor(Node_t *node) {
    //節點如果有左子樹,則其前驅節點是左子樹的最大值
    if ( node->leftchild != NULL ) {
        return getMax( node->leftchild );
    } else {
        cout<<"(該點無左子樹,開始回溯祖先...)"<<endl;
    }

    //如果沒有右子樹,則向上回溯,最頂層的祖先節點則是後繼
    Node_t *y = node->parent; //y首先指向該節點的父節點
    while( y != NULL && node == y->leftchild ) {
        node = y;
        y = y->parent;
    }
    cout<<y->data;
}

//獲取節點後繼
void BSearchTree:: getSuccessor(Node_t *node) {
    //節點如果有右子樹,則其後繼節點是右子樹的最小值
    if ( node->rightchild != NULL ) {
        return getMin( node->rightchild );
    } else {
        cout<<"(該點無右子樹,開始回溯祖先...)"<<endl;
    }

    //如果沒有右子樹,則向上回溯,最頂層的祖先節點則是後繼
    Node_t *y = node->parent;
    while( y != NULL && node == y->rightchild ) { //遇到第一個“拐角”回溯結束
        node = y;  //節點向上爬一層
        y = y->parent; //y也向上逐層回溯祖先
    }
    cout<<y->data;
}

//返回樹高,樹通用寫法
//ps:演算法導論認為只有一個根節點時樹高為0,我們常認為1
int BSearchTree::getHeight(Node_t *root) const {
    return root ?  max(getHeight(root->leftchild),getHeight(root->rightchild))+1 : -1;
}

測試程式碼:

#include"BSearchTree.h"


void main(void) {
     int arrs[] = { 14,2,4,10,3,5,8,23,18,35 };
    //int arrs[] = { 23, 65, 12, 3, 8, 76,  90, 21, 75, 34,345, 61 };
    int len = sizeof(arrs) / sizeof(arrs[0]);
    BSearchTree bsearch_tree;
    bsearch_tree.createBSTree(arrs,len);

    cout<<"中序遍歷結果: ";
    bsearch_tree.visitMiddleOrder();
    cout<<endl;

    cout<<"尋找節點3..."<<endl;
    bsearch_tree.searchByValue(3);
    cout<<endl;
    cout<<"尋找節點100..."<<endl;
    bsearch_tree.searchByValue(100);
    cout<<endl;

    cout<<"max :";
    bsearch_tree.getMax(bsearch_tree.getRoot());
    cout<<"min :";
    bsearch_tree.getMin(bsearch_tree.getRoot());
    cout<<endl;


    cout<<"樹高:"<< bsearch_tree.getHeight(bsearch_tree.getRoot())<<endl<<endl;

    Node_t *pnext = bsearch_tree.searchNode(bsearch_tree.getRoot(),4);
    cout<<"節點"<<pnext->data<<"的後繼為:";
    bsearch_tree.getSuccessor(bsearch_tree.searchNode(bsearch_tree.getRoot(),4));

    pnext = bsearch_tree.searchNode(bsearch_tree.getRoot(),8);
    cout<<"節點"<<pnext->data<<"的後繼為:";
    bsearch_tree.getSuccessor(bsearch_tree.searchNode(bsearch_tree.getRoot(),8));
    cout<<endl;

    cout<<endl;

    Node_t *pbefore = bsearch_tree.searchNode(bsearch_tree.getRoot(),14);
    cout<<"節點"<<pbefore->data<<"的前驅為:";
    bsearch_tree.getPredecessor(bsearch_tree.searchNode(bsearch_tree.getRoot(),14));

    pbefore = bsearch_tree.searchNode(bsearch_tree.getRoot(),18);
    cout<<"節點"<<pbefore->data<<"的前驅為:";
    bsearch_tree.getPredecessor(bsearch_tree.searchNode(bsearch_tree.getRoot(),18));
    cout<<endl;


    system("pause");
}

執行結果:

這裡寫圖片描述