王道——数据结构——树与二叉树(3)
系列文章目录
其他章节相关文章
王道——数据结构——栈和队列(1)
本章节其他相关文章
王道——数据结构——树与二叉树(1)
王道——数据结构——树与二叉树(2)
王道——数据结构——树与二叉树(4)
文章目录
- 系列文章目录
- 其他章节相关文章
- 本章节其他相关文章
- 前言
- 一、5.3节
前言
本文为王道数据结构的第五章——树与二叉树的编程题。
运行软件:vscode
使用c++文件编写
本文所使用的树为《王道——数据结构——树与二叉树(1)》中建立的树
一、5.3节
11、已知二叉树以二叉链表存储,编写算法完成:对于树中的每个元素值为x的结点,删去以它为根节点的子树,并释放相应的空间。
// 第十一题 使用层次遍历主树,发现结点值为x时,对x的子树进行后续遍历,访问各结点时删除结点
// 复杂版
void test11(){BiTree T;InitBiTree(T);buildTree(T);PreOrder(T);int x;printf("\n请输入你想删除的元素值:");scanf("%d", &x);BiTNode *p, *temp, *last, *par;LinkQueue Q; // 使用队列进行层次遍历,只有结点不为x的值才能入队InitLinkQueue(Q);LinkStack S;InitLinkStack(S); // 使用栈进行后续遍历EnQueue(Q, T);while(Q.front->next != NULL){DeQueue(Q, p);temp = p->lchild;if(temp && temp->data.value == x){ // 删去以x为根节点的子树while (temp || S != NULL){if(temp){Push(S, temp);temp = temp->lchild;}else{if(S->data->rchild != last && S->data->rchild != NULL)temp = S->data->rchild;else{Pop(S, last);free(last);}}}p->lchild = NULL;}else if(temp != NULL)EnQueue(Q, p->lchild);temp = p->rchild;if(temp && temp->data.value == x){ // 删去以x为根节点的子树while (temp || S != NULL){if(temp){Push(S, temp);temp = temp->lchild;}else{if(S->data->rchild != last && S->data->rchild != NULL)temp = S->data->rchild;else{Pop(S, last);free(last);}}}p->rchild = NULL;}else if(p->rchild != NULL)EnQueue(Q, p->rchild);}PreOrder(T);
}// 简洁版 通过函数调用实现
void Delechild(BiTree T){if(T->lchild != NULL)Delechild(T->lchild);if(T->rchild != NULL)Delechild(T->rchild);free(T);
}void test11_2(){BiTree T;InitBiTree(T);buildTree(T);PreOrder(T);int x;printf("\n请输入你想删除的元素值:");scanf("%d", &x);BiTNode *p;LinkQueue Q; // 使用队列进行层次遍历,只有结点不为x的值才能入队InitLinkQueue(Q);EnQueue(Q, T);while(Q.front->next != NULL){DeQueue(Q, p);if(p->lchild != NULL){if(p->lchild->data.value == x){Delechild(p->lchild);p->lchild = NULL;}elseEnQueue(Q, p->lchild);}if(p->rchild != NULL){if(p->rchild->data.value == x){Delechild(p->rchild);p->rchild = NULL;}elseEnQueue(Q, p->rchild);}}PreOrder(T);
}
12、在二叉树中查找值为x的结点,试编写算法(用C语言)打印值为x的结点的所有祖先节点,假设值为x的结点不多于一个
// 第十二题(用C) 使用后续遍历,设立标志tag=0,当发现x时tag变为1,访问节点时判断tag是否为1,如果为1打印输出该结点
int test12(BiTree T, int x, int tag){if(T->data.value == x)tag = 1;if(tag == 0 && T->lchild != NULL)tag = test12(T->lchild, x, tag);if(tag == 0 && T->rchild != NULL)tag = test12(T->rchild, x, tag);if(tag == 1 && T->data.value != x)printf("%d ", T->data.value);return tag;// 运行代码// BiTree T;// InitBiTree(T);// buildTree(T);// int x, tag = 0;// printf("请输入你想查找的数字:");// scanf("%d", &x);// x = test12(T, x, tag);
}
13、设一棵二叉树的结点结构为(LLINK,INFO,RLINK),ROOT为指向该二叉树根节点的指针,p和q分别为指向二叉树中任意两个结点的指针,试编写算法ANCESTOR(ROOT, p, q, r),找到p和q的最近公共结点r。
// 第十三题 使用后续遍历的方法建立两个栈分别保存p,q的祖先结点,假设p在q左边,则必先遍历到p再遍历到q
// 使用新的栈对两个栈进行逆置,分别对两个新的栈进行遍历找到最近公共结点
// 找a结点所有的祖先节点并保存在栈中
LinkStack Stackparent(BiTree T, int a){LinkStack S;InitLinkStack(S);BiTNode *p = T, *last;while (p || S!= NULL){if(p){Push(S, p);p = p->lchild;}else{if(S->data->rchild != NULL && S->data->rchild != last)p = S->data->rchild;else{if(S->data->data.value == a)break;Pop(S, last);}}}return S;
}void test13(){BiTree T;InitBiTree(T);buildTree(T);printf("请输入你想查找的第一个结点值:");int a, b;scanf("%d", &a);printf("请输入你想查找的第二个结点值:");scanf("%d", &b);LinkStack S1, S2, SN1, SN2;InitLinkStack(S1);InitLinkStack(S2);InitLinkStack(SN1);InitLinkStack(SN2);BiTNode *temp;S1 = Stackparent(T, a); // 找a的所有祖先节点S2 = Stackparent(T, b); // 找b的所有祖先结点while(S1 != NULL){ // 将S1逆置Pop(S1, temp);Push(SN1, temp);}while(S2 != NULL){ // 将S2逆置Pop(S2, temp);Push(SN2, temp);}StackNode *p = SN1, *q = SN2;while(p->next != NULL && q->next != NULL){ // 如果遍历的其中一个栈的最后一个元素还没有找到不同的元素,那么其中一个结点是另一个结点的孩子结点if(p->next->data == q->next->data){ // 从一棵树找到的两个结点,根节点肯定是公共结点,这里直接从第二个结点开始计算 p = p->next;q = q->next;}elsebreak;}printf("最近公共结点值为:%d",p->data->data.value);
}
14、假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树b的宽度。
// 第十四题 使用队列进行层次遍历,用weigh计算每层结点个数,weighest保存最宽的层结点数
// 使用last指针指向每层的最后一个元素,当访问到last指针时,last指针指向下一层最后一个元素
void test14(){BiTree T;InitBiTree(T);buildTree(T);LinkQueue Q;InitLinkQueue(Q);BiTNode *p = T, *last = T;int weight = 0, weightest = 0;EnQueue(Q, p);while(Q.front->next != NULL){DeQueue(Q, p);weight++;if(p->lchild != NULL)EnQueue(Q, p->lchild);if(p->rchild != NULL)EnQueue(Q, p->rchild);if(p == last){last = Q.rear->data;if(weight > weightest)weightest = weight;weight = 0;}}printf("树的宽度:%d", weightest);
}
15、设有一棵满二叉树(所有结点值均不同),已知其先序序列为pre,设计一个算法求其后序序列post。
// 第十五题 将先序序列的第一个元素放到后序序列的最后一个元素上,先序序列除了第一个元素剩下的所有元素为左右子树的总和——根左右
// 左子树为其二分之一,将左子树从后序序列第一个位置开始防止,然后放右子树
// l1为先序序列的开始位置,h1为先序序列的最后一个元素位置,l2为后序序列开始位置,h2为后序序列最后一个元素位置
void GetPostOrder(int pre[], int l1, int h1, int post[7], int l2, int h2){if(l1<=h1){post[h2] = pre[l1];int half;half = (h1-l1)/2;GetPostOrder(pre, l1+1, l1+half, post, l2, l2+half-1);GetPostOrder(pre, l1+half+1, h1, post, l2+half, h2-1); }
}void test15(){int pre[7] = {1,2,4,5,3,6,7};int post[7];GetPostOrder(pre, 0, 6, post, 0, 6);printf("后序序列:");for (int i = 0; i<7; i++){printf("%d ", post[i]);}
}
16、设计一个算法将二叉树的叶节点按从左到右的顺序连成一个单链表,表头指针为head。二叉树按二叉链表方式存储,链接时用叶节点的右指针域来存放单链表指针。
// 第十六题 使用栈对二叉树进行后序遍历,找到叶子结点,将pre指针指向叶子结点,找到下一个叶子结点时,将pre的右孩子指向该结点,并将pre指向该结点
void test16(){BiTree T;InitBiTree(T);buildTree(T);LinkStack S;InitLinkStack(S);BiTNode *p = T, *pre = NULL, *last, *temp, *testnode;while(p || S!=NULL){if(p){Push(S, p);p =p->lchild;}else{if(S->data->rchild != NULL && S->data->rchild != last)p = S->data->rchild;else{Pop(S, temp);if(temp->lchild == NULL && temp->rchild == NULL){if(pre)pre->rchild = temp;pre = temp;}last = temp;}}}p = T;while(p->lchild != NULL ) // 为了方便测试,树做左边必须有一个叶子节点p = p->lchild;while(p != NULL){printf("%d ", p->data.value);p = p->rchild;}}
17、试设计判断两棵树是否相似的算法。所谓二叉树T1和T2相似,指的是T1和T2都是空的二叉树或都只有一个根节点;或T1的左子树和T2的左子树相似,且T1的右子树和T2的右子树相似。
// 第十七题 相似:树的结构相同,形状相同,元素可以不同,使用标志位tag记录结构是否相同,1代表相同,0代表不同
void same(BiTree T1, BiTree T2, int &tag){if(tag == 0)return;if(T1 == NULL && T2 != NULL){tag = 0;}else if(T1 != NULL && T2 == NULL){tag = 0;}else if(T1 != NULL){same(T1->lchild, T2->lchild, tag);same(T1->rchild, T2->rchild, tag);}return;
}void test17(){BiTree T1, T2;printf("下面建立第一棵树\n");InitBiTree(T1);buildTree(T1);printf("下面建立第二棵树\n");InitBiTree(T2);buildTree(T2);int tag = 1;same(T1, T2, tag);if(tag == 1)printf("两棵树相似");else printf("两棵树不相似");
}
18、写出在中序线索二叉树里查找指定结点在后序的前驱结点算法。
// 第十八题 找后序线索二叉树指定节点的前驱结点,如果该结点的有右孩子不为空,则前驱结点为右孩子
// 如果该结点的右孩子为空但左孩子不为空,则前驱结点为左孩子
// 如果该结点的左右孩子都为空,则前驱结点为该结点祖先节点中最近的且不被访问过的左孩子
void test18_1(ThreadTree T, ThreadNode *p){if(p->rtag == 0)printf("%d", p->rchild->data.value);else if(p->ltag == 0)printf("%d", p->lchild->data.value);else{while(p->lchild != NULL && p->ltag != 0)p = p->lchild;if(p->lchild != NULL)printf("%d", p->lchild->data.value);else printf("该结点为后序遍历的第一个结点,没有前驱结点");}
}void test18(){ThreadTree T;InitThreadTree(T);buildTree(T);CreatTheadThree(T);Inorder(T);int x;printf("\n请输入你想要查询的数:");scanf("%d", &x);ThreadNode *p = T, *first;while(p->ltag == 0)p = p->lchild;while(p->data.value != x){if(p->rtag != 0)p = p->rchild;else{first = p->rchild;while(first->ltag == 0)first = first->lchild;p = first;}}printf("%d\n", p->data.value);test18_1(T, p);
}
19、二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和。给定一棵二叉树T,采用二叉链表存储,结点结构为:(left, weight, right),其中叶结点的weight域保存该结点的非负权值。设root为指向T的根结点的指针,请设计求T的WPL的算法。要求:
(1)给出算法的基本设计思想;
(2)使用C或C++语言,给出二叉树结点的数据类型定义;
(3)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
// 第十九题 采用队列实现二叉树的层次遍历,使用last标记每层最后一个元素,high记录层数,每个结点的带权路径长度为high*weight
// 树的带权路径长度为所有结点带权路径长度之和
typedef struct WPLNode{int weight;struct WPLNode *left, *right;
}WPLNode, *WPLTree;void test19(){BiTree T;InitBiTree(T);buildTree(T);LinkQueue Q;InitLinkQueue(Q);BiTNode *p, *last = T;int high = 1, sum = 0;EnQueue(Q, T);while(Q.front->next != NULL){DeQueue(Q, p);sum += high*p->data.value;if(p->lchild)EnQueue(Q, p->lchild);if(p->rchild)EnQueue(Q, p->rchild);if(p == last){high++;last = Q.rear->data;}}printf("%d", sum);
}
20、二叉树–请设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出。
// 第二十题 使用递归实现对二叉树的中序遍历,在访问结点时,加上左右括号,根节点和叶子节点不加括号
void test20_1(BiTNode *p, int &deep){if(deep != 1 ) // 根节点不加括号if(p->lchild != NULL || p->rchild != NULL) // 叶子结点不加括号printf("( ");if(p->lchild != NULL){deep++;test20_1(p->lchild, deep);deep--;}printf("%d ", p->data.value);if(p->rchild != NULL){deep++;test20_1(p->rchild, deep);deep--;}if(deep != 1)if(p->lchild != NULL || p->rchild != NULL)printf(") ");
}void test20(){BiTree T;InitBiTree(T);buildTree(T);int deep = 1;test20_1(T, deep);
}
王道——数据结构——树与二叉树(3)相关推荐
- 数据结构-树与二叉树-思维导图+小结
数据结构-树与二叉树-思维导图 1 数据结构-第五章-树与二叉树-思维导图 2 思维导图-补充 3 小结 3.1 知识点小结 3.2 习题小结 1 数据结构-第五章-树与二叉树-思维导图 数据结构 ...
- 数据结构——树和二叉树章节思维导图
数据结构--树和二叉树章节思维导图
- 数据结构—树与二叉树
总第119篇 前言 之前谈到的线性表.栈和队列都是一对一的数据结构,但是现实中也存在很多一对多的数据结构,这篇要写的就是一种一对多的数据结构---树.全文分为如下几部分: 树的一些基本概念 树的存储结 ...
- C语言 数据结构 树和二叉树
树 1.树:是n节点的有限集.树是n(n=>0)个节点的有限集. n=0时成为空树. 在任意一颗非空树中:(1)有且仅有一个称为根的节点:(2)当n>0时,其余节点可分为m(m>0) ...
- 数据结构-树,二叉树,森林
树,二叉树,森林 王卓老师的数据结构课程笔记 树和二叉树 定义 结点之间有分支,具有层次关系 是n个结点的有限集. 若n = 0,称为空树: 若n > 0,则它满足如下两个条件: 有且仅有一个特 ...
- 数据结构树、二叉树、完全二叉树、二叉查找树、平衡二叉树、红黑树、B+树
树.二叉树.平衡二叉树.二叉搜索树 树的前序遍历.中序遍历和后序遍历 树的前序遍历.中序遍历和后续遍历是以遍历时根所在的位置顺序命名的.层次遍历即按层从上至下,从左至右遍历即可. 前序遍历:根-> ...
- 数据结构--树和二叉树
文章目录 树和二叉树 树 1.树的定义 2.树的逻辑表示 3.树的基本术语: 4.树的性质 5.树的基本运算 二叉树 二叉树的存储结构 二叉树的遍历 树和二叉树 树 1.树的定义 2.树的逻辑表示 树 ...
- 数据结构——树与二叉树
树与二叉树 一.树的定义: 1.定义:树(Tree)是n(n>=0)个节点的有限集,n=0时称为"空树".在任意一棵非空树中: ⒈有且仅有一个特定的称为根(root)的节点. ...
- Python数据结构与算法笔记(八):数据结构——树,二叉树和AVL树
树 class Node:def __init__(self, name, type='dir'):self.name = nameself.type = type #"dir" ...
最新文章
- ajax实现关联词提示
- widedeep 在贝壳推荐场景的实践
- 【渝粤题库】国家开放大学2021春2320物流管理定量分析方法题目
- PHP+jquery 树状菜单
- 服务器显示配置命令,linux查看服务器配置命令
- Quanergy联手思科为智能交通创建物联网解决方案
- python使用默认参数
- activiti工作流 php,码云社 | 砺锋科技-SpringBoot整合Activiti工作流(附源码) - 用代码改变世界...
- python机器学习-乳腺癌细胞挖掘
- 限时,字节Java程序性能优化宝典大全,这才叫真正的性能优化
- 7.Excel数据分析-员工考勤表
- 即将首发 | 业界首个零售数字化创新白皮书,解锁全链路数字化致胜秘籍
- IARPA启动“奥丁”项目,发展生物特征识别技术
- 专家警告全球芯片短缺可能持续到 2022 年之后
- 浅谈到底什么是系统集成(弱电)和项目管理?
- 有时候内卷也可以走捷径,比如几行代码也可以霸榜朋友圈~
- 上半年要写的博客文章27
- 八位计算机最小二进制,八位二进制补码最小值
- 解题记录 LeetCode 下一个更大元素 II 单调栈
- 纳什均衡(Nash equilibrium)