C++实现二叉搜索树的常用操作

实现操作

(1)二叉搜索树的建立

(2)二叉搜索树的插入

(3)二叉搜索树的三种递归遍历(前序、中序和后续)

(4)二叉搜索树的三种非递归遍历(前序、中序和后续)

(5)二叉搜索树的逐层打印

(6)搜索某一个字符(递归算法)

(7)搜索一个字符(非递归算法)

(8)查找最大元素

(9)查找最小元素

有时间再实现:

(10)二叉搜索树的前驱和后继查找

(11)二叉搜索树的删除

源码分析:

#include <iostream>
#include <stack>
#include <queue>

using namespace std;
/*
*创建二叉搜索树结点类型,一个char数据,三个指针(左孩子、右孩子和双亲)
* 双亲指针(parent)在二叉搜索树的插入和删除操作、获取前驱和后继操作中都会用到,二叉树遍历用不到
*/
class binary_tree_node
{
public:
    /*全部声明为public,方便直接访问,注意初始化!*/
    binary_tree_node(char a):data(a),left_child(NULL),right_child(NULL),parent(NULL){};
    ~binary_tree_node(){};
    char data;
    binary_tree_node *left_child;
    binary_tree_node *right_child;
    binary_tree_node *parent;
};
/*
 *创建二叉搜索树类型,数据成员为根结点的指针
 * 通过不断插入结点的方法创建二叉搜索树
 * 二叉搜索树的遍历方法和普通二叉树的遍历没什么区别
*/
class binary_tree
{
public:
    /*自定义构造函数,形参为二叉搜索树的结点数量,注意初始化*/
    binary_tree(unsigned int size):root(NULL),_size(size){};
    ~binary_tree(){};
    /*二叉搜索树的创建,调用insert_node()插入结点,按照二叉搜索树的大小特性插入*/
    void create_binary_tree();
        binary_tree_node* get_root(); //获取根结点
    void inorder_tree_walk(binary_tree_node* node);//中序遍历的递归算法
    void insert_node(binary_tree_node *node); //通过比较结点关键字段的大小插入结点
    void preorder_tree_walk(binary_tree_node* node);//前序遍历的递归算法
    void postorder_tree_walk(binary_tree_node* node);//后续遍历的递归算法
    void inorder_tree_walk2(binary_tree_node* node);//中序遍历的非递归算法
    void preorder_tree_walk2(binary_tree_node* node);//前序遍历的非递归算法
    void postorder_tree_walk2(binary_tree_node* node);//后续遍历的非递归算法
    void levelorder_tree_walk(binary_tree_node* node);//逐层打印二叉树
    /* part II*/
    binary_tree_node* search(char a);//搜索一个元素,非递归
    binary_tree_node* search2(binary_tree_node* node, char a);//递归搜索一个元素
    char max();//找最大元素
    char min();//找最小元素
protected:
    void visit(binary_tree_node* node);//打印结点

private:
    binary_tree_node *root;//根结点指针
    unsigned int _size;//二叉搜索树的结点数量

};
/*获取根结点*/
binary_tree_node* binary_tree::get_root()
{
    return root;
}
/*打印结点关键字*/
void binary_tree::visit(binary_tree_node* node)
{
    cout<<node->data<<" ";
}
/*根据关键字大小插入新结点
*从根结点开始比较,比根节点小进入左子树,比根节点大进入右子树,逐步往叶子结点方向寻找到新结点的位置
* 再根据关键字大小挂在左边或者右边,设置好三个指针
*/
void binary_tree::insert_node(binary_tree_node* node)
{
    binary_tree_node *tmp1 = root;
    binary_tree_node *tmp2 = NULL;
    while(tmp1!=NULL)
    {
        tmp2=tmp1;
        if(node->data < tmp1->data)
            tmp1=tmp1->left_child;
        else
            tmp1=tmp1->right_child;
    }

    node->parent=tmp2;
    if(tmp2==NULL)
        root=node;
    else if(node->data < tmp2->data)
        tmp2->left_child=node;
    else
        tmp2->right_child=node;

}
/*
 * 每次输入一个字符创建一个结点,再把这个结点插入到二叉搜索树的叶子结点上
 * 如果根节点不存在,新结点就设为根节点
*/
void binary_tree::create_binary_tree()
{
    for(unsigned int i=0;i<_size;++i)
    {
        cout<<"input a charoctor"<<endl;
        char data;
        cin>>data;
        binary_tree_node *node = new binary_tree_node(data);
        insert_node(node);
    }

}
/*中序遍历的递归算法
 * 形参为根节点
 * 中序遍历的顺序为(左子树->根节点->右子树)
*/
void binary_tree::inorder_tree_walk(binary_tree_node* node)
{
    if(node!=NULL)
    {
        inorder_tree_walk(node->left_child);
        visit(node);
        inorder_tree_walk(node->right_child);
    }
}
/*中序遍历的非递归算法
 * 形参为根节点
 * 采用栈存储作为中序遍历的非递归方法,首先根节点进栈,先遍历左子树直到左子树为空,出栈并打印该节点关键字。再去访问出栈结点的右子树
 * 右子树不为空,继续:该节点进栈->遍历左子树->出栈并打印->右结点
*/
void binary_tree::inorder_tree_walk2(binary_tree_node* node)
{
    stack<binary_tree_node*> _stack;
    binary_tree_node *tmp = node;
    while(NULL!=tmp || !_stack.empty())//结点不为空或者栈不空,可以继续遍历
    {
        if(NULL!=tmp)
        {
            _stack.push(tmp);//结点进栈
            tmp=tmp->left_child;//遍历左子树,直到左子树为空
        }
        else
        {
            tmp=_stack.top();//左子树遍到叶子结点,取出栈顶结点并打印,访问右孩子
            visit(tmp);//如果右孩子不为空,重复上述步骤,先左再根后右;如果右孩子为空,再出栈一个结点,接着访问右孩子
            _stack.pop();
            tmp=tmp->right_child;
        }
    }
}
/*前序遍历的递归算法
 * 形参为根节点
 * 前序遍历的顺序为(根节点->左子树->右子树)
*/
void binary_tree::preorder_tree_walk(binary_tree_node* node)
{
    if(node!=NULL)
    {
        visit(node);
        preorder_tree_walk(node->left_child);
        preorder_tree_walk(node->right_child);
    }

}
/*
 * 前序遍历的非递归算法
 * 形参为根结点
 * 采用栈结构,根结点进栈,遍历左子树,结点进栈立即打印关键字
 * 直到左子树为空,出栈的同时,去访问其右孩子。如果右孩子不为空,重复上述步骤;如果右孩子为空,继续出栈
 *
 */
void binary_tree::preorder_tree_walk2(binary_tree_node* node)
{
    stack<binary_tree_node*> _stack;
    binary_tree_node *tmp = node;
    while(NULL!=tmp || !_stack.empty())
    {
        if(NULL!=tmp)
        {
            _stack.push(tmp);
            visit(tmp);
            tmp=tmp->left_child;
        }
        else
        {	tmp=_stack.top();
            _stack.pop();
            tmp=tmp->right_child;
        }
    }

}
/*
 * 后续遍历的递归算法
 * 左子树->右子树->根结点
 */
void binary_tree::postorder_tree_walk(binary_tree_node* node)
{
    if(node!=NULL)
    {
        postorder_tree_walk(node->left_child);
        postorder_tree_walk(node->right_child);
        visit(node);
    }

}
/*
 *后续遍历的非递归算法
 * 后续遍历的非递归算法比较复杂,这里采用两个栈的思路
 *  后续:左子树->右子树->根节点,先在第一个栈里遍历 根结点->右子树->左子树,用第二个栈颠倒次序
*/
void binary_tree::postorder_tree_walk2(binary_tree_node* node)
{
    stack<binary_tree_node*> _stack;
    stack<binary_tree_node*> output;
    binary_tree_node *tmp = node;
    _stack.push(tmp);
    while(!_stack.empty())
    {
        tmp=_stack.top();
        output.push(tmp);//栈一出栈,栈二进栈
        _stack.pop();
        if(NULL!=tmp->left_child)//先left后right不能颠倒
            _stack.push(tmp->left_child);
        if(NULL!=tmp->right_child)
            _stack.push(tmp->right_child);

    }

    while(!output.empty())
    {
        binary_tree_node *tmp2 = output.top();
        visit(tmp2);
        output.pop();
    }

}
/*
 * 逐层打印二叉树,每层不间隔,如果每层间隔,要另外设计算法
 * 基于Queue来实现,也就是广度优先搜索(BFS)的思想
*/
void binary_tree::levelorder_tree_walk(binary_tree_node* node)
{
    queue<binary_tree_node*> _queue;
    _queue.push(node);
    while(!_queue.empty())
    {
        binary_tree_node *tmp = _queue.front();
        visit(tmp);
        _queue.pop();
        if(tmp->left_child!=NULL)
            _queue.push(tmp->left_child);
        if(tmp->right_child!=NULL)
            _queue.push(tmp->right_child);
    }
}
/*
 * 搜索元素
 * 非递归
*/
binary_tree_node* binary_tree::search(char a)
{
    if(root==NULL)
        return NULL;
    else
    {
        binary_tree_node *tmp = root;
        while((tmp!=NULL)&&(tmp->data)!=a)
        {
            if(a<tmp->data)
                tmp=tmp->left_child;
            else
                tmp=tmp->right_child;
        }
        return tmp;
    }

}

/*
 * 递归搜索一个元素
*/
binary_tree_node* binary_tree::search2(binary_tree_node* node, char a)
{
    binary_tree_node *tmp = node;
    if((tmp->data==a)||(node==NULL))
        return node;
    else
    {	if(a<tmp->data)
            return search2(tmp->left_child, a);
        else
            return search2(tmp->right_child, a);
    }

}

/* 找最大元素*/
char binary_tree::max()
{
    binary_tree_node* tmp = root;
    while(tmp->right_child!=NULL)
    {
        tmp=tmp->right_child;
    }
    return tmp->data;
}

/*找最小元素*/
char binary_tree::min()
{
    binary_tree_node* tmp = root;
    while(tmp->left_child!=NULL)
    {
        tmp=tmp->left_child;
    }
    return tmp->data;
}
int main()
{
    binary_tree btree(7);
    btree.create_binary_tree();
    binary_tree_node *root = btree.get_root();
    btree.preorder_tree_walk(root);
    cout<<endl;
    btree.inorder_tree_walk(root);
    cout<<endl;
    btree.postorder_tree_walk(root);
    cout<<endl;
    btree.preorder_tree_walk2(root);
    cout<<endl;
    btree.inorder_tree_walk2(root);
    cout<<endl;
    btree.postorder_tree_walk2(root);
    cout<<endl;
    btree.levelorder_tree_walk(root);
    cout<<endl;
    binary_tree_node *result1=btree.search(‘D‘);
    cout<<"the address of result1:"<<result1<<endl;
    binary_tree_node *result2=btree.search2(root, ‘D‘);
    cout<<"the address of result2:"<<result2<<endl;
    cout<<"max node:"<<btree.max()<<endl;
    cout<<"min node:"<<btree.min()<<endl;
return 0;

}

测试:

输入二叉搜索树:

测试结果:

C++实现二叉搜索树的常用操作,布布扣,bubuko.com

时间: 2024-12-28 16:07:24

C++实现二叉搜索树的常用操作的相关文章

二叉搜索树的删除操作详解(BST)

一.思想:分类讨论 二.二叉搜索树的删除操作具体讨论分如下四种情况:(记我们要删除的节点为D) 1.如果D节点既没有左孩子,也没有右孩子,那么直接删除就好了: 2.如果D节点只有左孩子,没有右孩子,那么只需要把该D节点左孩子链接到D节点的父亲节点,然后删除D节点就好了: 3.如果D节点只有右孩子,没有左孩子,那么只需要把该D节点右孩子链接到D节点的父亲节点,然后删除D节点就好了: 4.如果D节点既有左孩子,又有右孩子,那么需要找到D节点的右子树的最小值节点,找到之后直接替换掉D节点,然后删除找到

二叉搜索树的相关操作

操作包括二叉搜索树的创建,插入,搜索,寻找前驱后继,删除,左右旋转,插入元素为根结点,以及两棵二叉树的合并. 二叉树的创建很简单,只需要设置 value, left child, right child 即可. 插入的时候递归插入树中合适的位置,通过比较插入元素的值与根结点元素的值,如果小于则递归插入到左子树中,否则递归插入到右子树中. 搜索的时候与插入类似,比较要搜索的值和根结点元素值的大小,若小于则递归到左子树中去查找,否则递归到右子树中去查找. 寻找前驱的方式是在左子树的右结点中去递归寻找

二叉搜索树的一些操作的C++实现

头文件: #include<iostream> using namespace std; typedef struct BiTNode { int data; int key; struct BiTNode *parent, *lchild, *rchild; }BiTNode, *BiTree; BiTree Tree_Search(BiTree x, int k); void Tree_Walk(BiTree x); BiTree Tree_Minimun(BiTree x); BiTre

数据结构 - 从二叉搜索树说到AVL树(一)之二叉搜索树的操作与详解(Java)

二叉搜索树(Binary Search Tree),简称BST,顾名思义,一颗可以用于搜索的二叉树.BST在数据结构中占有很重要的地位,一些高级树结构都是其的变种,例如AVL树.红黑树等,因此理解BST对于后续树结构的学习有很好的作用.同时利用BST可以进行排序,称为二叉排序,也是很重要的一种思想. 二叉树的性质:任意一个节点的所有左子树元素都比该元素值要小,而所有右子树元素都比该元素值要大. 符合该性质的二叉树就是一颗二叉搜索树,当然前提下是树中不允许有重复元素. 所有的二叉搜索树的中序遍历序

数据结构第三部分:树与树的表示、二叉树及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树、集合及其运算

参考:浙大数据结构(陈越.何钦铭)课件 1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找——方法一:顺序查找(时间复杂度O(n)) int

【数据结构】第9章 查找! (二叉搜索树BST AVL树 B-(+)树 字典树 HASH表)

难产的笔记...本来打算用1天 结果前前后后拖了5天 §9.1 静态查找表 9.1.1 顺序表的查找 各种扫 自己脑补吧 复杂度O(n) 9.1.2 有序表的查找 若表是单调的,则可以利用二分查找.复杂度O(logn) 9.1.3 静态树表的查找 见 http://blog.csdn.net/area_52/article/details/43795837 9.1.4 索引顺序表的查找 建立索引表查找 §9.2 动态查找表 动态查找表的特点是,表结构本身是在查找过程中动态生成的,即对于给定值ke

【数据结构】树与树的表示、二叉树存储结构及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树与哈夫曼编码、集合及其运算

1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找--方法一:顺序查找(时间复杂度O(n)) int SequentialSearch(St

算法导论第十二章 二叉搜索树

一.二叉搜索树概览 二叉搜索树(又名二叉查找树.二叉排序树)是一种可提供良好搜寻效率的树形结构,支持动态集合操作,所谓动态集合操作,就是Search.Maximum.Minimum.Insert.Delete等操作,二叉搜索树可以保证这些操作在对数时间内完成.当然,在最坏情况下,即所有节点形成一种链式树结构,则需要O(n)时间.这就说明,针对这些动态集合操作,二叉搜索树还有改进的空间,即确保最坏情况下所有操作在对数时间内完成.这样的改进结构有AVL(Adelson-Velskii-Landis)

二叉搜索树以及对二叉搜索树平衡调整

代码的思想和图片参考:好大学慕课浙江大学陈越.何钦铭的<数据结构> 我们首先介绍一下什么是二叉搜索树和二叉平衡树: 二叉搜索树:一棵二叉树,可以为空:如果不为空,满足以下性质1. 非空左子树的所有键值小于其根结点的键值.2. 非空右子树的所有键值大于其根结点的键值.3. 左.右子树都是二叉搜索树. 二叉搜索树操作的特别函数:Position Find( ElementType X, BinTree BST ):从二叉搜索树BST中查找元素X,返回其所在结点的地址,查找的次数取决于树的高度