数据结构C语言版 树的双亲表存储表示Word文档格式.docx
《数据结构C语言版 树的双亲表存储表示Word文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版 树的双亲表存储表示Word文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
'
;
//以空格符为空
intInitTree(PTree*T)
{//操作结果:
构造空树T
(*T).n=0;
return1;
}
voidDestroyTree()
{
//由于PTree是定长类型,无法销毁
//构造一个空队列Q
intInitQueue(LinkQueue*Q)
(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));
//动态分配一个空间
if(!
(*Q).front)
exit(0);
(*Q).front->
next=NULL;
//队头指针指向空,无数据域,这样构成了一个空队列
//若Q为空队列,则返回1,否则返回0
intQueueEmpty(LinkQueueQ)
if(Q.front==Q.rear)
return1;
else
return0;
//插入元素e为Q的新的队尾元素
intEnQueue(LinkQueue*Q,QElemTypee)
QueuePtrp=(QueuePtr)malloc(sizeof(QNode));
p)//存储分配失败
//生成一个以为e为数据域的队列元素
p->
data=e;
//将该新队列元素接在队尾的后面
(*Q).rear->
next=p;
(*Q).rear=p;
//若队列不空,删除Q的队头元素,用e返回其值,并返回1,否则返回0
intDeQueue(LinkQueue*Q,QElemType*e)
QueuePtrp;
if((*Q).front==(*Q).rear)
p=(*Q).front->
next;
//队头元素
*e=p->
data;
next=p->
if((*Q).rear==p)
(*Q).rear=(*Q).front;
free(p);
//构造树T
intCreateTree(PTree*T)
LinkQueueq;
QElemTypep,qq;
inti=1,j,l;
charc[MAX_TREE_SIZE];
//临时存放孩子结点数组
InitQueue(&
q);
//初始化队列
printf("
请输入根结点(字符型,空格为空):
"
);
scanf("
%c%*c"
&
(*T).nodes[0].data);
//根结点序号为0,%*c吃掉回车符
if((*T).nodes[0].data!
=Nil)//非空树
{
(*T).nodes[0].parent=-1;
//根结点无双亲
qq.name=(*T).nodes[0].data;
qq.num=0;
EnQueue(&
q,qq);
//入队此结点
while(i<
MAX_TREE_SIZE&
&
!
QueueEmpty(q))//数组未满且队不空
{
DeQueue(&
q,&
qq);
//出队一个结点
printf("
请按长幼顺序输入结点%c的所有孩子:
qq.name);
gets(c);
l=strlen(c);
for(j=0;
j<
l;
j++)
{
(*T).nodes[i].data=c[j];
(*T).nodes[i].parent=qq.num;
p.name=c[j];
p.num=i;
EnQueue(&
q,p);
i++;
}
}
if(i>
MAX_TREE_SIZE)
结点数超过数组容量\n"
exit(0);
(*T).n=i;
}
(*T).n=0;
#defineClearTreeInitTree//二者操作相同
//若T为空树,则返回1,否则返回0
intTreeEmpty(PTreeT)
if(T.n)
//返回T的深度
intTreeDepth(PTreeT)
intk,m,def,
max=0;
//存储深度
for(k=0;
k<
T.n;
++k)
def=1;
//初始化本际点的深度
m=T.nodes[k].parent;
while(m!
=-1)
m=T.nodes[m].parent;
def++;
if(max<
def)
max=def;
returnmax;
//最大深度
//返回T的根
TElemTypeRoot(PTreeT)
inti;
for(i=0;
i<
i++)
if(T.nodes[i].parent<
0)
returnT.nodes[i].data;
returnNil;
//返回第i个结点的值
TElemTypeValue(PTreeT,inti)
if(i<
T.n)
returnT.nodes[i].data;
returnNil;
//改cur_e为value
intAssign(PTree*T,TElemTypecur_e,TElemTypevalue)
intj;
for(j=0;
(*T).n;
if((*T).nodes[j].data==cur_e)
(*T).nodes[j].data=value;
return1;
return0;
//若cur_e是T的非根结点,则返回它的双亲,否则函数值为"空"
TElemTypeParent(PTreeT,TElemTypecur_e)
for(j=1;
j<
T.n;
j++)//根结点序号为0
if(T.nodes[j].data==cur_e)
returnT.nodes[T.nodes[j].parent].data;
//若cur_e是T的非叶子结点,则返回它的最左孩子,否则返回"空"
TElemTypeLeftChild(PTreeT,TElemTypecur_e)
inti,j;
if(T.nodes[i].data==cur_e)//找到cur_e,其序号为i
break;
for(j=i+1;
j++)//根据树的构造函数,孩子的序号>其双亲的序号
//根据树的构造函数,最左孩子(长子)的序号<其它孩子的序号
if(T.nodes[j].parent==i)
returnT.nodes[j].data;
//若cur_e有右(下一个)兄弟,则返回它的右兄弟,否则返回"空"
TElemTypeRightSibling(PTreeT,TElemTypecur_e)
if(T.nodes[i].data==cur_e)//找到cur_e,其序号为i
if(T.nodes[i+1].parent==T.nodes[i].parent)
//根据树的构造函数,若cur_e有右兄弟的话则右兄弟紧接其后
returnT.nodes[i+1].data;
//输出树T
intPrint(PTreeT)
结点个数=%d\n"
T.n);
结点双亲\n"
printf("
%c"
Value(T,i));
//结点
if(T.nodes[i].parent>
=0)//有双亲
Value(T,T.nodes[i].parent));
//双亲
\n"
//插入c为T中p结点的第i棵子树
intInsertChild(PTree*T,TElemTypep,inti,PTreec)
intj,k,l,f=1,n=0;
//设交换标志f的初值为1,p的孩子数n的初值为0
PTNodet;
TreeEmpty(*T))//T不空
for(j=0;
j++)//在T中找p的序号
if((*T).nodes[j].data==p)//p的序号为j
break;
l=j+1;
//如果c是p的第1棵子树,则插在j+1处
if(i>
1)//c不是p的第1棵子树
for(k=j+1;
k<
(*T).n;
k++)//从j+1开始找p的前i-1个孩子
if((*T).nodes[k].parent==j)//当前结点是p的孩子
{
n++;
//孩子数加1
if(n==i-1)//找到p的第i-1个孩子,其序号为k1
break;
}
l=k+1;
//c插在k+1处
}//p的序号为j,c插在l处
if(l<
(*T).n)//插入点l不在最后
//依次将序号l以后的结点向后移c.n个位置
for(k=(*T).n-1;
k>
=l;
k--)
(*T).nodes[k+c.n]=(*T).nodes[k];
//向后移c.n个位置
if((*T).nodes[k].parent>
=l)
(*T).nodes[k+c.n].parent+=c.n;
for(k=0;
c.n;
k++)
(*T).nodes[l+k].data=c.nodes[k].data;
//依次将树c的所有结点插于此处
(*T).nodes[l+k].parent=c.nodes[k].parent+l;
(*T).nodes[l].parent=j;
//树c的根结点的双亲为p
(*T).n+=c.n;
//树T的结点数加c.n个
while(f)
{//从插入点之后,将结点仍按层序排列
f=0;
//交换标志置0
for(j=l;
(*T).n-1;
j++)
if((*T).nodes[j].parent>
(*T).nodes[j+1].parent)
//如果结点j的双亲排在结点j+1的双亲之后(树没有按层序排
//列),交换两结点
t=(*T).nodes[j];
(*T).nodes[j]=(*T).nodes[j+1];
(*T).nodes[j+1]=t;
f=1;
//交换标志置1
for(k=j;
k++)//改变双亲序号
if((*T).nodes[k].parent==j)
(*T).nodes[k].parent++;
//双亲序号改为j+1
elseif((*T).nodes[k].parent==j+1)
(*T).nodes[k].parent--;
//双亲序号改为j
else//树T不存在
intdeleted[MAX_TREE_SIZE+1];
//删除标志数组(全局量)
//删除T中结点p的第i棵子树
voidDeleteChild(PTree*T,TElemTypep,inti)
intj,k,n=0;
QElemTypepq,qq;
=(*T).n;
deleted[j]=0;
//置初值为0(不删除标记)
pq.name='
a'
//此成员不用
if((*T).nodes[j].data==p)
//j为结点p的序号
for(k=j+1;
if((*T).nodes[k].parent==j)
n++;
if(n==i)
//k为p的第i棵子树结点的序号
if(k<
(*T).n)//p的第i棵子树结点存在
n=0;
pq.num=k;
deleted[k]=1;
//置删除标记
n++;
q,pq);
while(!
QueueEmpty(q))
for(j=qq.num+1;
if((*T).nodes[j].parent==qq.num)
pq.num=j;
deleted[j]=1;
EnQueue(&
if(deleted[j]==1)
for(k=j+1;
deleted[k-1]=deleted[k];
(*T).nodes[k-1]=(*T).nodes[k];
if((*T).nodes[k].parent>
j)
(*T).nodes[k-1].parent--;
j--;
(*T).n-=n;
//n为待删除结点数
//层序遍历树T,对每个结点调用函数Visit一次且仅一次
voidTraverseTree(PTreeT,void(*Visit)(TElemType))
Visit(T.nodes[i].data);
voidvi(TElemTypec)
%c"
c);
intmain()
PTreeT,p;
TElemTypee,e1;
InitTree(&
T);
构造空树后,树空否?
%d(1:
是0:
否)树根为%c树的深度为%d\n"
TreeEmpty(T),Root(T),TreeDepth(T));
CreateTree(&
构造树T后,树空否?
层序遍历树T:
TraverseTree(T,vi);
请输入待修改的结点的值新值:
%c%*c%c%*c"
e,&
e1);
Assign(&
T,e,e1);
层序遍历修改后的树T:
%c的双亲是%c,长子是%c,下一个兄弟是%c\n"
e1,
Parent(T,e1),LeftChild(T,e1),RightSibling(T,e1));
建立树p:
p);
层序遍历树p:
TraverseTree(p,vi);
将树p插到树T中,请输入T中p的双亲结点子树序号:
%c%d%*c"
i);
InsertChild(&
T,e,i,p);
Print(T);
删除树T中结点e的第i棵子树,请输入ei:
%c%d"
DeleteChild(&
T,e,i);
system("
pause"
输出效果:
1(1:
否)树根为树的深度为0
a
请按长幼顺序输入结点a的所有孩子:
bc
请按长幼顺序输入结点b的所有孩子:
d
请按长幼顺序输入结点c的所有孩子:
e
请按长幼顺序输入结点d的所有孩子:
请按长幼顺序输入结点e的所有孩子:
0(1:
否)树根为a树的深度为3
abcde
ef
abcdf
f的双亲是c,长子是,下一个兄弟是
A
请按长幼顺序输入结点A的所有孩子:
B
请按长幼顺序输入结点B的所有孩子:
AB
b2
结点个数=7
结点双亲
ba
ca
db
Ab
fc
BA
a1
结点个数=3
请按任意键继续...