二叉排序树的重要性不用多说,下面用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. python学习笔记3--set

    #int string list tuple dict bool float set #集合:天生去重 s=set() #空的集合 s2={'} ls=[1,2,3,4,5,6,7,1,2,3,4] ...

  2. 阮一峰:自适应网页设计(Responsive Web Design)别名(响应式web设计)

    随着3G的普及,越来越多的人使用手机上网. 移动设备正超过桌面设备,成为访问互联网的最常见终端.于是,网页设计师不得不面对一个难题:如何才能在不同大小的设备上呈现同样的网页? 手机的屏幕比较小,宽度通 ...

  3. nodejs使用记录

    安装 下载64or32的安装程序,狂点下一步,无脑安装.然后检查一下: npm 使用npm -v命令检查npm是否可用 然后我们就可以使用npm了,npm语法如下: npm install <M ...

  4. [译]Quartz.NET 框架 教程(中文版)2.2.x 之第四课 更多关于Triggers

    第四课 更多关于Triggers 跟作业任务类似,触发器也非常容易使用,但是在你能够充分掌握Quartz之前,你需要知道并理解许多触发器的客户化的参数.前面已经提到过,有许多不同类型的触发器供你选择, ...

  5. [转载]PayPal为什么从Java迁移到Node.js,性能提高一倍,文件代码减少44%

    http://ourjs.com/detail/52a914f0127c763203000008 大家都知道PayPal是另一家迁移到Node.js平台的大型公司,Jeff Harrell的这篇博文 ...

  6. iOS学习笔记(1)— UIView 渲染和内容管理

    iOS中应用程序基本上都是基于MVC模式开发的.UIView就是模型-视图-控制器中的视图,在iOS终端上看到的.摸到的都是UIView. UIView在屏幕上定义了一个矩形区域和管理区域内容的接口. ...

  7. c++细节--section1

    1.register声明的变量为寄存器变量,因此没有地址,不能对它取地址操作. 2.[用错sizeof]当数组作为函数参数传递时,数组会退化为同类型的指针. 3.每个成员在成员初始化列表中只能出现一次 ...

  8. python模块-platform

    #author:Blood_Zero #coding:utf- import platform print dir(platform) #获取platform函数功能 platform.archite ...

  9. Servlet笔记6--Servlet程序改进

    第一步改进,GenericServlet: 我们目前所有放入Servlet类直接实现了javax.servlet.Servlet接口,但是这个接口中有很多方法是目前不需要的,我们可能只需要编写serv ...

  10. nanosleep()

    函数原型 #include <time.h> int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);   描述 ...