中序线索化二叉树数据结构.docx

上传人:b****0 文档编号:994173 上传时间:2022-10-15 格式:DOCX 页数:16 大小:19.36KB
下载 相关 举报
中序线索化二叉树数据结构.docx_第1页
第1页 / 共16页
中序线索化二叉树数据结构.docx_第2页
第2页 / 共16页
中序线索化二叉树数据结构.docx_第3页
第3页 / 共16页
中序线索化二叉树数据结构.docx_第4页
第4页 / 共16页
中序线索化二叉树数据结构.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

中序线索化二叉树数据结构.docx

《中序线索化二叉树数据结构.docx》由会员分享,可在线阅读,更多相关《中序线索化二叉树数据结构.docx(16页珍藏版)》请在冰豆网上搜索。

中序线索化二叉树数据结构.docx

中序线索化二叉树数据结构

中序线索化二叉树数据结构.

 

当用二叉链表作为二叉树的存储结构时,因为每个结点中只有指向其左、右孩子结点的指针,所以从任一结点出发只能直接找到该结点的左、右孩子。

在一般情况下靠它无法直接找到该结点在某种遍历次序下的前驱和后继结点。

如果在每个结点中增加指向其前驱和后继结点的指针,将降低存储空间的效率。

与此同时,我们可以证明:

在n个结点的二叉链表中含有n+1个空指针。

因为含n个结点的二叉链表中含有2n个指针,除了根结点,每个结点都有一个从父结点指向该结点的指针,因此一共使用了n-1个指针,所以在n个结点的二叉链表中含有2n-(n-1)=n+1个空指针。

因此,可以利用这些空指针,存放指向结点在某种遍历次序下的前驱和后继结点的指针。

这种附加的指针称为线索,加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树。

为了区分一个结点的指针是指向其孩子的指针,还是指向其前驱或后继结点的线索,可在每个结点中增加两个线索标志。

这样,线索二叉树结点类型定义为:

 

Lchild

Ltag

Data

Rtag

Rchild

 

其中:

1.Ltag=0时,表示Lchild指向该结点的左孩子;

2.Ltag=1时,表示Lchild指向该结点的线性前驱结点;

3.Rtag=0时,表示Rchild指向该结点的右孩子;

4.Rtag=1时,表示Rchild指向该结点的线性后继结点;

以二叉链表结点数据结构所构成的二叉链表作为二叉树的存储结构,叫做线索二叉链表;指向结点的线性前驱或者线性后继结点的指针叫做线索;加上线索的二叉树称为线索二叉树;对二叉树以某种次序遍历将其变为线索二叉树的过程叫做线索化。

中序线索化是指用二叉链表结点数据结构建立二叉树的二叉链表,然后按照中序遍历的方法访问结点时建立线索。

 

 

例如有如上图所示二叉树,则中序遍历的顺序是:

O/J*I+HAG

【参考程序】

#include

#include

typedefenum{Link,Thread}PointerTag;/*指针标志*/

typedefcharDataType;

typedefstructBiThreTree{/*定义结点元素*/

PointerTagLTag,RTag;

DataTypedata;

structBiThreTree*lchild,*rchild;

}BiThreTree;

BiThreTree*pre;/*全局变量,用于二叉树的线索化*/

BiThreTree*CreateTree()/*按前序输入建立二叉树*/

{

BiThreTree*T;

DataTypech;

scanf("%c",&ch);

if(ch==’#’)

T=NULL;

else

{T=(BiThreTree*)malloc(sizeof(BiThreTree));

T->data=ch;

T->LTag=Link;/*初始化时指针标志均为Link*/

T->RTag=Link;

T->lchild=CreateTree();

T->rchild=CreateTree();

}

returnT;

}

voidInThread(BiThreTree*T)

{

BiThreTree*p;

p=T;

if(p)

{

InThread(p->lchild);

if(!

p->lchild)

{p->LTag=Thread;

p->lchild=pre;

}

if(!

pre->rchild)

{pre->RTag=Thread;

pre->rchild=p;

}

pre=p;

InThread(p->rchild);

}

}

BiThreTree*InOrderThrTree(BiThreTree*T)/*中序线索化二叉树*/

{

BiThreTree*Thre;/*Thre为头结点的指针*/

Thre=(BiThreTree*)malloc(sizeof(BiThreTree));

Thre->lchild=T;

Thre->rchild=Thre;

pre=Thre;

InThread(T);

pre->RTag=Thread;

pre->rchild=Thre;

Thre->rchild=pre;

returnThre;

}

voidInThrTravel(BiThreTree*Thre)/*中序遍历二叉树*/

{

BiThreTree*p;

p=Thre->lchild;

while(p!

=Thre)/*指针回指向头结点时结束*/

{

while(p->LTag==Link)

p=p->lchild;

printf("%4c",p->data);

while(p->RTag==Thread&&p->rchild!

=Thre)

{p=p->rchild;

printf("%4c",p->data);

}

p=p->rchild;

}

}

voidmain()

{

BiThreTree*T,*Thre;

printf(“PreOrderCreateBinaryTree:

\n”);

T=CreateTree();

Thre=InOrderThrTree(T);

printf(“InOrderTraverseBinaryTree:

\n”);

InThrTravel(Thre);

system("pause");

}

【调试举例】

(1)建立二叉树时,按先序遍历方式输入:

“ABD##EH##I##CF##G##”,其中“#”表示空指针。

(2)建立的二叉树为:

A

BC

DEFG

HI

(3)程序输出为中序遍历线索化二叉树的结果:

DBHEIAFCG

已知A、B和C为三个递增有序的线性表,现要求对A表作如下操作:

删除那些既在B表中出现又在C表中出现的元素。

【实验步骤】

1.试对顺序表编写实现上述操作的算法并上机编写代码,要求算法尽可能高效。

在实验报告中分析你的算法的时间复杂度。

2.A表中要删除的元素实际上就是在三个表中都存在的元素。

注意这三个线性表都是递增有序的线性表!

可以利用这一性质减少对线性表“扫描”的趟数。

3.改用单链表作为存储结构编写算法,请释放A表中无用的结点空间,并上机编程实现。

【算法思想】

先从B和C中找出共有元素same,再从A中从当前位置开始,凡小于same的元素均保留,等于same的就跳过,大于same时就再找下一个same。

【顺序存储结构算法描述】

voidSqList_Delete(SqList&A,SqListB,SqListC)

{

i=0;j=0;m=0;/*i指示A中元素原来的位置,m为移动后的位置*/

while(i

{

if(B.elem[j]

elseif(B.elem[j]>C.elem[k])k++;

else{

same=B.elem[j];/*找到了相同元素same*/

while(B.elem[j]==same)j++;

while(C.elem[k])==same)k++;/*j,k后移到新的元素*/

while(i

A.elem[m++]=A.elem[i++];/*需要保留的元素移动到新位置*/

while(i

}/*else*/

}/*while*/

while(i

A.elem[m++]=A.elem[i++];/*A的剩余元素重新存储*/

A.length=m;

}/*SqList_Delete*/

【顺序存储结构参考程序】

#include

main()

{

#defineN3/*宏定义,代表数组维数*/

#defineM4

#defineT5

inti,j,k,r,m,same;/*定义变量分别指向数组a,b,c*/

inta[N],b[M],c[T];

printf(“pleaseinputnumbers:

\n”);

for(i=0;i

for(j=0;j

for(k=0;k

i=0;j=0;m=0;k=0;/*分别赋值为0,即指向数组的第一元素*/

while(i

{

if(b[j]

elseif(b[j]>c[k])k++;

else{

same=b[j];

while(b[j]==same)j++;

while(c[k]==same)k++;

while(i

a[m++]=a[i++];

while(i

}

}

while(i

a[m++]=a[i++];

printf("a[%d]={",m);/*输出删除元素后的数组a/*

for(r=0;r

printf("%d",a[m-1]);

printf("}\n");

return;

}

【程序调试】

程序运行是屏幕显示:

pleaseinputnumbers:

此时输入三组测试数据,数据间用空格隔开:

234回车

3456回车

45678回车

程序输出结果:

a[3]={2,3},即删除了数组a中即在b和c中都出现的元素。

【单链表存储结构参考程序】

#include

#include

TypedefstructLNode{

intdata;

structLNode*next;

}Lnode,*LinkList;/*定义链表节点的结构*/

voidmain()

{/*功能:

建立单链表A,B,C,并且删除A中均在B和C中出现的数据。

*/

CreateList(LinkListhead);/*函数声明*/

ListDelete(LinkListLa,LinkListLb,LinkListLc);

Print(LinkListhead);

LinkListheadA,headB,headC;

headA=NULL;

headB=NULL;

headC=NULL;

headA=CreateList(headA);/*建立链表*/

headB=CreateList(headB);

headC=CreateList(headC);

print(headA);/*输出显示链表数据*

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1