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

// 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

i12蓝牙耳机使用说明书图片_配置强悍、适用于开车、运动的蓝牙耳机Xisem西圣 Ares使用体验...

现在的蓝牙耳机市场五花八门、有降噪的、有高保真音质的、有适用于运动不掉的… … 真有是各出奇招。那么作为消费者应该如何选择呢&#xff1f;前段时间入手一款硬件配置很高、无论是开车&#xff0c;还是运动都适用的蓝牙耳机“Xisem西圣 Ares真无线蓝牙耳机”。包装简介&…

LeetCode 918. 环形子数组的最大和(前缀和+单调队列)

文章目录1. 题目2. 解题1. 题目 给定一个由整数数组 A 表示的环形数组 C&#xff0c;求 C 的非空子数组的最大可能和。 在此处&#xff0c;环形数组意味着数组的末端将会与开头相连呈环状。 &#xff08;形式上&#xff0c;当0 < i < A.length 时 C[i] A[i]&#xff0…

小案例:王者荣耀战力查询系统(免费调用外部接口

一、查询网址&#xff08;点击&#xff09;&#xff1a; 王者战力查询-王者战力排行榜 二、战力查询接口&#xff1a; 接口调用&#xff1a; https://www.jk.cxkf.cc/api_select.php参数&#xff1a; hero&#xff1a;英雄名字 type&#xff1a;qq、wx、ios_qq、ios_wxqq&…

open函数返回-1_4.6 linux的系统调用执行探究(1)

arm64大约支持280个系统调用&#xff0c;我们平时使用的这些系统调用&#xff0c;到底工作原理是什么&#xff0c;调用后又是到哪里实现的呢&#xff0c;这篇文章初步了解下内核系统调用的流程&#xff0c;并告诉跟踪这个流程的方法。废话不多说&#xff0c;如上就是linux的系统…

LeetCode 781. 森林中的兔子(哈希+贪心)

文章目录1. 题目2. 解题1. 题目 森林中&#xff0c;每个兔子都有颜色。 其中一些兔子&#xff08;可能是全部&#xff09;告诉你还有多少其他的兔子和自己有相同的颜色。 我们将这些回答放在 answers 数组里。 返回森林中兔子的最少数量。 示例: 输入: answers [1, 1, 2] 输…

C#操作Excel(1)Excel对象模型

Excel对象模型 &#xff08;.Net Perspective&#xff09; 本文主要针对在Visual Studio中使用C# 开发关于Excel的应用程序 本文的PDF下载地址&#xff1a;C#操作Excel2007.pdf 来源&#xff1a;Understandingthe Excel Object Model from a .NET Developers Perspective Exce…

蓝牙适配器 能同时接多少个设备_便携音箱也能有立体环绕声,JVC智能蓝牙颈挂音箱体验...

说起音箱&#xff0c;相信音乐爱好者是很熟悉了&#xff0c;而随着蓝牙技术的不断发展&#xff0c;便携式蓝牙音箱开始受到越来越多用户的喜爱&#xff0c;它能够让我们摆脱线材束缚&#xff0c;随时随地畅享音乐。虽然便携式蓝牙音箱小巧易携带&#xff0c;音质方面也在不断提…

LeetCode 1156. 单字符重复子串的最大长度

文章目录1. 题目2. 解题1. 题目 如果字符串中的所有字符都相同&#xff0c;那么这个字符串是单字符重复的字符串。 给你一个字符串 text&#xff0c;你只能交换其中两个字符一次或者什么都不做&#xff0c;然后得到一些单字符重复的子串。 返回其中最长的子串的长度。 示例 …

☆☆在Eclipse中编译NDK的so文件(普通安卓项目转换为NDK项目的设定)

1 将Native的编译链接配置加入项目中 2 进行编译 3 项目支持Native后&#xff0c;在首尾分别新增了两个编译过程 转载于:https://www.cnblogs.com/YangBinChina/p/3937287.html

小案例:利用图床自动化批量上传图片并获取图片链接

一、前言&#xff1a; 用python爬虫写了一个小脚本&#xff0c;用来自动上传图片到图床&#xff0c;然后返回链接&#xff0c;我们只需直接复制链接就可以。&#xff08;需要安装Requests库&#xff09;因为不同图床需要提交的POST表单不一致&#xff0c;所以在这里我用ImgURL…

LeetCode 497. 非重叠矩形中的随机点(前缀和+二分查找)

文章目录1. 题目2. 解题1. 题目 给定一个非重叠轴对齐矩形的列表 rects&#xff0c;写一个函数 pick 随机均匀地选取矩形覆盖的空间中的整数点。 提示&#xff1a; 整数点是具有整数坐标的点。 矩形周边上的点包含在矩形覆盖的空间中。 第 i 个矩形 rects [i] [x1&#xff0…

win10蓝屏提示重新启动_电脑蓝屏五大要素,秒判蓝屏问题及处理!

电脑蓝屏是个老生常谈的问题&#xff0c;而蓝屏问题也是电脑问题中最为复杂的问题之一&#xff0c;别说电脑小白&#xff0c;就是电脑老鸟有时候面对蓝屏都会犯怵&#xff01;简单来说&#xff0c;电脑蓝屏就好像人类突然晕倒&#xff0c;或者最严重的情况直接死亡&#xff0c;…

LeetCode 528. 按权重随机选择(前缀和+二分查找)

文章目录1. 题目2. 解题1. 题目 给定一个正整数数组 w &#xff0c;其中 w[i] 代表下标 i 的权重&#xff08;下标从 0 开始&#xff09;&#xff0c;请写一个函数 pickIndex &#xff0c;它可以随机地获取下标 i&#xff0c;选取下标 i 的概率与 w[i] 成正比。 例如&#xf…

boss直聘改回系统头像_BOSS 直聘找工作,消息却已读不回?| 在线求职5条避坑指南...

前几天在半撇私塾的求职群里&#xff0c;一个同学反馈&#xff1a;在 BOSS 直聘求职的时候&#xff0c;为什么总是被「已读不回」呢&#xff1f;就连逛豆瓣的上班小组&#xff0c;都能遇到这样的反馈&#xff1a;为什么会出现「已读不回」的情况呢&#xff1f;关于这个问题的答…

解决问题:Python调用cmd命令,出现中文乱码

一、前言&#xff1a; Python如何使用OS模块调用cmd 在os模块中提供了两种调用 cmd 的方法&#xff0c;os.popen() 和 os.system() os.system(cmd) 是在执行command命令时需要打开一个终端&#xff0c;并且无法保存command命令的执行结果。 os.popen(cmd,mode) 打开一个与c…

LeetCode 587. 安装栅栏 / LintCode 1152. 安装栅栏(凸包检测:排序+叉积正负判断+正反扫描+去重)

文章目录1. 题目2. 解题1. 题目 在一个二维的花园中&#xff0c;有一些用 (x, y) 坐标表示的树。 由于安装费用十分昂贵&#xff0c;你的任务是先用最短的绳子围起所有的树。 只有当所有的树都被绳子包围时&#xff0c;花园才能围好栅栏。 你需要找到正好位于栅栏边界上的树的…

arduino读取水位传感器的数据显示在基于i2c的1602a上_XSB-IC-S2智能水位监测仪-老友网...

XSB-IC-S2智能水位监测仪 多功能本身就是智能仪器仪表的一个特点。例如&#xff0c;为了设计速度较快和结构较复杂的数字系统&#xff0c;仪器生产厂家制造了具有脉冲发生器、频率合成器和任意波形发生器等功能的函数发生器。这种多功能的综合型产品不但在性能上(如准确度)比专…

七夕小案例:用代码给心爱的她画一个爱心

一、爱心示例&#xff1a; 二、开始写代码&#xff1a; /* * Hi。宝贝&#xff01; * 这么久了。还没和宝贝说过我的工作呢&#xff01; * 我是个前端工程师。俗称程序员。网页相关。 * 如这个页面。就是个什么也没有的网页。 * 我的工作就是给这种空白的页面加点儿东西。 * 嗯…

小案例:13行python代码实现对微信进行推送消息

一、前言&#xff1a; Python可以实现给QQ邮箱、企业微信、微信等等软件推送消息&#xff0c;今天咱们实现一下Python直接给微信推送消息。 这里咱们使用了一个第三方工具pushplus 二、单人推送 实现步骤&#xff1a; 1、用微信注册一个此网站的账号 2、将token复制出来&am…

python书籍_Python书籍大汇总——入门到实战

学习Python的朋友们越来越多&#xff0c;当当网和京东上面的Python类编程书籍&#xff0c;也从几年前寥寥无几到现在多的不知道选哪本才好了的地步。无论是自学还是参加培训班跟着老师学习&#xff0c;我们都需要几本实用的Python书&#xff0c;系统全面的掌握Python编程的相关…