12 二叉树-链式存储-二叉排序树(BST)
呜呜 写这个东西花了我2天 居然花了两天!!我还要写AVL呢啊啊啊啊啊啊啊!!!!!!
等下还要跑去上自习 大早上起来脸都没洗现在先赶紧发博客 昨晚写出来了独自在其他人都睡着了的宿舍狂喜乱舞。。
迷之想哭 不知道能不能考上。。。。。。
不管能不能考上 活在当下就对了 走好每一步踏踏实实吧!!
删除操作的代码考虑了很多东西,自己写的时候一开始觉得有点抽象,特别是左右孩子链接的处理,还有是否是根结点的判别……
其实也不知道我这个写法对不对,看了一些网上的代码,别人的都写得好简单啊!
先这么写着吧,回头有空了我再思考下有没有更简单的实现方法!如果有网友有好建议也欢迎留言!
1、二叉排序树的定义:
或者是一棵空树,或者是一颗具有以下特性的非空二叉树:
(1)若左(右)子树非空,则右(左)子树上的关键字值均小(大)于根结点的关键字值。
(2)左、右子树本身也分别是一颗二叉树。
2、二叉排序树的特点:
(1)对二叉排序树进行中序遍历可以得到一个递增的有序序列。
(2)维护的时候只需修改指针就可以完成插入和删除操作,平均执行时间为O(log2n)。
(3)平均查找性能取决于树的高度,最糟糕的情况下:由于输入的序列是有序的,形成了倾斜单支二叉树(可以理解为变成一个单链表),查找效率降成O(n)(平均查找长度与单链表相同)。
(4)查找判定树不唯一。
3、二叉排序树的适用场合:
有序表是动态查找表的时候应选择二叉排序树作为其逻辑结构。(静态查找表则合适用顺序表)
4、代码实现
注释详见代码!这里不赘述了!如果有不明白或者有错的地方欢迎留言和指正!
包括:
①二叉排序树的建立(包含插入操作)
②二叉排序树的查找
③二叉排序树的删除
④为了写删除操作还增加了一个判别孩子结点是双亲结点的左孩子or右孩子的小函数……
【注】因为此代码算法是自己思考设计的,自己比较笨拙,可能会有实现很冗余的地方,如果要使用建议参考其他人的版本。。可能只合适做数据结构的学习理解用orz
#include<iostream>
#include<stdlib.h>
#include<cstdio>
#include<stack>
#include<queue>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
/*存储结构描述*/
typedef struct BitNode
{
int data;
struct BitNode *lchild,*rchild;
} BitNode,*BiTree;
/*建立一个二叉排序树*/
/*其实是二叉排序树的插入算法*/
void initTree(BiTree &T,int x)
{
if(T==NULL)
{
T=(BitNode*)malloc(sizeof(BitNode));
T->data=x;
T->lchild=NULL;
T->rchild=NULL;
}
else
{
if(x>T->data)
initTree(T->rchild,x);
else initTree(T->lchild,x);
}
}
/*二叉排序树的结点查找*/
/*
1、如果查找成功,返回查找的结点
2、如果查找失败 返回NULL(走到了叶子结点的下一层→【NULL】)
3、指针p指向结点的双亲结点
*/
BitNode *BST_Search(BiTree T,int x,BitNode *&p)
{ p=NULL;
while(T!=NULL&&x!=T->data)
{
p=T;
if(x<T->data)
T=T->lchild;
else T=T->rchild;
}
return T;
}
/*结点的删除*/
/*
1、如果是叶结点,直接删除即可
2、如果删除的结点只有单枝左子树或者右子树→让子树成为父结点的子树,直接替代被删结点的位置
3、如果删除的结点有左右两棵子树,这里可以采用p的(x序遍历)直接后继或者直接前驱进行替代。
这里选为中序遍历的直接后继作为替代结点,其中序遍历下的直接后继为被删除结点右子树最左结点。
4、在最后链接被删结点双亲和被删结点孩子的这一步中,如果被删结点为根结点,则不需修改它双亲结点(本来就没双亲),但是要修改指向树的指针T!!不然它会指向空域。
*/
int relationship(BitNode *a,BitNode *b)
{
if(a->lchild==b) return ;//b是a的左孩子
else if(a->rchild==b) return ;//b是a的右孩子
else return ;//没关系
} int Delete(BiTree &T,int x)
{
BitNode *p=NULL,*psdad=NULL;
BitNode *tool=NULL,*tooldad=NULL;
p=BST_Search(T,x,psdad);
//如果删除的结点是叶结点
if(p->lchild==NULL&&p->rchild==NULL)
{
if(relationship(psdad,p)==)
{
psdad->lchild=NULL;
}
else
{
psdad->rchild=NULL;
}
free(p);
}
else if(p->lchild==NULL)
{
if(relationship(psdad,p)==)
{
psdad->lchild=p->rchild;
free(p);
}
else
{
psdad->rchild=p->rchild;
free(p);
}
}
else if(p->rchild==NULL)
{
if(relationship(psdad,p)==)
{
psdad->lchild=p->lchild;
free(p);
}
else
{
psdad->rchild=p->lchild;
free(p);
}
}
else//p有左右两棵子树//有错,明天思考
{
tooldad=p;
tool=p->rchild;
/*转向右子树,向左走到尽头*/
//cout<<"tool1:"<<tool->data<<endl;
//if(tooldad!=NULL)
// cout<<"tooldad:"<<tooldad->data<<endl;
//else cout<<"tooldad:null"<<endl; while(tool->lchild)
{
tooldad=tool;
tool=tool->lchild;
} //cout<<"tool2:"<<tool->data<<endl;
//if(tooldad!=NULL)
// cout<<"tooldad:"<<tooldad->data<<endl;
//else cout<<"tooldad:null"<<endl;
if(tool==p->rchild)//即:被删除结点右子树的中序遍历第一个结点就是右孩子,这时直接把右孩子挪上去代替被删结点
{
//cout<<"ct1"<<endl;
tool->lchild=p->lchild;
if(psdad)//如果被删除的不是根结点 则需要把代替原位置的结点和被删结点的双亲接连上去
{
if(relationship(psdad,p)==)
{
psdad->lchild=tool;
free(p);
}
else
{
psdad->rchild=tool;
free(p);
}
}
else//被删除的是根结点 要把指向根结点的指针一并修改 不然树头会指向空域
{T=tool;free(p);}
}
else
{
//cout<<"ct2"<<endl;
tooldad->lchild=tool->rchild;//当前结点为最左结点,它一定没有左孩子,可能有右孩子。
tool->lchild=p->lchild;
tool->rchild=p->rchild;
tool->lchild=p->lchild;
if(psdad)
{
if(relationship(psdad,p)==)
{
psdad->lchild=tool;
free(p);
}
else
{
psdad->rchild=tool;
free(p);
}
}
else {T=tool;free(p);}
}
}
return OK; } void visit(BiTree T)
{
cout<<T->data<<' ';
}
/*中序遍历\测试用*/
void inOrder(BiTree T)
{
if(T!=NULL)
{
inOrder(T->lchild);
visit(T);
inOrder(T->rchild);
}
}
int main()
{
BiTree tree=NULL;
BitNode *ans=NULL,*ansdad=NULL;
int x;
cin>>x;
while(x!=)
{
initTree(tree,x);
cin>>x;
}
cout<<"--- show the bst tree ---"<<endl;
inOrder(tree);
cout<<endl;
cout<<"Test Search function:"<<endl;
cin>>x;
ans=BST_Search(tree,x,ansdad);
if(ans==NULL)
cout<<"NULL."<<endl;
else
{
cout<<"successful found."<<ans->data<<endl;
if(ansdad!=NULL)
cout<<"His father's data is:"<<ansdad->data<<endl;
else cout<<"He is the Root of BST tree."<<endl;
}
int w; cin>>w;
while(w!=)
{
Delete(tree,w);
cout<<"--- show the bst tree ---"<<endl;
inOrder(tree);
cout<<endl;
cin>>w;
}
return ;
}
5、代码实现截图
12 二叉树-链式存储-二叉排序树(BST)的更多相关文章
- C#数据结构-二叉树-链式存储结构
对比上一篇文章"顺序存储二叉树",链式存储二叉树的优点是节省空间. 二叉树的性质: 1.在二叉树的第i层上至多有2i-1个节点(i>=1). 2.深度为k的二叉树至多有2k- ...
- Java实现链式存储的二叉树
二叉树的定义: 二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的.分别称作这个根的左子树和右子树的二叉树组成. 二叉树的遍历方式主要 ...
- Java实现链式存储的二叉查找树(递归方法)
二叉查找树的定义: 二叉查找树或者是一颗空树,或者是一颗具有以下特性的非空二叉树: 1. 若左子树非空,则左子树上所有节点关键字值均小于根节点的关键字: 2. 若右子树非空,则右子树上所有节点关键字值 ...
- 【Java】 大话数据结构(6) 栈的顺序与链式存储
本文根据<大话数据结构>一书,实现了Java版的栈的顺序存储结构.两栈共享空间.栈的链式存储机构. 栈:限定仅在表尾进行插入和删除操作的线性表. 栈的插入(进栈)和删除(出栈)操作如下图所 ...
- C语言- 基础数据结构和算法 - 栈的链式存储
听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...
- javascript实现数据结构:线性表--线性链表(链式存储结构)
上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...
- 栈的链式存储 - API实现
基本概念 其它概念详情參看前一篇博文:栈的顺序存储 - 设计与实现 - API实现 这里也是运用了链表的链式存储API高速实现了栈的API. 代码: // linkstack.h // 链式存储栈的A ...
- [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)
优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...
- C++编程练习(6)----“实现简单的队列的链式存储结构“
队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出.简称链队列. 实现代码如下: /* LinkQueue.h 头文件 */ #include<iostream> #defi ...
随机推荐
- IP和网段及子网掩码基础知识
IP地址由网络号和主机号两部分组成,网络号的最高位必须是"0",IP地址和子网掩码求"与"算出网络地址,只有网络地址相同才可直接通信,否则需要借助路由. 主机标 ...
- leaflet入门(四)API翻译(上)
L.Map L.Marker L.Popup L.Map API各种类中的核心部分,用来在页面中创建地图并操纵地图. Constructor(构造器) 通过div元素和带有地图选项的描述的文字对象来实 ...
- 20170831工作日记--自定义View学习
学习了LayoutInflater的原理分析.视图的绘制流程.视图的状态及重绘等知识,按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件.组合控件.以及继承控件.那么下面我们就来依次 ...
- linux 修改ip 地址
1./etc/sysconfig/network-scripts/ifcfg-网卡 如果是新网卡 自己写配置文档 ip a 即可查看网卡名字 (这是eno16777736) BOOTPROTO= dh ...
- 团队项目之UML图设计---WeEdit
团队信息: 学号: 姓名: 本次博客链接: 041602209 黄毓明(临时队长) https://www.cnblogs.com/mingsonic/p/9820702.html 06160023 ...
- PAT甲级 1130. Infix Expression (25)
1130. Infix Expression (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Give ...
- hdu 1443 Joseph【约瑟夫环】
题目 题意:一共有2k个人,分别为k个好人和k个坏人,现在我们需要每隔m个人把坏人挑出来,但是条件是最后一个坏人挑出来前不能有好人被挑出来..问最小的m是多少 约瑟夫环问题,通常解决这类问题时我们把编 ...
- jQuery插件初级练习2答案
html: $.font($("p"),"30px").html("变化了") jQuery: $.extend({ font:functi ...
- AngularJS 过滤器 Filter
过滤器实质是数据转换或过滤,把ViewMode中的数据转化成View层用户友好的信息.可以看做一个函数,负责接收输入,转换成输出,每次参数变化时,它就被执行,输出被视图View使用. 一.基本定义及其 ...
- Delphi XE3写DLL,用Delphi7调用,报错!
http://bbs.csdn.net/topics/390870532 用delphi xe3写的DLL,delphi7调用,参数都是PAnsiChar,DLL里的函数接收delphi7传的入参,没 ...