// c6-5.h 树的二叉链表(孩子—兄弟)存储结构(见图6.32)
typedef struct CSNode
{TElemType data;CSNode *firstchild,*nextsibling;
}CSNode,*CSTree;

一棵树无论有多少叉,它最多有一个长子和一个排序恰在其下的兄弟。根据这样的定
义,则每个结点的结构就都统一到了二叉链表结构上。这样有利于对结点进行操作。图
633 是图628(a)所示之树的二叉链表(孩子—兄弟)存储结构。

// func6-2.cpp bo6-5.cpp和algo7-1.cpp调用
void PreOrderTraverse(CSTree T,void(*Visit)(TElemType))
{ // 先根遍历孩子—兄弟二叉链表结构的树Tif(T){Visit(T->data); // 先访问根结点PreOrderTraverse(T->firstchild,Visit); // 再先根遍历长子子树PreOrderTraverse(T->nextsibling,Visit); // 最后先根遍历下一个兄弟子树}
}
// bo6-5.cpp 树的二叉链表(孩子—兄弟)存储(存储结构由c6-5.h定义)的基本操作(17个)
#define ClearTree DestroyTree // 二者操作相同
#include"func6-2.cpp" // 包括PreOrderTraverse()
void InitTree(CSTree &T)
{ // 操作结果:构造空树TT=NULL;
}
void DestroyTree(CSTree &T)
{ // 初始条件:树T存在。操作结果:销毁树Tif(T){if(T->firstchild) // T有长子DestroyTree(T->firstchild); // 销毁T的长子为根结点的子树if(T->nextsibling) // T有下一个兄弟DestroyTree(T->nextsibling); // 销毁T的下一个兄弟为根结点的子树free(T); // 释放根结点T=NULL;}
}
typedef CSTree QElemType; // 定义队列元素类型
#include"c3-2.h" // 定义LinkQueue类型(链队列)
#include"bo3-2.cpp" // LinkQueue类型的基本操作
void CreateTree(CSTree &T)
{ // 构造树Tchar c[20]; // 临时存放孩子结点(设不超过20个)的值CSTree p,p1;LinkQueue q;int i,l;InitQueue(q);printf("请输入根结点(字符型,空格为空): ");scanf("%c%*c",&c[0]);if(c[0]!=Nil) // 非空树{T=(CSTree)malloc(sizeof(CSNode)); // 建立根结点T->data=c[0];T->nextsibling=NULL;EnQueue(q,T); // 入队根结点的指针while(!QueueEmpty(q)) // 队不空{DeQueue(q,p); // 出队一个结点的指针printf("请按长幼顺序输入结点%c的所有孩子: ",p->data);gets(c);l=strlen(c);if(l>0) // 有孩子{p1=p->firstchild=(CSTree)malloc(sizeof(CSNode)); // 建立长子结点p1->data=c[0];for(i=1;i<l;i++){p1->nextsibling=(CSTree)malloc(sizeof(CSNode)); // 建立下一个兄弟结点EnQueue(q,p1); // 入队上一个结点p1=p1->nextsibling;p1->data=c[i];}p1->nextsibling=NULL;EnQueue(q,p1); // 入队最后一个结点}elsep->firstchild=NULL; // 长子指针为空}}elseT=NULL; // 空树
}
Status TreeEmpty(CSTree T)
{ // 初始条件:树T存在。操作结果:若T为空树,则返回TURE;否则返回FALSEif(T) // T不空return FALSE;elsereturn TRUE;
}
int TreeDepth(CSTree T)
{ // 初始条件:树T存在。操作结果:返回T的深度CSTree p;int depth,max=0;if(!T) // 树空return 0;if(!T->firstchild) // 树无长子return 1;for(p=T->firstchild;p;p=p->nextsibling){ // 求子树深度的最大值depth=TreeDepth(p);if(depth>max)max=depth;}return max+1; // 树的深度=子树深度最大值+1
}
TElemType Value(CSTree p)
{ // 返回p所指结点的值return p->data;
}
TElemType Root(CSTree T)
{ // 初始条件:树T存在。操作结果:返回T的根if(T)return Value(T);elsereturn Nil;
}
CSTree Point(CSTree T,TElemType s)
{ // 返回二叉链表(孩子—兄弟)树T中指向元素值为s的结点的指针。另加LinkQueue q;QElemType a;if(T) // 非空树{InitQueue(q); // 初始化队列EnQueue(q,T); // 根结点入队while(!QueueEmpty(q)) // 队不空{DeQueue(q,a); // 出队,队列元素赋给aif(a->data==s)return a;if(a->firstchild) // 有长子EnQueue(q,a->firstchild); // 入队长子if(a->nextsibling) // 有下一个兄弟EnQueue(q,a->nextsibling); // 入队下一个兄弟}}return NULL;
}
Status Assign(CSTree &T,TElemType cur_e,TElemType value)
{ // 初始条件:树T存在,cur_e是树T中结点的值。操作结果:改cur_e为valueCSTree p;if(T) // 非空树{p=Point(T,cur_e); // p为cur_e的指针if(p) // 找到cur_e{p->data=value; // 赋新值return OK;}}return ERROR ; // 树空或没找到
}
TElemType Parent(CSTree T,TElemType cur_e)
{ // 初始条件:树T存在,cur_e是T中某个结点// 操作结果:若cur_e是T的非根结点,则返回它的双亲;否则函数值为“空”CSTree p,t;LinkQueue q;InitQueue(q);if(T) // 树非空{if(Value(T)==cur_e) // 根结点值为cur_ereturn Nil;EnQueue(q,T); // 根结点入队while(!QueueEmpty(q)){DeQueue(q,p);if(p->firstchild) // p有长子{if(p->firstchild->data==cur_e) // 长子为cur_ereturn Value(p); // 返回双亲t=p; // 双亲指针赋给tp=p->firstchild; // p指向长子EnQueue(q,p); // 入队长子while(p->nextsibling) // 有下一个兄弟{p=p->nextsibling; // p指向下一个兄弟if(Value(p)==cur_e) // 下一个兄弟为cur_ereturn Value(t); // 返回双亲EnQueue(q,p); // 入队下一个兄弟}}}}return Nil; // 树空或没找到cur_e
}
TElemType LeftChild(CSTree T,TElemType cur_e)
{ // 初始条件:树T存在,cur_e是T中某个结点// 操作结果:若cur_e是T的非叶子结点,则返回它的最左孩子;否则返回“空”CSTree f;f=Point(T,cur_e); // f指向结点cur_eif(f&&f->firstchild) // 找到结点cur_e且结点cur_e有长子return f->firstchild->data;elsereturn Nil;
}
TElemType RightSibling(CSTree T,TElemType cur_e)
{ // 初始条件:树T存在,cur_e是T中某个结点// 操作结果:若cur_e有右兄弟,则返回它的右兄弟;否则返回“空”CSTree f;f=Point(T,cur_e); // f指向结点cur_eif(f&&f->nextsibling) // 找到结点cur_e且结点cur_e有右兄弟return f->nextsibling->data;elsereturn Nil; // 树空
}
Status InsertChild(CSTree &T,CSTree p,int i,CSTree c)
{ // 初始条件:树T存在,p指向T中某个结点,1≤i≤p所指结点的度+1,非空树c与T不相交// 操作结果:插入c为T中p结点的第i棵子树// 因为p所指结点的地址不会改变,故p不需是引用类型int j;if(T) // T不空{if(i==1) // 插入c为p的长子{c->nextsibling=p->firstchild; // p的原长子现是c的下一个兄弟(c本无兄弟)p->firstchild=c;}else // 找插入点{p=p->firstchild; // 指向p的长子j=2;while(p&&j<i){p=p->nextsibling;j++;}if(j==i) // 找到插入位置{c->nextsibling=p->nextsibling;p->nextsibling=c;}else // p原有孩子数小于i-1return ERROR;}return OK;}else // T空return ERROR;
}
Status DeleteChild(CSTree &T,CSTree p,int i)
{ // 初始条件:树T存在,p指向T中某个结点,1≤i≤p所指结点的度// 操作结果:删除T中p所指结点的第i棵子树// 因为p所指结点的地址不会改变,故p不需是引用类型CSTree b;int j;if(T) // T不空{if(i==1) // 删除长子{b=p->firstchild;p->firstchild=b->nextsibling; // p的原次子现是长子b->nextsibling=NULL;DestroyTree(b);}else // 删除非长子{p=p->firstchild; // p指向长子j=2;while(p&&j<i){p=p->nextsibling;j++;}if(j==i) // 找到第i棵子树{b=p->nextsibling;p->nextsibling=b->nextsibling;b->nextsibling=NULL;DestroyTree(b);}else // p原有孩子数小于ireturn ERROR;}return OK;}elsereturn ERROR;
}
void PostOrderTraverse(CSTree T,void(*Visit)(TElemType))
{ // 后根遍历孩子—兄弟二叉链表结构的树TCSTree p;if(T){if(T->firstchild) // 有长子{PostOrderTraverse(T->firstchild,Visit); // 后根遍历长子子树p=T->firstchild->nextsibling; // p指向长子的下一个兄弟while(p){PostOrderTraverse(p,Visit); // 后根遍历下一个兄弟子树p=p->nextsibling; // p指向再下一个兄弟}}Visit(Value(T)); // 最后访问根结点}
}
void LevelOrderTraverse(CSTree T,void(*Visit)(TElemType))
{ // 层序遍历孩子—兄弟二叉链表结构的树TCSTree p;LinkQueue q;InitQueue(q);if(T){Visit(Value(T)); // 先访问根结点EnQueue(q,T); // 入队根结点的指针while(!QueueEmpty(q)) // 队不空{DeQueue(q,p); // 出队一个结点的指针if(p->firstchild) // 有长子{p=p->firstchild;Visit(Value(p)); // 访问长子结点EnQueue(q,p); // 入队长子结点的指针while(p->nextsibling) // 有下一个兄弟{p=p->nextsibling;Visit(Value(p)); // 访问下一个兄弟EnQueue(q,p); // 入队兄弟结点的指针}}}}
}
// main6-5.cpp 检验bo6-5.cpp的主程序
#include"c1.h"
typedef char TElemType;
TElemType Nil=' '; // 以空格符为空
#include"c6-5.h"
#include"bo6-5.cpp"
void vi(TElemType c)
{printf("%c ",c);
}
void main()
{int i;CSTree T,p,q;TElemType e,e1;InitTree(T);printf("构造空树后,树空否? %d(1:是0:否) 树根为%c 树的深度为%d\n",TreeEmpty(T),Root(T),TreeDepth(T));CreateTree(T);printf("构造树T后,树空否? %d(1:是0:否) 树根为%c 树的深度为%d\n",TreeEmpty(T),Root(T),TreeDepth(T));printf("先根遍历树T:\n");PreOrderTraverse(T,vi);printf("\n请输入待修改的结点的值新值: ");scanf("%c%*c%c%*c",&e,&e1);Assign(T,e,e1);printf("后根遍历修改后的树T:\n");PostOrderTraverse(T,vi);printf("\n%c的双亲是%c,长子是%c,下一个兄弟是%c\n",e1,Parent(T,e1),LeftChild(T,e1),RightSibling(T,e1));printf("建立树p:\n");InitTree(p);CreateTree(p);printf("层序遍历树p:\n");LevelOrderTraverse(p,vi);printf("\n将树p插到树T中,请输入T中p的双亲结点子树序号: ");scanf("%c%d%*c",&e,&i);q=Point(T,e);InsertChild(T,q,i,p);printf("层序遍历树T:\n");LevelOrderTraverse(T,vi);printf("\n删除树T中结点e的第i棵子树,请输入e i: ");scanf("%c%d",&e,&i);q=Point(T,e);DeleteChild(T,q,i);printf("层序遍历树T:\n",e,i);LevelOrderTraverse(T,vi);printf("\n");DestroyTree(T);
}

代码的运行结果:

构造空树后,树空否? 1(1:是0:否) 树根为树的深度为0
请输入根结点(字符型,空格为空): R
请按长幼顺序输入结点R的所有孩子: ABC
请按长幼顺序输入结点A的所有孩子: DE
请按长幼顺序输入结点B的所有孩子:
请按长幼顺序输入结点C的所有孩子: F
请按长幼顺序输入结点D的所有孩子:
请按长幼顺序输入结点E的所有孩子:
请按长幼顺序输入结点F的所有孩子: GHK
请按长幼顺序输入结点G的所有孩子:
请按长幼顺序输入结点H的所有孩子:
请按长幼顺序输入结点K的所有孩子:
构造树T后,树空否? 0(1:是0:否) 树根为R 树的深度为4
先根遍历树T:(见图628(a))
R A D E B C F G H K
请输入待修改的结点的值新值: D d
后根遍历修改后的树T:
d E A B G H K F C R
d的双亲是A,长子是,下一个兄弟是E
建立树p:
请输入根结点(字符型,空格为空): f
请按长幼顺序输入结点f的所有孩子: ghk
请按长幼顺序输入结点g的所有孩子:
请按长幼顺序输入结点h的所有孩子:
请按长幼顺序输入结点k的所有孩子:
层序遍历树p:(见图629)
f g h k
将树p插到树T中,请输入T中p的双亲结点子树序号: R 3
层序遍历树T:(见图630)
R A B f C d E g h k F G H K
删除树T中结点e的第i棵子树,请输入e i: C 1
层序遍历树T:(见图631)

R A B f C d E g h k

转载于:https://www.cnblogs.com/KongkOngL/p/3945943.html

树的存储结构(树的二叉链表(孩子—兄弟))相关推荐

  1. 二叉树的链式存储结构--二叉链表

    1 二叉树的链式存储结构 //二叉链表的结点结构定义typedef int TElemType; typedef struct BiTNode {TElemType data;struct BiTNo ...

  2. C#实现二叉树--二叉链表结构

    二叉树的简单介绍 关于二叉树的介绍请看这里 : 二叉树的简单介绍 http://www.cnblogs.com/JiYF/p/7048785.html 二叉链表存储结构: 二叉树的链式存储结构是指,用 ...

  3. 数据结构-二叉链表的结构与实现

    目录 一.引言 二.什么是二叉链表 三.二叉链表的结构 四.二叉链表的实现 1. 创建二叉链表 2. 遍历二叉链表 3. 插入节点 4. 删除节点 五.应用场景 六.总结 七.代码示例 一.引言 数据 ...

  4. 6-2-二叉树(二叉链表存储)-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版...

    课本源码部分 第6章  树和二叉树 - 二叉树(二叉链表存储) --<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴 ...

  5. 二叉树的二叉链表存储结构构建以及先序遍历

    #include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR -1 typedef int TElemTy ...

  6. 树的存储结构-孩子兄弟表示法

    实现:用二叉链表作树的存储结构,链表中每个结点的两个指针域分别指向其第一个孩子结点和下一个兄弟结点 代码如下: #include <iostream> using namespace st ...

  7. 数据结构之树的存储结构

    数据结构之树的存储结构 思维导图 双亲表示法: 增 删 孩子表示法: 孩子兄弟表示法:(重要) 森林和二叉树的转化 思维导图 双亲表示法: 增 增加M.L节点 删 删除G节点(叶节点) 删除(非叶节点 ...

  8. 理论基础 —— 树 —— 树的存储结构

    [父亲表示法] 由于树中每个结点均有且仅有一个父结点,那么根据这一特性,用一维数组来存储树的各个结点(一般按层序存储),数组中的一个元素对应树中的一个结点,每个结点记录两类信息:结点的数据信息.该结点 ...

  9. 树的概念及存储结构(双亲表示法,孩子表示法,孩子兄弟表示法)

    文章目录 一. 树的概念 二. 树的存储结构 (一). 双亲表示法 (二). 孩子表示法 1. 定长结点链表存储结构 2. 孩子链表存储结构 (三). 孩子兄弟表示法 一. 树的概念 树(Tree)是 ...

最新文章

  1. 【转】 linux iio子系统
  2. 矩形在as3视觉编程中的几个应用方式
  3. Xml文件数据的优点
  4. mac下php mysql数据库文件怎么打开_Mac环境下php操作mysql数据库的方法分享
  5. List集合的特有功能概述
  6. Sequelize 中文文档 v4 - Querying - 查询
  7. Java中synchronized同步块的执行流程
  8. Python a和a[:]的区别
  9. 技术人看《长安十二时辰》的正确姿势是?
  10. 计算机最低分怎么英语,编写一个学生类 有年龄 英语、数学、计算机三门成绩 求平均分、最高分、最低分...
  11. 模拟信号的数字处理方法
  12. editplus破解源码
  13. 网络编程之TCP例子一(帅帅老师讲堂)
  14. 头孢一代比一代强吗?
  15. 抖音python广告用的什么音乐_被抖音捧火的几首纯音乐,都是你们要的原版,太震撼人心!...
  16. 在centos上安装vmware14
  17. docer kafka安装
  18. 你偷看的小黄片,全被监视了!网友:隐私早已。。。
  19. ChatGPT的各项超能力从哪儿来?万字拆解追溯技术路线图来了!
  20. 使用localStorage完成Vue项目中的历史搜索

热门文章

  1. 赢在中国 (2008-3-19)
  2. Python 中的range,以及numpy包中的arange函数
  3. js 日期星期 带农历
  4. 批处理详细教程(五)
  5. Android应用开发—Android 消息处理机制:HandlerMessage
  6. php控制器教程,laravel基础教程 -- 控制器
  7. Ubuntu17.04 之 systemd 设置开机启动
  8. 逻辑综合工具DesignCompiler使用教程
  9. Flask中的 url_for() 函数
  10. Android 开源优秀 Library 推荐