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 ...
随机推荐
- 常用模块xml,shelve,configparser,hashlib
XML 什么XML:全称 可扩展标记语言 标记指的是代表某种含义的字符 XML<> 为什么需要XML 为能够在不同的平台间继续数据的交换 为了使交换的数据能让对方看懂 就需要按照一定的语法 ...
- noip2017d2t2
看数据范围想到状压,我们知道最后是选出一颗生成树,但边权的计算有一些有趣: 我们先选一个点做根:然后就发现边的权和深度有关:那我们按深度dp;即按层dp; dp[i][s]表示前i层选的点集为s,转移 ...
- Scala_对象
对象 单例对象 Scala并没有提供Java那样的静态方法或静态字段,但是,可以采用 object关键字实现单例对象,具备和Java静态方法同样的功能. 可以看出,单例对象的定义和类的定义很相似,明显 ...
- Scala_方法、函数、柯里化
方法.函数.柯里化 方法 声明方法: scala> def m1(x:Int,y:Int):Int = { | x + y | }m1: (x: Int, y: Int)Ints ...
- js-列表修改
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- MFC坐标系
MFC坐标系分为设备坐标系和逻辑坐标系两种.在设备坐标系中,一个像素表示一个单位长度,设备的原点(0,0)始终在显示平面的左上角位置,x轴正向向右,y轴正向向下. 逻辑坐标系中,原点可以放在任何一个位 ...
- B - Big String
We will construct an infinitely long string from two short strings: A = "^__^" (four chara ...
- WinRAR试用过期决绝方法
一.WinRAR 试用过期决绝方法 直接去WINRAR官方下个版本装上然后这样 复制以下内容(红色)到记事本,保存为rarreg.key文件(即文件名是rarreg,扩展名是key),把这文件拷贝到W ...
- VS2010的快捷键乱
vs2010的快捷键乱了,点击回车会出现属性窗口,点击退格键会相当于编辑里面的撤销功能 点击ctrl+s会出现sharepoint窗口,在网上找了一个解决方式(很难找),原问在这: http://q. ...
- 在ASP.NET Core中,静态类如何读取配置文件
这是今天下午一个同事问我的问题,如何在静态类中读取json配置文件.我当时并没有告诉他如何如何去做,办法肯定是有,但是这种编程思维确实得改改了.静态类.静态方法不是面向对象编程的最佳实践..NET C ...