Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一个简单的二叉搜索树(C++实现)

一个简单的二叉搜索树(C++实现)

作者头像
xcywt
发布于 2022-05-09 06:25:46
发布于 2022-05-09 06:25:46
27700
代码可运行
举报
文章被收录于专栏:xcywtxcywt
运行总次数:0
代码可运行

参考:http://www.cnblogs.com/skywang12345/p/3576373.html

这里主要就是自己实现的代码,删除动作有点不一样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef __BSTREE_H__
#define __BSTREE_H__
/*
参考:http://www.cnblogs.com/skywang12345/p/3576373.html

这里是介绍二叉查找树

1)若任意结点的左子树不空,则左子树上所有的结点的值均小于它的根结点的值
2)若任意结点的右子树不空,则左子树上所有的结点的值均大于它的根结点的值
3)任意结点的左右子树也分别为二叉查找树
4)没有键值相等的结点(但是这里实现的可以有相同key值的结点)。当键值相同时,插入在右子树中。
*/
#include<iomanip>
#include<iostream>
using namespace std;

template <class T>
class BSTNode
{
public:
    T key;
    BSTNode *left;
    BSTNode *right;
    BSTNode *parent;

    BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):key(value), parent(p),left(l), right(r)
    {
        //cout << "BSTNode() +++ " << endl;
    }
};

template <class T>
class BSTree
{
private:
public:
    BSTNode <T> *mRoot;

public:
    BSTree();
    ~BSTree();

    void insert(T key);
    void print();
    void preOrder();
    T maximum();
    T minimum();
    int remove(T data);
    void destory();
    
private:
    void insert(BSTNode<T> *&tree, BSTNode<T> *z);
    void print(BSTNode<T> *tree, T key, int direction);
    void preOrder(BSTNode<T> *tree) const;
    BSTNode<T>*  maximum(BSTNode<T> *tree);
    BSTNode<T>*  minimum(BSTNode<T> *tree);
    BSTNode<T>* getNode(T data);
    void destory(BSTNode<T> *tree);
};


template <class T>
BSTree<T>::BSTree()
{
    mRoot = NULL;
}

template <class T>
BSTree<T>::~BSTree()
{

}

template <class T>
void BSTree<T>::insert(T key)
{
    BSTNode<T> *z = new BSTNode<T>(key, NULL, NULL, NULL);
    if(z)
    {
        insert(mRoot, z);
    }
}

// 这里的&是引用传递
template <class T>
void BSTree<T>::insert(BSTNode<T> *&tree, BSTNode<T> *pNode) 
{
    BSTNode<T> *pIndex = NULL;
    BSTNode<T> *pTemp = tree;

    // 先找到插入的位置
    while(pTemp != NULL)
    {
        pIndex = pTemp;
        if(pNode->key < pTemp->key)
            pTemp = pTemp->left;
        else
            pTemp = pTemp->right;
    }

    pNode->parent = pIndex;
    if(!pIndex)
        tree  = pNode;
    else if(pNode->key < pIndex->key)
        pIndex->left = pNode;
    else
        pIndex->right = pNode;

}



template <class T>
void BSTree<T>::print()
{
    if(mRoot)
    {
        print(mRoot, mRoot->key, 0);
    }
}

/*
key:结点的键值
direction:
    -1 - 表示为左孩子
    0 - 表示为根节点
    1 - 表示为左孩子
*/
template <class T>
void BSTree<T>::print(BSTNode<T> *tree, T key, int direction)
{
    if(tree)
    {
        if(direction == 0)
            cout << setw(2) << tree->key << " is root" << endl;
        else
            cout << setw(2) << tree->key << " is " << setw(2) << key << "'s " << setw(12) << (direction==1?"right child":"left child") << endl;

        print(tree->left, tree->key, -1);
        print(tree->right, tree->key, 1);
    }
}

template <class T>
void BSTree<T>::preOrder()
{
    cout << "preOrder: ";
    preOrder(mRoot);
    cout << endl;
}


// 这里是遍历。
template <class T>
void BSTree<T>::preOrder(BSTNode<T> *tree) const
{
    if(tree)
    {
        #if 1 // 前置遍历
        cout << tree->key << " "; 
        preOrder(tree->left);
        preOrder(tree->right);
        #endif
        
        #if 0 // 中序遍历
        preOrder(tree->left);
        cout << tree->key << " ";     
        preOrder(tree->right);
        #endif

        #if 0 // 后序遍历
        preOrder(tree->left);    
        preOrder(tree->right);
        cout << tree->key << " ";     
        #endif
    }
}

// 找二叉查找树中的最大值,返回key值最大的那个结点
template <class T>
BSTNode<T> * BSTree<T>::maximum(BSTNode<T> *tree)
{
    BSTNode<T> *temp = tree;
    if(temp)
    {
        while(temp->right)
        {
            temp = temp->right;
        }

        return temp;
    }
    else
    {
        return NULL;
    }
}


// 找二叉查找树中的最小值,返回key值最小的那个结点
template <class T>
BSTNode<T> * BSTree<T>::minimum(BSTNode<T> *tree)
{
    BSTNode<T> *temp = tree;
    if(temp)
    {
        while(temp->left)
        {
            temp = temp->left;
        }

        return temp;
    }
    else
    {
        return NULL;
    }
}

template <class T>
T BSTree<T>::maximum()
{
    BSTNode<T> *temp = maximum(mRoot);
    if(temp)
    {
        return temp->key;
    }

    return NULL;
}

template <class T>
T BSTree<T>::minimum()
{
    BSTNode<T> *temp = minimum(mRoot);
    if(temp)
    {
        return temp->key;
    }

    return NULL;
}

// 通过data去获取结点。
template <class T>
BSTNode<T>* BSTree<T>::getNode(T data)
{
    BSTNode<T> *temp = mRoot;
    if(!temp)
    {
        return NULL;
    }

    while(temp)
    {
        if(temp->key == data)
            return temp;
        else if(temp->key < data)
            temp = temp->right;
        else
            temp = temp->left;
    }

    return NULL;
}


// 这个仅仅是用来打印结点的。测试用的
template <class T>
void showNode(BSTNode<T>* node)
{
        if(node->parent)
        {
            cout << "    parent: " << node->parent->key << endl;
        }
        else
        {
            cout << "    parent is NULL" << endl;
        }

        if(node->left)
        {
            cout << "    left: " << node->left->key << endl;
        }
        else
        {
            cout << "    left is NULL" << endl;
        }

        if(node->right)
        {
            cout << "    right: " << node->right->key << endl;
        }
        else
        {
            cout << "    right is NULL" << endl;
        }
}

/*
参考:http://blog.csdn.net/zq17865815296/article/details/52658908
先说一下如何删除二叉树查找树的节点吧。总共有三种情况
1.被删除的节点是叶子节点,这时候只要把这个节点删除,再把指向这个节点的父节点指针置为空就行
2.被删除的节点有左子树,或者有右子树,而且只有其中一个,那么只要把当前删除节点的父节点指向被删除节点的左子树或者右子树就行。
3.被删除的节点既有左子树而且又有右子树,这时候需要把左子树的最右边的节点或者右子树最左边的节点提到被删除节点的位置,为什么要这样呢,
根据二叉查找树的性质,父节点的指针一定比所有左子树的节点值大而且比右子树的节点的值小,为了删除父节点不破坏二叉查找树的平衡性,
应当把左子树最大的节点或者右子树最小的节点放在父节点的位置,这样的话才能维护二叉查找树的平衡性。(我是找的右子树的最小节点)
*/
template <class T>
int BSTree<T>::remove(T data)
{
    cout << "remove :" << data << endl;
    BSTNode<T>* node = getNode(data);// 这里要找到要删除的结点。
    if(node)
    {
        showNode(node);
        if(node->parent == NULL)// 删除根结点
        {
            // 这里选择的是把左子树接到右子树中key最小的那个结点的左结点上。还有一种是把右子树接到左子树的key最大的那个右结点上
            BSTNode<T> *temp = minimum(node->right);
            if(temp)
            {
                temp->left = node->left;
                mRoot = node->right;// 要更新根节点
            }
            delete node;
            node = NULL;
            return 0;
        }

        if((node->right == NULL) && (node->left == NULL)) // 删除叶子结点
        {
            if(node->parent->left == node)
            {
                node->parent->left = NULL;
            }
            else
            {
                node->parent->right = NULL;
            }
        }
        else if(node->right && node->left) // 删除有两个子节点的
        {
            BSTNode<T> *temp = minimum(node->right); // 获取后继结点,这个结点一定是没有左子树的。
            cout << "have left and right child, mimmum :" << temp->key << endl;
            if(temp == temp->parent->left) // 后继结点如果是左结点,就将它的右子树接到它父亲的左子树中。
            {
                temp->parent->left = temp->right;
            }
            else // 后继结点如果是右结点,就将它的右子树接到它父亲的右子树中。
            {
                temp->parent->right = temp->right;
            }
            node->key = temp->key; // 把后继结点的key保存在要删除的结点中
            delete temp; // 其实是删除的后继结点。
            temp = NULL;
        }
        else // 删除只有一个只有一个子结点。
        {
            if(node->right) // 有右子节点
            {
                if(node->parent->left == node)
                {
                    node->parent->left = node->right;
                }
                else
                {
                    node->parent->right = node->right;
                }
            }
            else
            {
                if(node->parent->left == node)
                {
                    node->parent->left = node->left;
                }
                else
                {
                    node->parent->right = node->left;
                }    
            }        
            delete node;
            node = NULL;
        }

    }
    else
    {
        return -1;
    }

    return 0;
}


template <class T>
void BSTree<T>::destory(BSTNode<T> *tree)
{
    if(tree)
    {
        if(tree->left)
            destory(tree->left);
        if(tree->right)
            destory(tree->right);
        delete tree;
        tree = NULL;
    }
}

template <class T>
void BSTree<T>::destory()
{
    destory(mRoot);
}

#endif // __BSTREE_H__

下面是测试代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
#include"bstree.h"
using namespace std;

/*
可以插入相同的,会插入在右子树中。
*/
void fun()
{
    cout << "fun() +++ " << endl;
    int i = 0, len = 0;
    BSTree<int>* tree = new BSTree<int>;
    if(tree->mRoot == NULL)
        cout << "fun() mRoot is NULL" << endl;
    int arr[] = {2, 15, 4, 44, 30, 36, 50, 12, 55, 414};
    int count = sizeof(arr)/sizeof(int);
    for(int i = 0; i<count; i++)
    {
        tree->insert(arr[i]);
    }
    tree->insert(125);

    tree->insert(5);
    tree->preOrder();
    int maxkey = tree->maximum();
    cout << "Max key = " << maxkey << endl;
    int minkey = tree->minimum();
    cout << "Min key = " << minkey << endl;
    tree->remove(12);
    tree->remove(2);

    tree->preOrder();
    //tree->print();

    tree->destory();
    cout << "fun() --- " << endl;
}

int main()
{
    cout << "hello world" << endl;
    fun();
    return 0;
}

注意:上面只有bstree.h,没有bstree.cpp。

关于为何C++的模板类声明和实现要放在一起可以参考:http://www.cnblogs.com/xcywt/p/8039574.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-01-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【C++高阶】二叉搜索树的全面解析与高效实现
二叉搜索树(BST,Binary Search Tree)又称二叉排序树,是一种特殊的二叉树,它或者是一棵空树,或者是具有以下性质的二叉树:
IsLand1314
2024/10/15
1400
【C++高阶】二叉搜索树的全面解析与高效实现
二叉搜索树的模拟实现
由于这些特性,就使得在该树中查找值非常的方便,大于目前节点的值,就遍历右子树;小于目前节点的值,就遍历左子树。其次,二叉排序树还有以下特点:不可出现重复数据
用户11039529
2024/08/17
1040
二叉搜索树的模拟实现
二叉查找树 C++实现(含完整代码)
       一般二叉树的查找是通过遍历整棵二叉树实现,效率较低。二叉查找树是一种特殊的二叉树,可以提高查找的效率。二叉查找树又称为二叉排序树或二叉搜索树。
Tencent JCoder
2022/05/06
7170
二叉查找树 C++实现(含完整代码)
C++两种方法实现二叉搜索树
a.从根节点出发,如果要找的值大于当前的节点值,去右边找, 如果要找的值小于当前的节点值,则去左边找, 如果相等则表示找到了。 b.如果值存在的话,最多查找高度次
Yui_
2024/10/15
930
C++两种方法实现二叉搜索树
【C++进阶学习】第五弹——二叉搜索树——二叉树进阶及set和map的铺垫
在我们目前的学习中,二叉搜索树最重要的用途就是key--val模型,KV模型就是每一个key值都对应一个val值,这样就形成一个<key,val>键值对,这样的应用在生活中是非常常见的
GG Bond1
2024/07/20
1000
【C++进阶学习】第五弹——二叉搜索树——二叉树进阶及set和map的铺垫
C++之搜索二叉树
本文介绍了二叉搜索树的相关概念,主要介绍了如何使用和实现搜索二叉树以及搜索二叉树具体的例题练习。
摘星
2023/04/28
5440
C++之搜索二叉树
【C++进阶】探秘二叉搜索树
本篇文章将介绍一种功能更加强大的二叉树——二叉搜索树。 相比于普通的二叉树,二叉搜索树在很多方面都有优势,尤其是在查找数据上效率明显提高,并且通过中序遍历二叉搜索树它所存储的数据是有序的。
_小羊_
2024/10/16
600
【C++进阶】探秘二叉搜索树
C++:二叉搜索树
二叉搜索树(BST, Binary Search Tree)又叫做二叉排序树,它可以是一颗空树,其性质如下:
二肥是只大懒蓝猫
2023/03/30
2870
C++:二叉搜索树
【C++的剃刀】我不允许你还不会二叉搜索树BST
1. K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到 的值。 比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:
小文要打代码
2024/10/16
990
【C++的剃刀】我不允许你还不会二叉搜索树BST
C++二叉搜索树与KV模型
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值 它的左右子树也分别为二叉搜索树
有礼貌的灰绅士
2023/04/12
4220
C++二叉搜索树与KV模型
今天你学C++了吗?——二叉搜索树的拓展
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个人主页✨✨✨✨✨✨
用户11352420
2025/03/26
960
今天你学C++了吗?——二叉搜索树的拓展
二叉树进阶之二叉搜索树
还有一个注意的点: 二叉搜索树的中序遍历一定可以是一个有序的序列,并且再插入节点后依旧是一个二叉搜索树的结构!
ahao
2024/03/19
880
二叉树进阶之二叉搜索树
C++【二叉搜索树】
时隔多日,又回到了二叉树的学习中,在 C++ 进阶中,我们首先要学习 二叉搜索树,重新捡起二叉树的相关知识,然后会学习 AVL 树 及 红黑树,最后会用红黑树封装实现库中的 set 和 map,作为 C++ 进阶中的难度最高峰,整个学习过程非常艰辛,但 关关难过关关过,让我们先从比较简单的 二叉搜索树 开始学习
北 海
2023/07/01
1910
C++【二叉搜索树】
【C++篇】数据之林:解读二叉搜索树的优雅结构与运算哲学
二叉搜索树(Binary Search Tree, BST)是一种重要的数据结构,广泛应用于计算机科学中的数据管理和检索。它允许高效的查找、插入和删除操作,且在最佳情况下能够达到对数时间复杂度。
半截诗
2025/05/29
1350
【C++篇】数据之林:解读二叉搜索树的优雅结构与运算哲学
【C++】二叉搜索树
int a[] = {8, 3, 1, 10, 6, 4, 7, 14, 13};
啊QQQQQ
2024/11/19
1470
【C++】二叉搜索树
【C++航海王:追寻罗杰的编程之路】一篇文章带你了解二叉搜索树
二叉搜索树(BST, Binary Search Tree)又称二叉排序树或二叉查找树,它或者是一棵空树,或者具有以下性质的二叉树:
枫叶丹
2024/06/04
1150
【C++航海王:追寻罗杰的编程之路】一篇文章带你了解二叉搜索树
【C++】二叉搜索树 - 从基础概念到代码实现
最优情况下,二叉搜索树为完全二叉树(或者接近完全二叉树),其高度为:log2 N 最差情况下,二叉搜索树退化为单指树,其高度为:N 所以综合而言二叉搜索树增删查改的时间复杂度为:O(N)
_孙同学
2025/04/27
1310
【C++】二叉搜索树 - 从基础概念到代码实现
种树:二叉树、二叉搜索树、AVL树、红黑树、哈夫曼树、B树、树与森林
树是我们计算机中非常重要的一种数据结构,同时使用树这种数据结构,可以描述现实生活中的很多事物,例如家 谱、单位的组织架构、等等。 树是由n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就 是说它是根朝上,而叶朝下的。
看、未来
2020/08/25
1.2K0
种树:二叉树、二叉搜索树、AVL树、红黑树、哈夫曼树、B树、树与森林
二叉搜索树实现教程:用C++实现数据存储与查找
最优情况下,⼆叉搜索树为完全⼆叉树(或者接近完全⼆叉树),其⾼度为:O(log2N) 最差情况下,⼆叉搜索树退化为单支树(或者类似单⽀),其⾼度为:O(N /2) 所以综合而言⼆叉搜索树增删查改时间复杂度为:O(N) 那么这样的效率显然是无法满⾜我们需求的,在后续当中还有平衡⼆叉搜索树AVL树和红⿊树,才能适用于我们在内存中存储和搜索数据。
用户11286421
2024/11/21
1110
二叉搜索树实现教程:用C++实现数据存储与查找
【数据结构】二叉搜索树BSTree
(注意:不能插入重复的元素,并且每次插入都是要定位到空节点的位置;我们先定义一个 cur从root开始,比较元素的大小:若插入的元素比当前位置元素小就往左走,比当前位置元素大就往右走,直到为空,相等就不能插入了;同时定义一个parent去记录当前 cur的前一个位置,最后判断cur是parent的左子树还是右子树即可)
平凡的人1
2023/10/15
2650
【数据结构】二叉搜索树BSTree
推荐阅读
相关推荐
【C++高阶】二叉搜索树的全面解析与高效实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验