二叉排序树的重要性不用多说,下面用c++实现二叉排序树的建立,插入,查找,修改,和删除。难点在于删除,其他几个相对比较简单。

以下是代码:

 #include<iostream>
using namespace std;
//定义节点
typedef struct BiNode
{
int data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree; //插入函数
void insertBST(BiTree &T,int key)
{
if(NULL==T)
{
T=new BiNode;
T->data=key;
T->lchild=T->rchild=NULL;
}
else if(T->data==key)
cout<<"不能重复!";
else if(T->data>key)
insertBST(T->lchild,key);
else
insertBST(T->rchild,key); }
//通过插入函数实现创建二叉排序树
void createBST(BiTree &T)
{
int n;
cout<<"请输入要插入的节点数: ";
cin>>n;
int a[n];
cout<<"请输入要插入的数据:中间用空格分开"<<endl;
for(int i=;i<n;i++)
{
cin>>a[i];
insertBST(T,a[i]);
} cout<<"创建二叉排序树完成!"<<endl; } //前序遍历并打印
void preOrderTraverse(BiTree T)
{
if(T)
{
cout <<T->data<< " ";
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
//中序遍历并打印
void midOrderTraverse(BiTree T)
{ if(T)
{
midOrderTraverse(T->lchild);
cout <<T->data<< " ";
midOrderTraverse(T->rchild);
}
} //定义全局变量layer,表示层数
int layer=;
//下面是查找函数,返回是否查找到数据并且可以确定查找元素的层数
bool searchBST(BiTree &T,int key)
{
layer++;
if(T==NULL)
{
return false;
}
else
{
if (key==T->data)
{ return true; }
else if(key<T->data)
searchBST(T->lchild,key);
else
searchBST(T->rchild,key);
}
}
//利用上面查找函数实现查找操作
void findBST(BiTree &T)
{
int k;
cout<<"请输入要查找的元素值: ";
cin>>k;
if(searchBST(T,k))
{
cout<<"查找成功,该元素位于二叉树中!"<<endl;
cout<<"层数为:"<<layer<<endl;
} else
cout<<"没有查找到该元素!"<<endl;
}
     //定义删除节点的函数
void deletenode(BiTree &p)
{
BiTree q,s; //函数形参P指向要删除的节点,即它的双亲节点的rchild
//根据要删除的节点的孩子情况分三种讨论
//没有左孩子
if(!p->lchild)
{
q=p;
p=p->rchild;
delete q;
}
//没有右孩子
if(!p->rchild)
{
q=p;
p=p->lchild;
delete q; }
//两个孩子都有
else
{
q=p; //q指向上一个节点,s指向下一个节点,即指向q的右孩子,初始时q=p,最终s指向跟p节点换值的那个节点。
s=q->lchild; while(s->rchild)    //通过这个循环实现寻找最接近要删除节点(p)值的节点
{
q=s;
s=s->rchild;
}
p->data=s->data;    //交换值,有个注意事项,s是不存在右孩子的,因为如果存在,则右孩子比他大,更接近p,s需要继续循环,最终s还是没有右孩子。
if(q!=p)          
{
q->rchild=s->lchild;
}
else        //如果q,s 没有移动,即此时q=p,s的初始值就是最接近p点的节点,此时q不存在右节点,需要单独讨论
{
q->lchild=s->lchild;      
}
delete s;
} } //删除操作
bool deleteBST(BiTree &T,int del)
{
if(!T)
return false;
else
{
if(T->data==del)
{
deletenode(T);
return true;
}
else if(del<T->data)
{
return deleteBST(T->lchild,del);
}
else
{
return deleteBST(T->rchild,del);
}
} }

下面是主函数:

 //主函数
int main()
{
BiTree T=NULL;
int d;
createBST(T);
cout<<"前序遍历的结果为:"<<endl;
preOrderTraverse(T);
cout<<endl;
cout<<"中序遍历的结果为:"<<endl;
midOrderTraverse(T);
cout<<endl;
findBST(T);
cout<<"请输入要删除的数据:"<<endl;
cin>>d;
deleteBST(T,d);
cout<<"前序遍历的结果为:"<<endl;
preOrderTraverse(T); }

上面的代码分别实现了查找,建立,插入和删除的操作,删除比较难主要是因为删除节点后下面的所有节点都会受到影响。此时采取的思维是分类讨论节点的孩子节点情况,

最复杂的情况是存在左右孩子,此时有两种思路,对左边孩子树进行操作或者对右边孩子树进行操作,我给出的代码是左边,二者道理一样。具体方法参考代码,说明很详细。

下面给出一个存在双孩子节点的图

画的虽然简陋,但大概意思就这样,(画图的确是理解数据结构的利器啊)最后给出控制台运行结果:

over~

一步一步写数据结构(BST-二叉排序树)的更多相关文章

  1. 一步一步写平衡二叉树(AVL树)

    平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵 ...

  2. 一步一步写算法(之prim算法 上)

    原文:一步一步写算法(之prim算法 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面我们讨论了图的创建.添加.删除和保存等问题.今 ...

  3. .NET跨平台:在Mac上跟着错误信息一步一步手写ASP.NET 5程序

    今天坐高铁时尝试了一种学习ASP.NET 5的笨方法,从空文件夹开始,根据运行dnx . kestrel命令的错误信息,一步一步写代码,直至将一个最简单的ASP.NET程序运行起来. 尝试的具体步骤如 ...

  4. 《一步一步写嵌入式操作系统》读书笔记1—Skyeye介绍、安装和HelloWorld

    2013-11-14 最近在看<一步一步写嵌入式操作系统>,感觉此书甚好,许多地方讲得很清楚.可操作性强,计划边读边实践边写笔记,希望能够逐步熟悉嵌入式操作系统底层的东西,最终剪裁出一套实 ...

  5. 一步一步写一个简单通用的makefile(三)

    上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化. 优化后的makefile: #Hel ...

  6. Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)

    我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...

  7. 一步一步写算法(之prim算法 下)

    原文:一步一步写算法(之prim算法 下) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前两篇博客我们讨论了prim最小生成树的算法,熟悉 ...

  8. 一步一步写算法(之prim算法 中)

    原文:一步一步写算法(之prim算法 中) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] C)编写最小生成树,涉及创建.挑选和添加过程 MI ...

  9. 一步一步写算法(之挑选最大的n个数)

    原文:一步一步写算法(之挑选最大的n个数) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 从一堆数据中挑选n个最大的数,这个问题是网上流传的 ...

  10. 一步一步写算法(之n!中末尾零的个数统计)

    原文:一步一步写算法(之n!中末尾零的个数统计) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在很多面试的题目中,求n!结果中零的个数也是 ...

随机推荐

  1. windows下自动启动Redis隐藏命令行窗口

    这段时间看了看关于Redis的相关内容,对于Redis在windows下的安装和常规启动我就不多说了.可以参考其他的博客http://www.cnblogs.com/edisonchou/p/3821 ...

  2. 网站监控系统安装部署(zabbix,nagios)

    zabbix分布式监控系统安装部署 官方网站链接 https://www.zabbix.com/documentation/2.0/manual/installation 安装环境说明 参考地址 ht ...

  3. Spring Data JPA原生SQL查询

    package com.test.cms.dao.repository;import org.springframework.stereotype.Repository;import javax.pe ...

  4. 多年前写的DataTable与实体类的转换

    介绍 介绍 很多年前一直使用Ado.net,后来慢慢转型到其他的orm,在转型过程中,有意向将两者的模型结合起来,利用DataTable中的行状态完善一些mvc中的数据控制作用.现在把它放出来,留个纪 ...

  5. 纯javascript代码实现浏览器图片选择预览、旋转、批量上传

    工作中遇到的业务场景,和同事一起研究了下,主要是为了兼容IE版本 其实就是一些琐碎的知识点在网上搜集下解决方式,然后集成了下,主要有以下点: 1. IE input type=file的图片预览要用I ...

  6. Anaconda+django写出第一个web app(四)

    前面对Models有了一些了解,今天开始进一步了解Views,了解Views如何和Models交互以及了解模板(templates). 打开main文件夹下的views.py,重新编写homepage ...

  7. CF448C Painting Fence

    传送门 Descriptionzed 最近总是受到 Farmer 的困扰,因此他在自家的门前插了一排栅栏以防农气的入侵.栅栏由 N 个竖条栅栏横向组成,每个竖条栅栏宽度为 1.过了一段时间,zed 觉 ...

  8. [转]激活函数ReLU、Leaky ReLU、PReLU和RReLU

    “激活函数”能分成两类——“饱和激活函数”和“非饱和激活函数”. sigmoid和tanh是“饱和激活函数”,而ReLU及其变体则是“非饱和激活函数”.使用“非饱和激活函数”的优势在于两点:    1 ...

  9. CSS 特殊性、继承与层叠

    一.特殊性规则 选择器的特殊性由选择器本身的组件确定:特殊性由四个部分组成,其初始值为0,0,0,0. 1.    对于选择器中的每一个id,记0,1,0,0: 2.    对于选择器中的每一个类.伪 ...

  10. 使用IntelliJ IDEA新建maven的javaWeb项目部署,启动访问index,jsp页面

    对于用惯了eclipse的人,idea其实还挺不一样的,也是摸索了很久,看了好多博客,这里就记录一下,以后肯定经常用!,不过使用熟练了,功能确实非常强大,真的牛! 1 新建maven项目,配置好目录结 ...