二叉排序树的重要性不用多说,下面用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. sql 存储时空格转成问号问题

    最近做系统,从邮件中导出邮件,上传到系统中,遇到一个奇葩的问题,如下: 通过本地文件看,文件名中是一个空格,上传至数据库后,展示就变成了问号,究其原因,发现是一个特殊字符导致: 最近认真去查了一下这个 ...

  2. gdb查看内存(转)

    可以使用examine命令(简写是x)来查看内存地址中的值.x命令的语 法如下所示: x/<n/f/u> <addr> n.f.u是可选的参数. n是一个正整数,表示需要显示的 ...

  3. Java并发编程原理与实战三十七:线程池的原理与使用

    一.简介 线程池在我们的高并发环境下,实际应用是非常多的!!适用频率非常高! 有过使用过Executors框架的朋友,可能不太知道底层的实现,这里就是讲Executors是由ThreadPoolExe ...

  4. 当今最流行的Web项目管理工具精选

    代码管理 以前各种开源项目的代码都是通过博客和个人网页来发布的.这种分享方式并不是最容易的一种,也不便于他人对代码做出贡献.下面是几个管理项目代码的工具,不管对于个人开发者还是团队开发者来说,它们都是 ...

  5. 20155232 2016-2017-3 《Java程序设计》第7周学习总结

    20155232 2016-2017-3 <Java程序设计>第7周学习总结 教材学习内容总结 第十三章 1.Greenwich MeanTime,格林威治时间,简称GMT时间,由观察太阳 ...

  6. Caffe的loss layer(转)

    英文可查:地址 1.SoftmaxWithLoss 对一对多的分类任务计算多项逻辑斯蒂损失,并通过softmax传递预测值,来获得各类的概率分布.该层可以分解为SoftmaxLayer+Multino ...

  7. sql server 查询本周、本月所有天数的数据

    查询本月所有的天数: --本月所有的天数 ),) day from (),,)+'-01' day) t1, ( ) t2 ),) ),,)+'%' 查询本周所有的天数: ),,),) ),,),) ...

  8. [转]双线性插值(Bilinear interpolation)

    1,原理 在图像的仿射变换中,很多地方需要用到插值运算,常见的插值运算包括最邻近插值,双线性插值,双三次插值,兰索思插值等方法,OpenCV提供了很多方法,其中,双线性插值由于折中的插值效果和运算速度 ...

  9. Dream------Hadoop--Hadoop HA QJM (Quorum Journal Manager)

    In a typical HA cluster, two separate machines are configured as NameNodes. At any point in time, ex ...

  10. oracle关键字作为字段名使用方法

    有时我们在定义字段名及别名时所用名与oracle关键字同名,这时该如何处理呢? 其实很简单,只要在此关键字加上"",如"group" SQL> DROP ...