数据结构实验题,二叉树的先序,后序,中序,层次遍历,插入结点,求叶子结点个数,求非叶子结点个数,求总结点数,求树的深度,已知先序和中序重构二叉树。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int ctrl_i=0;
typedef struct BTNode{char data;    //结点的信息用一个字符保存BTNode*lchild,  *rchild; //左右孩子的指针
}BTNode;#define MAX_SIZE 128
#define STR_SIZE 1024typedef struct Node {    // 定义二叉链char         data;   // 数据元素struct Node* lchild; // 指向左孩子节点struct Node* rchild; // 指向右孩子节点
} LinkNode;                // struct Node 的别名typedef struct Quene {      // 定义顺序队int     front;          // 队头指针int     rear;           // 队尾指针BTNode* data[MAX_SIZE]; // 存放队中元素
} SqQueue;                  // struct Queue 的别名//生成唯一的根节点。根节点的信息用一个字符参数输入。
BTNode *CreateRoot(char c)
{//申请根结点空间BTNode * tmp = (BTNode *)malloc(sizeof(BTNode));//判断申请空间是否成功,若成功,则输入结点信息,并初始化指针if (!tmp) printf("申请空间失败,无法创建根结点\n");else{//申请空间成功,为根节点赋初值tmp->data = c;tmp->lchild = NULL;tmp->rchild = NULL;}//返回根节点return  tmp ;
}//在指定结点下插入一个左孩子,原先的左子树作为新插入左孩子结点的左子树,并返回新插入左孩子结点的指针。
BTNode *InsertLeftNode(BTNode *curNode,  char c)
{//申请左孩子结点的空间BTNode * tmp = (BTNode *)malloc(sizeof(BTNode) );//判断申请空间是否成功,若成功,则输入结点信息,并初始化指针if (tmp==NULL) printf("申请空间失败,无法创建根结点\n");else{//curNode原先的左子树挂到新结点下面tmp->lchild = curNode->lchild;//新结点右子树置空tmp->rchild = NULL;//输入新结点信息tmp->data = c;//新结点作为左孩子挂在curNode下面curNode->lchild=tmp;}return  tmp  ;
}//删除左子结点
//若指定结点的左子结点仅有一颗子树,则删除该左子结点,同时将其子树作为指定结点的左子树。
void DelLeftNode(BTNode *curNode)
{//如果curNode的左子结点有两颗子树,则不删除,直接返回。if ( curNode->lchild->lchild  && curNode->lchild->rchild  )   return;//暂存左子结点指针BTNode * tmp =  curNode->lchild  ;//保存该左子结点的非空子树BTNode *lc = tmp->lchild?tmp->lchild: tmp->rchild ;//该非空子树挂到curNode的左路curNode->lchild = lc;//删除左子结点free(tmp);
}//在指定结点下插入一个右孩子,原先的右子树作为新插入右孩子结点的右子树,并返回新插入右孩子结点的指针。
BTNode *InsertRightNode(BTNode *curNode,  char c)
{//申请右孩子结点的空间BTNode * tmp = (BTNode *)malloc(sizeof(BTNode) );//判断申请空间是否成功,若成功,则输入结点信息,并初始化指针if (tmp==NULL) printf("申请空间失败,无法创建根结点\n");else{//curNode原先的左子树挂到新结点下面tmp->rchild = curNode->rchild;//新结点右子树置空tmp->lchild = NULL;//输入新结点信息tmp->data = c;//新结点作为右孩子挂在curNode下面curNode->rchild=tmp;}return tmp;
}//若指定结点的右子结点仅有一颗子树,则删除该右子结点,同时将其子树作为指定结点的右子树。
void DelRightNode(BTNode *curNode)
{//如果curNode的右子结点有两颗子树,则不删除,直接返回。if ( curNode->rchild->lchild  && curNode->rchild->rchild  )   return;//暂存右子结点指针BTNode * tmp =  curNode->rchild  ;//保存该右子结点的非空子树BTNode *lc = tmp->rchild?tmp->rchild: tmp->lchild ;//该非空子树挂到curNode的右路curNode->rchild = lc;//删除左子结点free(tmp);
}
//按先序遍历的输出次序输入一个字符串,其中每个字符代表二叉树中一个结点的值,用’#’字符表示空结点。试根据此先序遍历的字符次序一次性构造出链式二叉树。
BTNode * CreateTree(char *str)
{int i = ctrl_i;char ch;BTNode *T;ch = str[i++];ctrl_i = i;if(ch=='#')T = NULL;else{T=(BTNode*)malloc(sizeof(BTNode));T->data = ch;T->lchild = CreateTree(str);T->rchild = CreateTree(str);}return T;
}//按照先序遍历的方式访问每一个结点,输出结点信息中的字符。
//访问某结点的函数,这里只需要输出结点信息中的字符。
void Visit(BTNode * node)
{if(node)printf("%6c",node->data);
}
void PreOrderTraverse(BTNode * root)
{//若root非空,则先访问root,再按照先序遍历方式访问其左子树和右子树if (root)  //判断非空{Visit(root);   //访问该结点PreOrderTraverse(root->lchild);   //先序遍历的方式访问该结点的左子树PreOrderTraverse(root->rchild);   //先序遍历的方式访问该结点的右子树}
}//非叶子结点数
//写一个函数统计二叉树中的非叶子结点数目。
int TotalNoLeafNodes(BTNode * root)
{//若root为空树,非叶子结点数为0if (root == NULL) return 0;//若root没有任何子树,则非叶子结点数也为0else if (root->lchild==NULL && root->rchild==NULL) return 0;//否则,root结点本身就是非叶子结点,还加上其子树的非叶子结点数else return 1 + TotalNoLeafNodes(root->lchild) + TotalNoLeafNodes(root->rchild);
}//二叉树深度
//写一个函数求二叉树中的深度。
int TreeDeep(BTNode * root)
{//如果root为空树,则深度为0if (root == NULL) return 0;//否则,需要先计算出其左右子树的深度,在深度大的值上再加上root本身这一层,即为root指向二叉树的深度else{//计算左子树深度int ld = TreeDeep(root->lchild);//计算右子树深度int rd = TreeDeep(root->rchild);//返回 root层对深度的贡献值 + 左右子树深度值中的大值return 1 + (ld > rd ? ld : rd);}
}//中序遍历
//按照中序遍历的方式访问每一个结点,输出结点信息中的字符。
void InOrderTraverse(BTNode * root)
{if (root)  //判断非空{InOrderTraverse(root->lchild);   //先序遍历的方式访问该结点的左子树Visit(root);   //访问该结点InOrderTraverse(root->rchild);   //先序遍历的方式访问该结点的右子树}
}
//后序遍历
//按照后序遍历的方式访问每一个结点,输出结点信息中的字符。
void PostOrderTraverse(BTNode * root)
{if (root)  //判断非空{PostOrderTraverse(root->lchild);   //先序遍历的方式访问该结点的左子树PostOrderTraverse(root->rchild);   //先序遍历的方式访问该结点的右子树Visit(root);   //访问该结点}
}
void initQueue(SqQueue** q) {if (!((*q) = (SqQueue*)malloc(sizeof(SqQueue)))) {printf("内存分配失败!");exit(-1);}(*q)->front = (*q)->rear = -1; // 置 -1
}// 判断队列是否为空
bool emptyQueue(SqQueue* q) {// 首指针和尾指针相等,说明为空。空-返回真,不空-返回假if (q->front == q->rear) {return true;}return false;
}// 进队列
bool enQueue(SqQueue* q, BTNode* node) {// 判断队列是否满了。满(插入失败)-返回假,不满(插入成功)-返回真if (q->rear == MAX_SIZE - 1) {return false;}q->rear++;               // 头指针加 1q->data[q->rear] = node; // 传值return true;
}// 出队列
bool deQueue(SqQueue* q, BTNode** node) {// 判断是否空了。空(取出失败)-返回假,不空(取出成功)-返回真if (q->front == q->rear) {return false;}q->front++;                // 尾指针加 1*node = q->data[q->front]; // 取值return true;
}//层次遍历
//从根结点层开始,逐层从左至右访问二叉树的每一个结点。
//在该函数之前,需要实现一个队列,队列中的元素为BTNo的*类型void levelOrder(BTNode* BT) {SqQueue* q;       // 定义队列initQueue(&q);    // 初始化队列if (BT != NULL) { // 根节点指针进队列enQueue(q, BT);}// 一层一层的把节点存入队列,当没有孩子节点时就不再循环while (!emptyQueue(q)) {      // 队不为空循环deQueue(q, &BT);          // 出队时的节点printf("%6c", BT->data);   // 输出节点存储的值if (BT->lchild != NULL) { // 有左孩子时将该节点进队列enQueue(q, BT->lchild);}if (BT->rchild != NULL) { // 有右孩子时将该节点进队列enQueue(q, BT->rchild);}}
}//结点总数
//计算二叉树中的结点总数。
int TotalNodes(BTNode * root)
{//若root为空树,结点数为0if (root == NULL) return 0;else return  1 + TotalNodes(root->lchild) + TotalNodes(root->rchild);
}
//叶子结点数
//计算二叉树中的叶子结点总数。
int TotalLeafNodes(BTNode * root)
{//若root为空树,叶子结点数为0if (root == NULL) return 0;else if(root->lchild==NULL&&root->rchild==NULL) return 1;return (TotalLeafNodes(root->lchild) + TotalLeafNodes(root->rchild));
}
//二叉树重构
//已知某二叉树的先序和中序遍历结果,试重构此二叉树。
//ppos为先序遍历的字符串,ipos为中序遍历的字符串,n为结点总数
//返回重构的二叉树根结点
BTNode* RestoreTree(char *ppos, char *ipos, int n)
{int i = 0;  int n1 = 0,n2 = 0;  int m1 = 0,m2 = 0;  BTNode*node = NULL;  char lpre[n],rpre[n];  char lin[n],rin[n];  if (n == 0)  {  return NULL;  }  node = (BTNode*)malloc(sizeof(BTNode));    if (node==NULL)    {    return NULL;    }    memset(node,0,sizeof(BTNode));   //先序序列的第一个元素必为根结点  node->data = ppos[0];  //根据根结点将中序序列分为左子树和右子数  for (i = 0;i<n;i++)  {  if ((i<=n1)&&(ipos[i]!=ppos[0]))  {  lin[n1++] = ipos[i];  }  else if(ipos[i]!=ppos[0])  {  rin[n2++] = ipos[i];  }  }  //根据树的先序序列的长度等于中序序列的长度  //且先序遍历是先左子树再后子树,无论先序还是中序 左子树和右子树的长度都是固定的  //主意 从i=1开始 因为先序遍历的第一个是根   for (i = 1;i < n;i++)  {  if (i< (n1+1))//n1代表了左子树的长度  {  lpre[m1++] = ppos[i];  }  else  {  rpre[m2++] = ppos[i];  }  }  node->lchild = RestoreTree(lpre,lin,n1);  node->rchild = RestoreTree(rpre,rin,n2);  return node;
}/*A                       A/ \                     / \B   C                   B   C/                   /   / \D                   D   E   F\G二叉树1                 二叉树2*/
int main()
{//方式1:逐个生成每个结点。//生成二叉树1//定义一个root指针,用来保存根结点, BTNode *root;//定义一个curNode指针,用来指向root之外的当前结点BTNode *curNode;//生成根结点A,用root指针指向该根结点root = CreateRoot('A');//在A下插入左子结点BInsertLeftNode(root,'B');//在A下插入右子结点C,用curNode指向CcurNode = InsertRightNode(root,'C');//在C下插入左子结点DInsertLeftNode(curNode,'D');PreOrderTraverse(root);printf("\n");//试生成二叉树2{BTNode *root2;BTNode *curNode2;root2 = CreateRoot('A');curNode2 = InsertLeftNode(root2,'B');InsertLeftNode(curNode2,'D');curNode2 = InsertRightNode(root2,'C');InsertRightNode(curNode2,'F');curNode2 = InsertLeftNode(curNode2,'E');InsertRightNode(curNode2,'G');PreOrderTraverse(root2);printf("\n");//your codes}//方式2: 用先序次序生成二叉树//二叉树1的先序次序为  AB##CD###ctrl_i = 0;BTNode * root3  =  CreateTree("AB##CD###");PreOrderTraverse(root3);printf("\n");//写出二叉树2的先序次序,并生成该树。ctrl_i = 0;    BTNode * root4  =  CreateTree("ABD###CE#G##F##");PreOrderTraverse(root4);printf("\n");//生成二叉树1和二叉树2//输出二叉树2的结点总数,叶子结点数,非叶子节点数和深度。printf("\n 先序AB##CD### 二叉树 结点总数:%d\n",TotalNodes(root3));printf("\n 先序AB##CD### 二叉树 叶结点总数:%d\n",TotalLeafNodes(root3));printf("\n 先序AB##CD### 二叉树 非叶结点总数:%d\n",TotalNoLeafNodes(root3));printf("\n 先序AB##CD### 二叉树 深度:%d\n",TreeDeep(root3));//输出二叉树1的结点总数,叶子结点数,非叶子节点数和深度。printf("\n 先序ABD###CE#G##F## 二叉树 结点总数:%d\n",TotalNodes(root4));printf("\n 先序ABD###CE#G##F## 二叉树 叶结点总数:%d\n",TotalLeafNodes(root4));printf("\n 先序ABD###CE#G##F## 二叉树 非结点总数:%d\n",TotalNoLeafNodes(root4));printf("\n 先序ABD###CE#G##F## 二叉树 深度:%d\n",TreeDeep(root4));//按照先序、中序、后序、层次四种方式输出二叉树1和2printf("\n 先序AB##CD### 二叉树 :\n");PreOrderTraverse(root3); printf("\n 中序AB##CD### 二叉树 :\n");InOrderTraverse(root3);printf("\n 后序AB##CD### 二叉树 :\n");PostOrderTraverse(root3);printf("\n 层次AB##CD### 二叉树 :\n");levelOrder(root3);//二叉树2printf("\n 先序ABD###CE#G##F## 二叉树 :\n");PreOrderTraverse(root4); printf("\n 中序ABD###CE#G##F## 二叉树 :\n");InOrderTraverse(root4);printf("\n 后序ABD###CE#G##F## 二叉树 :\n");PostOrderTraverse(root4);printf("\n 层次ABD###CE#G##F## 二叉树 :\n");levelOrder(root4);//将二叉树2的先序和中序遍历字符串保存到两个数组BTNode * root5;BTNode * root6;char apre[] = "ABCD";char ain[] = "BADC";char bpre[] = "ABDCEGF";char bin[] = "DBAEGCF";//根据这两个数组,重建二叉树2root5 = RestoreTree(apre,ain,4);root6 = RestoreTree(bpre,bin,7);printf("\n 重构后二叉树1:\n");PreOrderTraverse(root5);printf("\n 重构后二叉树2:\n");PreOrderTraverse(root6);printf("\n");return 0;
}

运行结果:

​​​​​​​

二叉树遍历,求叶结点,重构相关推荐

  1. 二叉树 Java 实现 前序遍历 中序遍历 后序遍历 层级遍历 获取叶节点 宽度 ,高度,队列实现二叉树遍历 求二叉树的最大距离...

    数据结构中一直对二叉树不是很了解,今天趁着这个时间整理一下 许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显 ...

  2. 数据结构二叉树遍历求后序

    注意左右子树的递归 参考自https://blog.csdn.net/hou_blog/article/details/50015503

  3. 本题要求按照先序遍历的顺序输出给定二叉树的叶结点。

    函数接口定义: void PreorderPrintLeaves( BinTree BT ); 其中BinTree结构定义如下: typedef struct TNode *Position; typ ...

  4. 6-8 先序输出叶结点 (15 分)

    ** 6-8 先序输出叶结点 (15 分) ** 本题要求按照先序遍历的顺序输出给定二叉树的叶结点. 函数接口定义: void PreorderPrintLeaves( BinTree BT ); 其 ...

  5. PTA4-11 先序输出叶结点

    4-11 先序输出叶结点   (15分) 本题要求按照先序遍历的顺序输出给定二叉树的叶结点. 函数接口定义: void PreorderPrintLeaves( BinTree BT ); 其中Bin ...

  6. 58同城2021校招笔试——二叉树遍历

    目录 题目: 解答: 博主笨拙的想法--些许暴力 思路: 非常妙的方法: 题目: 对给定的二叉树依次完成前序,中序,后序遍历,并输出遍历结果. 每行输入为一个二叉树,一维数组形式.其中-1表示Nil节 ...

  7. 二叉树的进阶操作---(求二叉树中所有结点个数,求叶子结点个数,求第k层结点个数;在二叉树中查找某一结点;层序遍历;判断是否为完全二叉树)

    typedef struct TreeNode {struct TreeNode *left;struct TreeNode *right;char val; }TreeNode;typedef st ...

  8. JAVA 二叉树 常见操作合集(前中后序递归非递归遍历 层序遍历 求深度宽度 判断兄弟结点 堂兄弟节点)

    今天复习了二叉树的相关操作,整理归纳如下. 二叉树结点定义 //节点类private static class TreeNode{private int val = 0;private TreeNod ...

  9. (数据结构)1.实现二叉树的各种基本运算的算法2.实现二叉树的各种遍历算法3. 由遍历序列构造二叉树4.求二叉树中的结点个数、叶子节点个数、某结点层次和二叉树宽度

    实验内容 1.假设二叉树中的每个结点值为单个字符,采用二叉链存储结构存储.设计一个算法,计算一棵给定二叉树b中的所有单分支结点个数. 2.假设二叉树中的每个结点值为单个字符,采用二叉链存储结构存储.设 ...

  10. c语言利用遍历求树高的程序,用C语言实现二叉树的遍历极其应用

    用C语言实现二叉树的遍历极其应用 [1][摘要]:<数据结构>是计算机系学生的一门专业技术基础课程,计算机科学各领域及有关的应用软件都要用到各种数据结构.C语言有较丰富的数据类型.运算符以 ...

最新文章

  1. 快速理解VirtualBox的四种网络连接方式
  2. 实在不好意思,最近写个项目,一直没时间来灌水
  3. 倒排列表求交集算法汇总
  4. Python自动化3.0-------学习之路-------函数!
  5. [疑问]您没有调试该服务器的权限。验证您是服务器上Debuger Users组的成员。...
  6. 数据结构与算法 / 散列表(HashTable)
  7. CentOS 修改IP地址, DNS, 网关
  8. 画像分析(3-3)标签建模-模型管理-新建关系
  9. 计算机专业论文docx,计算机系毕业论文范文-20210606000812.docx-原创力文档
  10. jdbc是java语言编写的类和接口_JDBC——Java语言连接数据库的标准
  11. 对于谷歌应用传统的自动语音识别(ASR)系统的解析
  12. ASP.NET 5系列教程
  13. java简单代码_几个简单的入门JAVA代码
  14. 服务器如何安装center os7系统,centeros7安装教程
  15. Windows XP 系统优化全攻略(转)
  16. DWG文件损坏了怎么办?
  17. 任意图像转素描:Python分分钟实现
  18. 【Python中三角函数正弦、余弦、正切的计算】
  19. Luogu5339 [TJOI2019]唱、跳、rap和篮球 【生成函数,NTT】
  20. 冉宝的每日一题-8月16日回溯法+ 动态规划压缩

热门文章

  1. 小程序毕设作品之微信小程序点餐系统毕业设计(1)开发概要
  2. php7 mysql fetch row,PHP中mysql_fetch_row() 和mysql_fetch_array之间有什么区别?
  3. 【ECSHOP插件】ECSHOP会员头像,上传头像评论显示头像
  4. 标签打印软件中标签间距以及边距如何设置
  5. 小说我成了机器人桑尼_我在月球当皇帝
  6. 全网疯传!传智播客java基础入门第二版pdf
  7. java winrar_WinRAR5.60官方无广告正式版
  8. 2021 自编译最新稳定版 裴讯 Phicomm K2 Openwrt 固件
  9. 使用markdown写大论文
  10. MD5加密的两种方式