二叉搜索树的基本功能实现

     

        二叉查找树(Binary Search Tree),又被称为二叉搜索树。设x为二叉查找树中的一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。



在二叉查找树中:
(01) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(02) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(03) 任意节点的左、右子树也分别为二叉查找树。
(04) 没有键值相等的节点(no duplicate nodes)。

在实际应用中,二叉查找树的使用比较多。下面,用C语言实现二叉查找树。

我在网上查到的一位大神写的加上我自己总结的,一起分享给大家

*二叉搜索树中的节点类 
 *Node.h 
 */  
# ifndef _NODE_  
#define _NODE_  
class Node  
{  
private:  
    int value;/*节点中存放的元素值*/  
    Node *parentNode;/*所指向的父节点指针*/  
    Node *leftChildNode;/*左孩子节点指针*/  
    Node *rightChildNode;/*右孩子节点指针*/  
public:  
    Node(int v);/*初始化函数*/  
    Node* getParentNode();/*返回父节点指针*/  
    Node* getLeftChildNode();/*返回左孩子节点指针*/  
    Node* getRightChildNode();/*返回右孩子节点指针*/  
    int getValue();/*返回节点元素值*/  
    void setParentNode(Node *p);/*设定父节点指针*/  
    void setLeftChildNode(Node *left);/*设定左孩子节点*/  
    void setRightChildNode(Node *right);/*设定右孩子结点*/  
    void setValue(int v);/*设定节点元素值*/  
};  
#endif  


/* 
 *Node.cpp 
 */  
#include "Node.h"  
#include <cstdio> //NULL  
  
/*初始化函数*/  
Node::Node(int r)  
{  
    setValue(r);  
    setParentNode(NULL);  
    setLeftChildNode(NULL);  
    setRightChildNode(NULL);  
}  
/*返回父节点指针*/  
Node* Node::getParentNode()  
{  
    return parentNode;  
}  
/*返回右孩子节点指针*/  
Node* Node::getRightChildNode()  
{  
    return rightChildNode;  
}  
/*返回左孩子节点指针*/  
Node* Node::getLeftChildNode()  
{  
    return leftChildNode;  
}  
/*返回节点元素值*/  
int Node::getValue()  
{  
    return value;  
}  
/*设定左孩子节点*/  
void Node::setLeftChildNode(Node *left)  
{  
    leftChildNode = left;  
}  
/*设定父节点指针*/  
void Node::setParentNode(Node *parent)  
{  
    parentNode = parent;  
}  
/*设定右孩子结点*/  
void Node::setRightChildNode(Node *right)  
{  
    rightChildNode = right;  
}  
/*设定节点元素值*/  
void Node::setValue(int v)  
{  
    value = v;  
}  

/*二叉搜索树类: 
 *BinarySearchTree.h 
 */  
#ifndef _BINARYSEARCHTREE_  
#define _BINARYSEARCHTREE_  
#define MAXLENGTH 100 //二叉搜索树的最大节点总数  
#include "Node.h"  
class BinarySearchTree  
{  
private:  
    Node *rootNode;/*根节点指针*/  
public:  
    BinarySearchTree();/*构造函数初始化*/  
    void setRootNode(Node *root);/*设置根节点*/  
    void treeInsert(int v);/*向搜索数中添加节点*/  
    void levelTreeWalk(Node *start);/*层次遍历*/  
    void inorderTreeWalk(Node *start);/*中序遍历*/  
    void preorderTreeWalk(Node *start);/*先序遍历*/  
    void postorderTreeWalk(Node *start);/*后序遍历*/  
    void transplant(Node *u,Node *v);/*将节点v替换到u的位置,并且相应子树进行转换*/  
    bool deleteNode(Node *point);/*从搜索树中删除节点point*/  
    bool max(int x,int y);/*比较两个整型元素值大小,x<y返回false*/  
    int getNodeNumber(Node *start);/*得到以start为根的树的节点总数*/  
    int getTreeHeight();/*计算二叉搜索树的高度*/  
    int getNodeHeight(Node *start);/*计算节点start的高度*/  
    Node* getRootNode();/*得到根节点指针*/  
    Node* getMinimum(Node *start);/*得到以start节点为根的搜索数中的具有最小元素值的节点*/  
    Node* treeMax(Node *start);//递归版本的得到具有最大元素值的节点  
    Node* getMaximum(Node *start);/*得到以start为根节点的搜索数中的具有最大元素值的节点*/  
    Node* getTreeSuccessor(Node *start);/*得到节点start的后继节点*/  
    Node* getTreePredessor(Node *start);/*得到start的前驱节点*/  
    Node* treeSearch2(Node *start,int k);/*迭代版本*/  
    Node* treeSearch1(Node *start,int k);/*搜索数的查找,如果k存在于搜索树中, 
                                           (从树根开始查找,)则返回给节点,否则返回null*/  
};  
#endif  

/* 
 *BinarySearchTree.cpp 
 */  
#include "BinarySearchTree.h"  
#include <cstdio>  
#include <iostream>  
using namespace std;  
  
/*构造函数初始化*/  
BinarySearchTree::BinarySearchTree()  
{  
    setRootNode(NULL);  
}  
/*得到根节点指针*/  
Node* BinarySearchTree::getRootNode()  
{  
    return rootNode;  
}  
/*设置根节点*/  
void BinarySearchTree::setRootNode(Node *root)  
{  
    rootNode = root;  
}  
  
/*向搜索数中添加节点,输入是新的节点元素值*/  
void BinarySearchTree::treeInsert(int v)  
{  
    /*新的插入的节点*/  
    Node *newInsertNode = new Node(v);  
    Node *y = NULL;  
    Node *x = getRootNode();//得到根节点  
    /*通过while循环中元素比较得到新的节点的合适位置*/  
    while(x!=NULL)  
    {  
        y = x;  
        if(v < x->getValue())    /*二叉搜索树的性质:x.left.value<x.value;*/  
            x = x->getLeftChildNode();  
        else                             /*x.right.value>=x.values*/  
            x = x->getRightChildNode();  
    }  
    //y = newInsertNode;  
    if(y == NULL)//二叉搜索树为空的情况  
        setRootNode(newInsertNode);  
    else if(v < y->getValue())  
    {  
        y->setLeftChildNode(newInsertNode);  
        newInsertNode->setParentNode(y);  
    }  
    else  
    {  
        y->setRightChildNode(newInsertNode);  
        newInsertNode->setParentNode(y);  
    }  
}  
  
/*从搜索树中删除节点point,如果删除成功,返回true, 
                                       如果是空子树,返回false*/  
/*1、point没有左右子孩子,直接删除point 
 *2、point没有左孩子的情况,直接删除point并把右孩子放到原来point位置 
        上面两种情况可以归为一类情况:没有左孩子,将右孩子放到point位置 
   3、只有左孩子情况,把左孩子放到point位置,删除point 
   4、左右孩子都有的情况:查找point节点的后继节点successor  
        1、如果successor为point右孩子(既然为point右孩子,则successsor没有左孩子) 
            将point左孩子作为successor左孩子,successor替换point,删除point节点 
        2、如果successor不是point的右孩子(是以point右孩子为根节点的子树最小值所在节点 
            且没有左孩子)将successor右节点sright作为successor所在子树根节点,并将point 
            右孩子节点pright作为successor右节点,successor左孩子节点pleft作为successor 
            左孩子节点,删除point,,, 
 */  
bool BinarySearchTree::deleteNode(Node *point)  
{  
    /*搜索树为空或point为空时进行的操作*/  
    if(point == NULL || getRootNode() == NULL)  
        return false;  
    /*如果节点point不再搜索树中*/  
    if(treeSearch1(getRootNode(),point->getValue()) == NULL)  
        return false;  
    /*下面的就是讨论的三种情况:*************************/  
    /*1、point的左孩子节点为空*/  
    if(point->getLeftChildNode() == NULL)  
        transplant(point,point->getRightChildNode());  
    /*2、point的右孩子节点为空*/  
    else if(point->getRightChildNode() == NULL)  
        transplant(point,point->getLeftChildNode());  
    /*3、point的左右孩子节点均不为空*/  
    else  
    {  
        /*得到point的后继节点*/  
        Node *successor = getMinimum(point->getRightChildNode());  
        /*当successor不为point的右孩子节点时进行的操作*/  
        if(successor->getParentNode() != point)  
        {  
            transplant(successor,successor->getRightChildNode());  
            successor->setRightChildNode(point->getRightChildNode());  
            successor->getRightChildNode()->setParentNode(successor);  
        }  
        transplant(point,successor);  
        successor->setLeftChildNode(point->getLeftChildNode());  
        successor->getLeftChildNode()->setParentNode(successor);  
    }  
    delete point;  
    return true;  
}  
/*此时u节点右节点为空,v节点左孩子为空,将u的左孩子节点放到v的左孩子节点处 
   并把u的父节点作为v的父节点,即删除u节点 
   此函数的作用是将u的父节点作为v的父节点,v作为u的父节点的原u位置相应子节点 
 v可以为空节点,也可以不是,对于u的左孩子节点的处理,由这个函数的调用者进行 
 处理 
*/  
void BinarySearchTree::transplant(Node *u,Node *v)  
{  
    if(u->getParentNode() == NULL)  
        setRootNode(v);  
    else if(u == u->getParentNode()->getLeftChildNode())  
        u->getParentNode()->setLeftChildNode(v);  
    else  
        u->getParentNode()->setRightChildNode(v);  
    if(v != NULL)  
        v->setParentNode(u->getParentNode());  
}  
  
/*得到以start节点为根的搜索数中的具有最小元素值的节点*/  
/*while迭代版本:*/  
Node* BinarySearchTree::getMinimum(Node *start)  
{  
    Node *minNode = start;  
    if(minNode == NULL)//空树的情况  
        return minNode;  
    while(minNode->getLeftChildNode() != NULL)  
    {  
        minNode = minNode->getLeftChildNode();  
    }  
    return minNode;  
}  
/*得到以start为根节点的搜索数中的具有最大元素值的节点*/  
/*递归版本:*/  
Node* BinarySearchTree::getMaximum(Node *start)  
{  
    return treeMax(start);  
}  
Node* BinarySearchTree::treeMax(Node *start)  
{  
    if(start == NULL)  
        return NULL;  
    else if(start->getRightChildNode() == NULL)  
        return start;  
    else  
        return treeMax(start->getRightChildNode());  
}  
  
/*得到以start为根的树的节点总数*/  
int BinarySearchTree::getNodeNumber(Node *start)  
{  
    if(start == NULL)  
        return 0;  
    if(start->getLeftChildNode() ==NULL)  
        return getNodeNumber(start->getRightChildNode()) + 1;  
    if(start->getRightChildNode() == NULL)  
        return getNodeNumber(start->getLeftChildNode()) + 1;  
    return getNodeNumber(start->getLeftChildNode()) +   
        getNodeNumber(start->getRightChildNode()) + 1;  
}  
/*层次遍历*/  
void BinarySearchTree::levelTreeWalk(Node *start)  
{  
    if(start == NULL)  
    {  
        cout << "这是一个空子树," << endl;  
        return;  
    }  
    /*定义一个数组来存放层次遍历过程中的节点指针,最大为MAXLENGTH*/  
    Node *B[MAXLENGTH + 1];  
    B[1] = start;/*根节点放到B[1]处*/  
    int nodeNumber = getNodeNumber(start);/*树中节点个数*/  
    int counter = 1;//已经放到数组B中的节点个数  
    int k = 1;/*在之后的每次循环中,counter之前有k个节点需要得到子节点放入数组B*/  
    int m,i;//寄存器值  
    while(counter < nodeNumber)  
    {  
        m = 0;  
        /*循环得到counter之前的k个节点它们的子节点*/  
        for(i = 1;i <= k;i ++)//k其实就是每一层中的节点个数  
        {  
            if(B[counter-k+i]->getLeftChildNode() != NULL)  
            {  
                m ++;  
                B[counter + m] = B[counter-k+i]->getLeftChildNode();  
            }  
            if(B[counter-k+i]->getRightChildNode() != NULL)  
            {  
                m ++;  
                B[counter + m] = B[counter-k+i]->getRightChildNode();  
            }  
        }  
        k = m;  
        counter = counter + k;  
    }  
    for(i = 1;i <= nodeNumber;i++)  
        cout << B[i]->getValue() << " ";  
}  
/*中序遍历:<<<<左根右>>>>*/  
void BinarySearchTree::inorderTreeWalk(Node *start)  
{  
    if(start != NULL)  
    {  
        inorderTreeWalk(start->getLeftChildNode());  
        cout << start->getValue() << " ";  
        inorderTreeWalk(start->getRightChildNode());  
    }  
}  
/*先序遍历:<<<<根左右>>>>*/  
void BinarySearchTree::preorderTreeWalk(Node *start)  
{  
    if(start != NULL)  
    {  
        cout << start->getValue() << " ";  
        preorderTreeWalk(start->getLeftChildNode());  
        preorderTreeWalk(start->getRightChildNode());  
    }  
}  
/*后序遍历:<<<<左右根>>>>*/  
void BinarySearchTree::postorderTreeWalk(Node *start)  
{  
    if(start != NULL)  
    {  
        preorderTreeWalk(start->getLeftChildNode());  
        preorderTreeWalk(start->getRightChildNode());  
        cout << start->getValue() << " ";  
    }  
}  
  
/*计算二叉搜索树的高度*/  
int BinarySearchTree::getTreeHeight()  
{  
    return getNodeHeight(getRootNode()) - 1;  
}  
/*计算节点start的高度*/  
int BinarySearchTree::getNodeHeight(Node *start)  
{  
    if(start == NULL)  
        return 0;  
    int leftChildLength = getNodeHeight(start->getLeftChildNode());  
    int rightChildLength = getNodeHeight(start->getRightChildNode());  
      
    /*这两个判断语句是把递归进行到二叉树的叶子节点进行判断并把 
       叶子节点的高度(本来为0)加一*/  
    if(max(leftChildLength,rightChildLength))  
        return leftChildLength + 1;  
    else  
        return rightChildLength + 1;  
}  
/*比较两个整型元素值大小,x<y返回false,x>=y返回true*/  
bool BinarySearchTree::max(int x,int y)  
{  
    if(x >= y)  
        return true;  
    else  
        return false;  
}  
  
/*得到节点start的后继节点,如果后继节点存在,则返回, 
   如果后继节点为自身,则返回null*/  
Node* BinarySearchTree::getTreeSuccessor(Node *start)  
{  
    if(start->getRightChildNode() != NULL)  
        return getMinimum(start->getRightChildNode());  
    Node *y = start->getParentNode();//叶子节点的情况  
    /*仍是二叉搜索树的性质决定*/  
    while(y != NULL && start == y->getRightChildNode ())  
    {  
        start = y;  
        y = y->getParentNode();  
    }  
    return y;  
}  
/*得到start的前驱节点如果前驱节点存在,则返回,如果前驱节点 
   为自身,则返回null*/  
Node* BinarySearchTree::getTreePredessor(Node *start)  
{  
    if(start->getLeftChildNode() != NULL)  
        return getMaximum(start->getLeftChildNode());  
    Node *y = start->getParentNode();  
    while(y != NULL && start == y->getRightChildNode())  
    {  
        start = y;  
        y = y->getParentNode();  
    }  
    return y;  
}  
  
/*搜索数的查找,如果k存在于搜索树中,则返回给节点,否则返回null*/  
Node* BinarySearchTree::treeSearch1(Node *start,int k)  
{  
    Node *temp = start;  
    if(temp == NULL || k == temp->getValue())  
        return temp;  
    if(k < start->getValue())  
        return treeSearch1(temp->getLeftChildNode(),k);  
    else  
        return treeSearch1(temp->getRightChildNode(),k);  
}  
/*搜索的while迭代版本*/  
Node* BinarySearchTree::treeSearch2(Node *start,int k)  
{  
    Node *temp = start;  
    while(temp != NULL && k != temp->getValue())  
    {  
        if(k < temp->getValue())  
            temp = temp->getLeftChildNode();  
        else   
            temp = temp->getRightChildNode();  
    }  
    return temp;  
}  
          





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值