数据结构之树和二叉树的应用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第六章树和二叉树的应用
6.1二叉排序树和平衡二叉树
在实际应用中,常常需要在一组记录中检索一个记录,向其中插入一个记录或者把找到的记录删除。
如果记录无序,查找起来将会很慢。如果记录有序,查找将会很快。但是遇到动态增减变化时,需要移动大量的元素。即使使用链表结构,查找起来也相当麻烦。非常需要一中插入、删除、和检索记录效率都很高的数据组织方法。二叉排序(查找、搜索)树就是这样一种高效的数据结构。
二叉排序树也称二叉查找树或二叉搜索树。它或者是一棵空树;
或者有性质:
(1)若其左子树不空,则左子树上所有结点的值均小于根结点
的值。
(2)若其右子树不空,则右子树上所有结点的值均大于根结点
的值。
(3)左右子树也为二叉排序树。
图5.21就是一棵二叉排序树。二叉排序树通常采用二叉链存储结构。二叉链存储结构的结点类型定义:
typedefstructtnode
{
KeyTypekey;//关键字域
ElemTypedata;//其他数据域
structtnode*lchild,*rchild;//指针
}BSTNode;
中序遍历二叉排序树可以得到有序序列。
6.1.2二叉排序树的基本运算
二叉排序树的基本运算如下:
1.BSTSearch(bt,k)在二叉排序树bt中,查找值为k的结点。
2.BSTInsert(bt,k)在二叉排序树bt中,插入值为k的结点。
3.CreateBST(bt,str,n)创建二叉排序树
4.输出二叉排序树DispBST(bt)
5.删除结点BSTDelete(bt,k)
1.查找结点BSTSearch(bt,k)
方法:将给定值k与查找树的根结点关键码比较。若相等,查找成功,结束查找过程。否则,a.当给k小于根结点关键码,查找将在以左子女为根的子树上继续进行;
b.当给k大于根结点关键码,查找将在以右子女为根的子树上继续进行;
c .若K 等于当前结点的关键字,则返回;如此反复,直至找到或子树为空,查找失败时为止。
例如,查找图5.21中关键字等于45的结点。从根结点开始比较。
45<63,在左子树中查找;45<55,在左子树中查找;45>42,在右子树中查找;45=45,查找成功,返回。
再如,查找图5.21中关键字等于73的结点。从根结点开始比较。
73>63,在右子树中查找;73<90,在左子树中查找;73>70,在右子树中查找;73<83,在左子树中查找;5.83的左子树为空,查找失败。所以稽核中不含关键字等于73的结点。
查找二叉排序树的算法
BSTNode*BSTSearch(BSTNode*bt,KeyTypek) { BSTNode*p=bt; while(p!=NULL&&p->key!=k) {if(k
p=p->lchild;/*沿左子树查找*/ else
p=p->rchild;/*沿右子树查找*/ } If(p!=NULL)
return(p);
elseprintf(“找不到”); }
2.二叉排序树的插入BSTInsert(bt,k)
向二叉排序树中插入一个结点的过程:设待插入结点的关键码为kx ,为将其插入,先要在二叉排序树中进行查找,若查找成功,按二叉排序树定义,待插入结点已存在,不用插入;查找不成功时,则插入之。因此,新插入结点一定是作为叶子结点添加上去的。
例如:记录的关键码序列为:63,90,70,55,67,42,98,83,10,45,58,则构造一棵二叉排序树的过程如图5.22所示:
φ
插入算法:
intBSTInsert(BSTNode*&bt,KeyTypek) { BSTNode*f,*p=bt; while(p!=NULL)
63 63 90
70
90 63 70
90 63 55
70
90 63 55
67 70
90 63 55 67 42
70
90 63 55 67 42
98
70 90 63 55 67 83
98 42 70 90 63 55 67 83 98
10 42 42 98 70 90 63 45 55 83 67 10 58 42 98 70 90 63 45 55 83 67 10 图6.2 构造二叉排序树
{if(p->key==k)return(0); f=p;/*f指向*p结点的双亲结点*/
if(p->key>k)p=p->lchild;/*k小,在左子树查找*/
elsep=p->rchild;/*否则在右子树找*/
}
p=(BSTNode*)malloc(sizeof(BSTNode));
p->key=k;p->lchild=p->rchild=NULL;
if(bt==NULL)bt=p;
elseif(k
elsef->rchild=p; return(1);
}
3.二叉排序树的构造CreateBST(bt,str,n)
上例说明,构造一棵二叉排序树则是从空树出发逐个插入结点的过程。
创建算法:
voidCreateBST(BSTNode*&bt,KeyTypestr[],intn)
{ bt=NULL; /*初始时bt为空树*/
inti=0;
while(i { BSTInsert(bt,str[i]);/*插入关键字*/ i++; } } 4.输出二叉排序树DispBST(bt) 这里指的是二叉排序树的括号形式的输出,而不是关键字的值的输出,也不是输出结点的地址。 关键字的值的输出可用二叉树的先序、中序、后序遍历,二叉排序树的中序序列是一个有序序列。所以可以用二叉排序树进行排序,这也是把它叫着二叉排序树的原因。 二叉排序树的括号形式的输出,如果不是空树,要求先输出根结点的关键字的值,当该结点有左孩子结点或有孩子结点时,后面紧跟前圆括号“(”,然后递归处理左子树,再输出一个逗号“,”,再递归处理右子树,最后输出一个后圆括号“)”。即使是没有左子树,右子树前面的逗号也是不能省略的。对应的地柜算法如下: voidDispBST(BSTNode*bt) { if(bt!=NULL) {printf("%d",bt->key); if(bt->lchild!=NULL||bt->rchild!=NULL) {printf("(");DispBST(bt->lchild); if(bt->rchild!=NULL)printf(","); DispBST(bt->rchild);printf(")");} } } 5.二叉排序树的删除BSTDelete(bt,k) 设*p是*f的左孩子,*p左、右子树为pL、pR,pR中序最右结点为S,S的中序前驱为Q。 (1)若*p为叶子结点,则修改*f的对应指针为空。 (2)若*p只有1棵子树,则用子树替代*p。 (3)若*p左右子树均不空。可以有两种做法: