b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

二叉排序树(查询、插入、删除)

电脑杂谈  发布时间:2019-06-24 03:05:05  来源:网络整理

二叉排序树 插入_二叉排序树的遍历_树与二叉树的区别

“二叉排序树,又称为二叉查找树。它或者是一颗空树,或者具有下列性质的二叉树。

构造一颗二叉排序树的目的,其实并不是为了排序,而是为了提高查找和插入删除关键字的速度。不管怎么说,在一个有序数据集上的查找,速度总是要快于无序数据集的,而二叉排序树这种非线性的结构,也有利于插入和删除的实现。”

通俗的讲,二叉排序树的本质就是一颗二叉树,只是关键字的排序比较有规律,能够利用二叉树的递归特性进行很方便的操作。在对于二叉排序树的基本操作中,包括:根据数据集构建二叉排序树(没有要查找的关键字,就插入)、查找、删除。其中,删除操作时最麻烦的,插入和查找的思路很像,下面详解。

首先定义一个二叉树的结构。

/*二叉排序树的节点结构定义*/

typedefstructBiTNode

{

intdata;

structBiTNode*lchild,*rchild;

}BiTNode,*BiTree;

查找操作思路:

先查找其根节点,如果根节点的数据与key值相等,则返回该根节点,并且返回TRUE;

否则, 如果key值大于根节点,则查询其右子树;

如果小于根节点,则查询其左子树。

代码如下:

intSearchBST(BiTreeT,intkey,BiTreef,BiTree*p)

{

/*递归查找二叉排序树T中是否存在key*/

/*指针f指向T的双亲,其初始调用值为NULL*/

/*若查找成功,则指针p指向该数据元素节点,并返回TRUE*/

/*否则指针p指向查找路径上访问的最后一个节点并返回FALSE*/

if(!T)

{

*p=f;//这是f唯一被用到的位置。

returnFALSE;

}

else

{

if(key==T->data)

{*p=T;returnTRUE;}

elseif(key>T->data)

returnSearchBST(T->rchild,key,T,p);/*在右子树继续查找*/

else

returnSearchBST(T->lchild,key,T,p);/*在左子树继续查找*/

}

}

intSearchBST2(BiTreeT,intkey,BiTreef,BiTree*p)

{

/*非递归*/

BiTrees;

if(!T)

{*p=f;returnFALSE;}

else

{

while(T)

{

if(key==T->data)

{*p=T;returnTRUE;}

if(key>T->data)

{s=T;T=T->rchild;}

else

{s=T;T=T->lchild;}

}

*p=s;

returnFALSE;

}

}

代码如下:

[cpp]

intInsertBST1(BiTree*T,intkey)

{

/*当二叉排序树T中不存在关键字等于key的数据元素时*/

/*插入key并返回TRUE,否则返回FALSE*/

/*调用查找函数SearchBST,非递归*/

BiTreep,s;

if(!SearchBST2(*T,key,NULL,&p))

树与二叉树的区别_二叉排序树 插入_二叉排序树的遍历

{

s=(BiTree)malloc(sizeof(BiTNode));

s->data=key;

s->lchild=s->rchild=NULL;

if(!p)

*T=s;/*插入s为根节点,此前树为空树*/

elseif(key>p->data)

p->rchild=s;/*插入s为右孩子*/

else

p->lchild=s;/*插入s为左孩子*/

returnTRUE;

}

returnFALSE;

}

intInsertBST2(BiTree*T,intkey)

{

/*当二叉排序树T中不存在关键字等于key的数据元素时*/

/*插入key并返回TRUE,否则返回FALSE*/

/*未调用查找函数,递归插入*/

if(!(*T))/*树为空,*/

{

说明:malloc 向系统申请分配指定size个字节的内存空间二叉排序树 插入,返回类型是 void* 类型。说明要有顺序,这是使说明内容条理化的必要条件.常见的说明顺序有:时间顺序、空间顺序、逻辑顺序.说明的时间顺序和记叙的时间顺序相似.空间顺序,要特别注意弄清空间的位置,注意事物的表里、大小、上下、前后、左右、东南西北等的位置和方向.逻辑顺序,常以推理过程来表现.采用什么顺序,主要取决于作者所说明对象的特点.说明事物的发展变化,时间顺序容易表示清楚.写建筑物的结构,离开空间顺序难让读者看明白.说明事理用逻辑顺序,正便于体现事理的内部联系.。在vc里面,用release模式编译运行程序的时候,堆分配(heap allocation)的时候调用的是malloc,如果你要分配10byte的空间,那么就会只分配10byte空间,而用debug模式的时候,堆分配调用的是_malloc_dbg,如果你只要分配10byte的空间,那么它会分配出除了你要的10byte之外,还要多出约36byte空间,用于存储一些薄记信息,debug堆分配出来之后就会按顺序连成一个链。

(*T)->data=key;

(*T)->lchild=(*T)->rchild=NULL;

returnTRUE;

}

if(key==(*T)->data)

returnFALSE;

if(key>(*T)->data)

returnInsertBST2(&((*T)->rchild),key);/*插入右孩子*/

else

4.排除插入的key已存在的情况,第(3)步的比较一直比较到当前节点t的左子节点或右子节点为null,此时t就是我们寻找到的节点,cmp>0则准备往t的右子节点插入新节点,cmp<0则准备往t的左子节点插入新节点。树中某结点的lchild,rchild,parent不等于-1时,它们分别是该结点的左、右孩子和双亲结点在向量中的下标。,lchild为结点的左孩子结点在向量中的位置,rchild为结点的右孩子结点在向量中的位置,parent为结点的双亲在向量的位置。

}

删除节点有三种情况分析:

a.叶子节点;(直接删除即可)

b. 仅有左或右子树的节点;(上移子树即可)

c. 左右子树都有的节点。( 用删除节点的直接前驱或者直接后继来替换当前节点,调整直接前驱或者直接后继的位置)

代码如下:

[cpp]

intDeleteBST(BiTree*T,intkey)

{

/*若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素节点*/

/*并返回TRUE;否则返回FALSE*/

if(!(*T))

returnFALSE;/*不存在关键字等于key的数据元素*/

else

{

if(key==(*T)->data)

Delete(T);

elseif(key<(*T)->data)

returnDeleteBST(&(*T)->lchild,key);

else

returnDeleteBST(&(*T)->rchild,key);

}

}

intDelete(BiTree*p)

{

/*从二叉排序树中删除节点p,并重接它的左或右子树*/

BiTreeq,s;

if (hufftree[p].lchild == -1 && hufftree[p].rchild == -1){。else if (ht[p].rchild.lchild。if(p->rchild)push(s,p->rchild)。

*p=NULL;

elseif(!(*p)->lchild)/*左子树为空,重接右子树*/

{

q=*p;

二叉排序树的遍历_树与二叉树的区别_二叉排序树 插入

*p=(*p)->rchild;

free(q);

}

elseif(!(*p)->rchild)/*右子树为空,重接左子树*/

{

q=*p;

*p=(*p)->lchild;

free(q);

}

else/*左右子树均不为空*/

{

q=*p;

s=(*p)->lchild;

while(s->rchild)/*转左,然后向右走到尽头*/

{

q=s;

s=s->rchild;

}

(*p)->data=s->data;

if(q!=*p)/*判断是否执行上述while循环*/

q->rchild=s->lchild;/*执行上述while循环,重接右子树*/

else

q->lchild=s->lchild;/*未执行上述while循环,重接左子树*/

free(s);

}

returnTRUE;

}

总结:二叉树以链式方式存储二叉排序树 插入,保持了链接存储结构在执行插入或删除操作时不用移动元素的优点,只要找到合适的插入和删除位置后,仅需要修改链接指针节课。插入删除的时间性能比较好。而丢与二拆排序树的查找,走的就是从根节点到要查找的节点的路径,其比较次数等于给定值的节点在二叉排序树的层数。极端情况,最少为1次,即根节点就是要找的节点,最多也不会超过树的深度。也就是说,二叉排序树的查找性能取决于二叉排序树的形状。可问题就在于,二叉排序树的形状是不确定的。

例如{62,88,58,47,35,73,51,99,37,93}这样的数组,我们可以构建一颗正常的二叉排序树。但是如果数组元素的次序是从小到大有序,如{35,37,47,51,58,62,73,88,93,99},则二拆排序树就成了极端的单支树,注意它依然是一颗二叉排序树。同样是查找节点99,左图只需要两次比较,而右图就需要10次比较才可以得到结果,而这差异很大。

也就是说,我们希望二叉排序树是比较平衡的,即其深度与完全二叉树相同。

这样就延续到了另一篇博客中要讲解的平衡二叉树。

附加:完整代码

[cpp]

#include<stdio.h>

#include<stdlib.h>

#defineTRUE1

#defineFALSE0

/*二叉排序树的节点结构定义*/

typedefstructBiTNode

{

intdata;

structBiTNode*lchild,*rchild;

}BiTNode,*BiTree;

intSearchBST(BiTreeT,intkey,BiTreef,BiTree*p)

{

/*递归查找二叉排序树T中是否存在key*/

/*指针f指向T的双亲,其初始调用值为NULL*/

/*若查找成功,则指针p指向该数据元素节点,并返回TRUE*/

/*否则指针p指向查找路径上访问的最后一个节点并返回FALSE*/

if(!T)

{

*p=f;//这是f唯一被用到的位置。

returnFALSE;

}

else

{

if(key==T->data)

{*p=T;returnTRUE;}

elseif(key>T->data)

returnSearchBST(T->rchild,key,T,p);/*在右子树继续查找*/

else

returnSearchBST(T->lchild,key,T,p);/*在左子树继续查找*/

}

}

intSearchBST2(BiTreeT,intkey,BiTreef,BiTree*p)

{

树与二叉树的区别_二叉排序树 插入_二叉排序树的遍历

/*非递归*/

BiTrees;

if(!T)

{*p=f;returnFALSE;}

else

{

while(T)

{

if(key==T->data)

{*p=T;returnTRUE;}

if(key>T->data)

{s=T;T=T->rchild;}

else

{s=T;T=T->lchild;}

}

*p=s;

returnFALSE;

}

}

intInsertBST1(BiTree*T,intkey)

{

/*当二叉排序树T中不存在关键字等于key的数据元素时*/

/*插入key并返回TRUE,否则返回FALSE*/

/*调用查找函数SearchBST,非递归*/

BiTreep,s;

if(!SearchBST2(*T,key,NULL,&p))

{

s=(BiTree)malloc(sizeof(BiTNode));

s->data=key;

s->lchild=s->rchild=NULL;

if(!p)

*T=s;/*插入s为根节点,此前树为空树*/

elseif(key>p->data)

p->rchild=s;/*插入s为右孩子*/

else

p->lchild=s;/*插入s为左孩子*/

returnTRUE;

}

returnFALSE;

}

intInsertBST2(BiTree*T,intkey)

{

/*当二叉排序树T中不存在关键字等于key的数据元素时*/

/*插入key并返回TRUE,否则返回FALSE*/

/*未调用查找函数,递归插入*/

if(!(*T))/*树为空,*/

{

说明:malloc 向系统申请分配指定size个字节的内存空间,返回类型是 void* 类型。说明要有顺序,这是使说明内容条理化的必要条件.常见的说明顺序有:时间顺序、空间顺序、逻辑顺序.说明的时间顺序和记叙的时间顺序相似.空间顺序,要特别注意弄清空间的位置,注意事物的表里、大小、上下、前后、左右、东南西北等的位置和方向.逻辑顺序,常以推理过程来表现.采用什么顺序,主要取决于作者所说明对象的特点.说明事物的发展变化,时间顺序容易表示清楚.写建筑物的结构,离开空间顺序难让读者看明白.说明事理用逻辑顺序,正便于体现事理的内部联系.。在vc里面,用release模式编译运行程序的时候,堆分配(heap allocation)的时候调用的是malloc,如果你要分配10byte的空间,那么就会只分配10byte空间,而用debug模式的时候,堆分配调用的是_malloc_dbg,如果你只要分配10byte的空间,那么它会分配出除了你要的10byte之外,还要多出约36byte空间,用于存储一些薄记信息,debug堆分配出来之后就会按顺序连成一个链。

(*T)->data=key;

(*T)->lchild=(*T)->rchild=NULL;

returnTRUE;

}

if(key==(*T)->data)

returnFALSE;

if(key>(*T)->data)

树中某结点的lchild,rchild,parent不等于-1时,它们分别是该结点的左、右孩子和双亲结点在向量中的下标。rchild 分别表示左、右孩子结点在数组中的序号,parent 表示该结点是否已加入。,lchild为结点的左孩子结点在向量中的位置,rchild为结点的右孩子结点在向量中的位置,parent为结点的双亲在向量的位置。

else

4.排除插入的key已存在的情况,第(3)步的比较一直比较到当前节点t的左子节点或右子节点为null,此时t就是我们寻找到的节点,cmp>0则准备往t的右子节点插入新节点,cmp<0则准备往t的左子节点插入新节点。树中某结点的lchild,rchild,parent不等于-1时,它们分别是该结点的左、右孩子和双亲结点在向量中的下标。,lchild为结点的左孩子结点在向量中的位置,rchild为结点的右孩子结点在向量中的位置,parent为结点的双亲在向量的位置。

}

voidorder(BiTreet)//中序输出

{

if(t==NULL)

return;

order(t->lchild);

printf("%d",t->data);

order(t->rchild);

}

二叉排序树的遍历_树与二叉树的区别_二叉排序树 插入

intDeleteBST(BiTree*T,intkey)

{

/*若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素节点*/

/*并返回TRUE;否则返回FALSE*/

if(!(*T))

returnFALSE;/*不存在关键字等于key的数据元素*/

else

{

if(key==(*T)->data)

Delete(T);

elseif(key<(*T)->data)

returnDeleteBST(&(*T)->lchild,key);

else

returnDeleteBST(&(*T)->rchild,key);

}

}

intDelete(BiTree*p)

{

/*从二叉排序树中删除节点p,并重接它的左或右子树*/

BiTreeq,s;

if(!(*p)->lchild&&!(*p)->rchild)/*p为叶子节点*/

*p=NULL;

elseif(!(*p)->lchild)/*左子树为空,重接右子树*/

{

q=*p;

*p=(*p)->rchild;

free(q);

}

elseif(!(*p)->rchild)/*右子树为空,重接左子树*/

{

q=*p;

*p=(*p)->lchild;/*不太理解*/

free(q);

}

else/*左右子树均不为空*/

{

q=*p;

s=(*p)->lchild;

while(s->rchild)/*转左,然后向右走到尽头*/

{

q=s;

s=s->rchild;

}

(*p)->data=s->data;

if(q!=*p)/*判断是否执行上述while循环*/

q->rchild=s->lchild;/*执行上述while循环,重接右子树*/

else

q->lchild=s->lchild;/*未执行上述while循环,重接左子树*/

free(s);

}

returnTRUE;

}

voidmain()

{

inti;

inta[10]={62,88,58,47,35,73,51,99,37,93};

BiTreeT=NULL;

for(i=0;i<10;i++)

InsertBST1(&T,a[i]);

printf("中序遍历二叉排序树:\n");

order(T);

printf("\n");

printf("删除58后,中序遍历二叉排序树:\n");

DeleteBST(&T,58);

order(T);

printf("\n");

}


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-108008-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      每日福利
      热点图片
      拼命载入中...