二叉排序树 C++

二叉排序树(Binary Sort Tree),又称二叉查找树。

1、若左子树不为空,则左子树上所有结点的值均小于他的根结构的值;

2、若右子树不为空,则右子树上所有结点的值均大于他的根结构的值;

3、他的左、右子树也分别为二叉排序树。

使用中序遍历时,二叉排序树的输出顺序是由小到大的有序数列。

二叉排序树类的: C++ 实现:

#include<iostream>
using namespace std;

template<class T>
struct TreeNode
{
    T element;
    TreeNode<T>*parent, *lnode, *rnode;
    TreeNode(){ parent = lnode = rnode = NULL; }
    TreeNode(const T& key)
    {
        element = key;
        parent = lnode = rnode = NULL;
    }
};

template<class T>
class BStree
{
public:
    BStree() :root(NULL){}
    //获取根结点
    TreeNode<T>* Getroot(){ return root; }
    //中序遍历
    void Inorder(TreeNode<T>*node);
    //递归查找
    TreeNode<T>* TreeSearch(TreeNode<T>*node, T key);
    //迭代查找
    TreeNode<T>* IterativeTreeSearch(TreeNode<T>*node, T key);
    //插入元素
    void TreeInsert(T key);
    //最大值
    TreeNode<T>*TreeMax(TreeNode<T>*node);
    //最小值
    TreeNode<T>*TreeMin(TreeNode<T>*node);
    //查找前驱结点
    TreeNode<T>*TreePredecessor(T key);
    //查找后继结点
    TreeNode<T>*TreeSuccessor(T key);
    //用结点 nodeM 替换结点 nodeN,删除操作的辅助函数
    void TransPlant(TreeNode<T>*nodeM, TreeNode<T>*nodeN);
    //删除结点是key的元素
    void Delete(T key);                 

private:
    TreeNode<T>* root;
};

//中序遍历
template<class T>
void BStree<T>::Inorder(TreeNode<T>*node)
{
    if (node == NULL)
        return;
    else
    {
        Inorder(node->lnode);
        cout << node->element << " ";
        Inorder(node->rnode);
    }
}

//递归查找,调用时,node的初始值是root
template<class T>
TreeNode<T>* BStree<T>::TreeSearch(TreeNode<T>*node, T key)
{
    if ((node == NULL) || (key == node->element))
    {
        if (node == NULL)
            cout << "不存在该元素" << endl;
        else
            cout << "存在该元素" << endl;
        return node;
    }

    if (key > node->element)
         return TreeSearch(node->rnode,key);
    else
        return TreeSearch(node->lnode,key);
}

//迭代查找,node参数为root(根结点)
template<class T>
TreeNode<T>* BStree<T>::IterativeTreeSearch(TreeNode<T>*node, T key)
{
    while (node != NULL&&key != node->element)
    {
        if (key < node->element)
            node = node->lnode;
        else
            node = node->rnode;
    }
    if (node == NULL)
        cout << "不存在该元素" << endl;
    else
        cout << "存在该元素" << endl;
    return node;
}

//插入元素
template<class T>
void BStree<T>::TreeInsert(T key)
{
    TreeNode<T>* y = NULL;
    TreeNode<T>* x = root;
    TreeNode<T>* z = new TreeNode<T>(key);  //将需要插入的元素放入新建立的结点中
    while (x != NULL)  //找到要插入位置的双亲结点
    {
        y = x;
        if (z->element < x->element)
            x = x->lnode;
        else
            x = x->rnode;
    }
    z->parent = y;
    if (y == NULL)    // 判断要插入的是:左 或 右结点
        root = z;
    else if (z->element>y->element)
        y->rnode = z;
    else
        y->lnode = z;
}

//最大值,一直遍历所给结点的右子树
template<class T>
TreeNode<T>*BStree<T>::TreeMax(TreeNode<T>*node)
{
    while (node->rnode != NULL)
        node = node->rnode;
    cout << "最大值是:" << node->element << endl;
    return node;
}

// 最小值,一直遍历所给结点的左子树
template<class T>
TreeNode<T>*BStree<T>::TreeMin(TreeNode<T>*node)
{
    while (node->lnode != NULL)
        node = node->lnode;
    cout << "最小值是:" << node->element << endl;
    return node;
}

//查找后继结点
template<class T>
TreeNode<T>*BStree<T>::TreeSuccessor(T key)
{
    TreeNode<T>* x = TreeSearch(root, key);    //查找关键字key所对应的结点
    if (x->rnode != NULL)                   //如果结点x存在右结点,则直接查找右结点为跟的最小值
        return TreeMin(x->rnode);
    /*若,不存在右结点
    1、if(x==x->parent->lnode), 则 x 的后继元素即是 x 的双亲结点
    2、if(x==x->parent->rnode),则 x 的双亲 y 及 y->lnode均小于x,
    直到 x 的某一祖先 Yn 为左节点时,Yn 的双亲即是 x 的后继元素
    */
    TreeNode<T>*y = x->parent;
    while (y != NULL&&x == y->rnode)
    {
        x = y;
        y = y->parent;
    }
    return y;
}

//查找前驱结点
template<class T>
TreeNode<T>*BStree<T>::TreePredecessor(T key)
{
    TreeNode<T>* x = TreeSearch(root, key);    //查找关键字key所对应的结点
    if (x->lnode != NULL)
        return TreeMax(x->lnode);    //若x的左子树不为空,查找左子树的最大值
    TreeNode<T>*y = x->parent;
    while (y != NULL&&x == y->lnode)
    {
        x = y;
        y = y->lnode;
    }
    return y;
}

//用结点 m 替换结点 n,不包括v的左右子树的更新
template<class T>
void BStree<T>::TransPlant(TreeNode<T>*nodeM, TreeNode<T>*nodeN)
{
    if (nodeN->parent == NULL)
        root = nodeM;
    else if (nodeN == nodeN->parent->lnode)   // nodeN 是左结点,更新nodeN->parent 的左结点
        nodeN->parent->lnode = nodeM;
    else
        nodeN->parent->rnode = nodeM;
    if (nodeM != NULL)
        nodeM->parent = nodeN->parent;
}

//删除结点关节字是key的元素
template<class T>
void BStree<T>::Delete(T key)
{
    TreeNode<T>*z = IterativeTreeSearch(root,key);    //z 是要删除的结点
    if (z->lnode == NULL)
        TransPlant(z->rnode,z);
    else if (z->rnode == NULL)
        TransPlant(z->lnode,z);
    else
    {
        //找要删除结点的后继元素,
        TreeNode<T>*y = TreeMin(z->rnode);   //类的成员函数在调用成员函数(模板)时,直接写函数名,不需要<T>
        if (y->parent != z)
        {
            TransPlant(y->rnode, y);         //用 y 的右结点替代 y
            y->rnode = z->rnode;             //y的右结点 = z的右结点
            y->rnode->parent = y;
        }
        TransPlant(y,z);              //用 y替代z
        y->lnode = z->lnode;
        y->lnode->parent = y;
    }
}

测试代码:注:生成的数组a[20]中,若有重复的数字,会有错误。

#include<iostream>
#include"stdlib.h"
#include<time.h>
#include"BSTreecpp.cpp"
using namespace std;

int main()
{
    //生成要插入的数据
    int max = 500;
    int min = 0;
    srand((unsigned)time(NULL));
    int a[20] = {};
    int x = 0;
    for (int i = 0; i < 20; i++)
    {
        a[i] = rand() % (max - min) + min;
        cout << a[i] << " ";
    }
    cout << "输入数据:" << endl;
    BStree<int>myTree;
    for (int i = 0; i < 20; i++)
        myTree.TreeInsert(a[i]);
    myTree.Inorder(myTree.Getroot());
    cout << "二叉搜索树中序遍历:" << endl;
    //验证递归查找
    int b = 0;
    TreeNode<int>* A = myTree.TreeSearch(myTree.Getroot(), b);
    //验证迭代查找
    TreeNode<int>* B = myTree.IterativeTreeSearch(myTree.Getroot(), a[2]);
    //验证求取最大值
    TreeNode<int>* C = myTree.TreeMax(myTree.Getroot());
    //验证求取最小值
    TreeNode<int>* D = myTree.TreeMin(myTree.Getroot());
    //求取后继结点
    TreeNode<int>*E = myTree.TreeSuccessor(a[1]);
    cout << a[1] << " 的后继元素是:" << E->element << endl;
    //求取前驱结点
    TreeNode<int>*F = myTree.TreePredecessor(a[3]);
    cout << a[3] << " 的前驱元素是:" << F->element << endl;
    //验证删除结点
    myTree.Delete(a[0]);
    myTree.Inorder(myTree.Getroot());
    cout << "二叉搜索树删除元素后:" << endl;
    system("pause");
    return 0;
}

时间: 2024-08-09 19:53:15

二叉排序树 C++的相关文章

【LeetCode】96. Unique Binary Search Trees-唯一二叉排序树的个数

一.描述: 二.思路: BST(二叉排序树):中序遍历的结果为非递减序列,并且节点(个数和值)相同的不同二叉树的中序遍历结果都相同: 当左子树的节点个数确定后,右子树的个数也随之确定: 当节点个数为0或1时,二叉树只有1种,表示为f(0)=1,f(1)=f(0)*f(0): 当节点个数为2时,总的种类数=左子树为空f(0)*右子树不为空f(1)+左子树不为空f(1)*右子树为空f(0),即f(0)*f(1)+f(1)*f(0)=2种: 当节点个数为3时,有左子树为空f(0)*右子树不为空f(2)

16.二叉排序树

转载请表名出处:http://blog.csdn.net/u012637501 一.二叉排序树 如果要查找的数据集是有序线性表且是顺序存储的,查找可以用折半.插值.斐波那契等查找算法来实现.然后,由于有序,当我们在插入和删除操作上,就需要耗费大量的时间.下面将要学习的二叉排序树,就是一种既可以使得插入和删除效率不错,又可以比较高效率地实现查找的算法.为此,构造一棵二叉排序树的目的并不是为了排序,而是为了提供查找和插入删除关键字的速度. 1.二叉排序树概念 二叉排序树(Binary Sort Tr

腾讯笔试题:满二叉排序树,任给3个子节点,找他们最大的公共父节点

腾讯笔试题出现了和这个类似的题目,没做出来,现在来好好解决这个问题吧,先从基本的开始. 先吐槽一下:感觉算法设计什么的,真的超级难,也许是我头脑太笨,转不过弯来吧,呵呵. 题目是这样的:一棵满二叉排序树,有K层,节点的值依次为 1~2k-1.现在告诉你树的高度是4层,给定你3个节点,比如9,11, 13,那么最大的公共父节点是12. 现在想起来这题我已经想出来一半了呀,但是大概人在紧张的时候大脑会思维短路,跳不出原有的思维陷阱.想法是这样的: 1. 首先是从根节点开始,如果给的三个叶节点的值其中

九度oj 题目1467:二叉排序树

题目1467:二叉排序树 时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:4102 解决:1644 题目描述: 二叉排序树,也称为二叉查找树.可以是一颗空树,也可以是一颗具有如下特性的非空二叉树: 1. 若左子树非空,则左子树上所有节点关键字值均不大于根节点的关键字值:        2. 若右子树非空,则右子树上所有节点关键字值均不小于根节点的关键字值:        3. 左.右子树本身也是一颗二叉排序树. 现在给你N个关键字值各不相同的节点,要求你按顺序插入一个初始为空树的二叉

[二叉查找树] 二叉排序树

题目描述 输入一系列整数,建立二叉排序数,并进行前序,中序,后序遍历. 输入 输入第一行包括一个整数n(1<=n<=100).接下来的一行包括n个整数. 输出 可能有多组测试数据,对于每组数据,将题目所给数据建立一个二叉排序树,并对二叉排序树进行前序.中序和后序遍历.每种遍历结果输出一行.每行最后一个数据之后有一个空格. 样例输入 1 2 2 8 15 4 21 10 5 39 样例输出 2 2 2 8 15 8 15 15 8 21 10 5 39 5 10 21 39 5 10 39 21

二叉排序树(BST)的建立

给一个非递归的吧. 1 /* 2 已知,二叉树存储结构定义见bstree.h,请编写一个算法函数bstree creatBstree(int a[],int n), 3 以数组a中的数据作为输入建立一棵二叉排序树,并将建立的二叉排序树进行中序遍历. 4 (提示,a中的原始数据可从data1.txt中读入,实验代码详见lab9_05.c) 6 */ 7 8 #include "Arrayio.h" 9 #include "bstree.h" 10 #define N

重温数据结构:二叉排序树的查找、插入、删除

读完本文你将了解到: 什么是二叉排序树 Binary Sort Tree BST 二叉排序树的关键操作 查找 插入 删除 运行代码测试 一道面试题 总结 Thanks 我们知道,二分查找可以缩短查找的时间,但是有个要求就是 查找的数据必须是有序的.每次查找.操作时都要维护一个有序的数据集,于是有了二叉排序树这个概念. 上篇文章 我们介绍了 二叉树 的概念,二叉树有左右子树之分,想必在区分左右子树时有一定的规则. 现在我们来介绍二叉树的一种特殊形式 - 二叉排序树,了解它的区分策略及常用操作. 什

二叉查找树 _ 二叉排序树 _ 二叉搜索树_C++

一.数据结构背景+代码变量介绍 二叉查找树,又名二叉排序树,亦名二叉搜索树 它满足以下定义: 1.任意节点的子树又是一颗二叉查找树,且左子树的每个节点均小于该节点,右子树的每个节点均大于该节点. 2.由1可推出,任意节点的左孩子小于该节点,右孩子大于该节点 以上讨论的是左(右)孩子(子树)存在的情况 它的中序遍历是一个升序的排序 在参考代码中,我们定义有: 主程序中,k代表插入或删除或查找的节点的值 root,根节点位置:a[i],第 i 号节点的值:cl[i],第 i 号节点左孩子的位置:cr

【转】B树、B-树、B+树、B*树、红黑树、 二叉排序树、trie树Double Array 字典查找树简介

B  树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中:否则,如果查询关键字比结点关键字小,就进入左儿子:如果比结点关键字大,就进入右儿子:如果左儿子或右儿子的指针为空,则报告找不到相应的关键字: 如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性

C语言实现二叉排序树

今天应同学之邀,写了一个二叉排序树,有不足的地方请指正,还有就是实现那个栈中序遍历功能,我也没弄懂,就根据自己的理解写吧,顺便扩展一点双重指针的知识,其实用C语言最烦指针了,感觉用java就不用考虑,这个程序是以'#'结尾的二叉排序树. /*(双重指针 BSTree *T)问:数据结构中 二叉树建立结点为什么用 双重指针?详细解释下双重指针 答:指针的指针.因为树的结点要用指针描述.如果只用指针,作形参传给建立结点的函数,这个指针值传给了函数栈中的内存,函数返回后,函数栈销毁,不能获得结点.而用