二叉树的相关操作(c语言)
二叉树的相关操作:包括先序序列+中序序列建树丶后序序列+中序序列建树丶层次序列+中序序列建树;先序遍历丶中序遍历丶后序遍历丶层次遍历;二叉树的深度及最大宽度;度分别为0,1,2的节点个数以及总结点个数
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
//二叉树节点结构体
struct BinaryTreeNode{
char m_key;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
// 定义栈的存储表示
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
struct SqStack{
char* base;
char* top;
int stacksize;
};
// 定义队列的存储表示
struct QNode {
BinaryTreeNode data; //元素为一棵树
struct QNode* next;
};
struct LinkQueue{
QNode* front;
QNode* rear;
};
// 栈的基本操作的函数
void InitStack(SqStack &S) {
S.base = (char*)malloc(STACK_INIT_SIZE * sizeof(char));
if (!S.base) exit(-1);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
}
bool StackEmpty(SqStack S) {
if (S.top == S.base) return true;
else return false;
}
void Push(SqStack &S, char e) {
if (S.top - S.base >= S.stacksize) {
S.base = (char*)realloc(S.base,
(S.stacksize + STACKINCREMENT) * sizeof(char));
if (!S.base) exit(-1);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
}
void Pop(SqStack &S, char &e) {
if (S.top == S.base) exit(-1);
e = *--S.top;
}
// 队列的基本操作的函数
void InitQueue(LinkQueue &Q) {
Q.front = Q.rear = (QNode*)malloc(sizeof(QNode));
if (!Q.front) exit(-1);
Q.front->next = NULL;
}
bool QueueEmpty(LinkQueue Q) {
if (Q.front == Q.rear) return true;
else return false;
}
void EnQueue(LinkQueue &Q, BinaryTreeNode e) {
QNode* p;
p = (QNode*)malloc(sizeof(QNode));
if (!p) exit(-1);
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
}
void DeQueue(LinkQueue &Q, BinaryTreeNode &e) {
if (Q.front == Q.rear) exit(-1);
QNode* p;
p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (Q.rear == p) Q.rear = Q.front;
free(p);
}
/****************************************
func:根据前序序列和中序序列构建二叉树
para:preOrder:前序序列;midOrder:中序序列;len:节点数
****************************************/
BinaryTreeNode* construct1(char* preOrder,char* midOrder,int len){
if(preOrder==NULL||midOrder==NULL||len<=0)
return NULL;
//先根遍历(前序遍历)的第一个值就是根节点的键值
char rootKey=preOrder[0];
BinaryTreeNode* root=new BinaryTreeNode;
root->m_key=rootKey;
root->m_pLeft=root->m_pRight=NULL;
if(len==1 && *preOrder==*midOrder)//只有一个节点
return root;
//在中根遍历(中序遍历)中找到根节点的值
char* rootMidOrder=midOrder;
int leftLen=0; //左子树节点数
while(*rootMidOrder!=rootKey&&rootMidOrder<=(midOrder+len-1)){
++rootMidOrder;
++leftLen;
}
if(*rootMidOrder!=rootKey)//在中根序列未找到根节点,输入错误
return NULL;
if(leftLen>0){ //构建左子树
root->m_pLeft=construct1(preOrder+1,midOrder,leftLen);
}
if(len-leftLen-1>0){ //构建右子树
root->m_pRight=construct1(preOrder+leftLen+1,rootMidOrder+1,len-leftLen-1);
}
return root;
}
/****************************************
func:根据后序序列和中序序列构建二叉树
para:postOrder:后序序列;midOrder:中序序列;len:节点数
****************************************/
BinaryTreeNode* construct2(char* postOrder,char* midOrder,int len)
{
if(postOrder==NULL || midOrder==NULL || len<=0)
return NULL;
//后根遍历(后序遍历)的最后一个值就是根节点的键值
char rootKey=*(postOrder+len-1); //获取根节点的值
BinaryTreeNode* root=new BinaryTreeNode;
root->m_key=rootKey;
root->m_pLeft=root->m_pRight=NULL;
if(len==1 && *postOrder==*midOrder)//只有一个节点
return root;
//在中根遍历(中序遍历)中找到根节点的值
char* rootMidOrder=midOrder;
int leftLen=0; //左子树节点数
while(*rootMidOrder!=rootKey&&rootMidOrder<=(midOrder+len-1)){
++rootMidOrder;
++leftLen;
}
if(*rootMidOrder!=rootKey)//在中根序列未找到根节点,输入错误
return NULL;
if(leftLen>0){ //构建左子树
root->m_pLeft=construct2(postOrder,midOrder,leftLen);
}
if(len-leftLen-1>0){ //构建右子树
root->m_pRight=construct2(postOrder+leftLen,rootMidOrder+1,len-leftLen-1);
}
return root;
}
/****************************************
func:根据后序序列和层次序列构建二叉树
para:level:层次序列;midOrder:中序序列;root:二叉树指针引用
****************************************/
void construct3(char* level,char* midOrder,BinaryTreeNode* &root)
{
int i;
int len=strlen(level); //取得层次遍历长度
int pos=0;
if(len==0 || level==NULL || midOrder==NULL)
{
return;
}
char *p=strchr(midOrder,level[0]);
if(p==NULL) //如果为空则抛弃第一个,跳到下一个;
{
char *L=(char*)malloc(sizeof(char)*len); //开辟数组
strncpy(L,level+1,len-1); //舍弃第一个
L[len-1]=0;
construct3(L,midOrder,root); //调用建树函数
return ;
}
pos=p-midOrder; //得到中序遍历左子树字符串长度
root->m_key=level[0]; //为根节点赋值
root->m_pLeft=NULL;
root->m_pRight=NULL;
if(pos!=0) //左子树的递归调用
{
root->m_pLeft=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
char *left_level=(char*)malloc(sizeof(char)*len);
char *left_inor=(char*)malloc(sizeof(char)*(pos));
strncpy(left_level,level+1,len-1); //舍去层次遍历第一个
strncpy(left_inor,midOrder,pos); //截取左子树字符串
left_level[len-1]=0;
left_inor[pos]=0;
construct3(left_level,left_inor,root->m_pLeft);
}
if(pos < strlen(midOrder)-1) //右子树的递归调用
{
root->m_pRight=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
char *right_level=(char*)malloc(sizeof(char)*(len));
char *right_inor=(char*)malloc(sizeof(char)*(len-pos));
strncpy(right_level,level+1,len-1);
strncpy(right_inor,midOrder+pos+1,len-pos-1);
right_level[len-1]=0;
right_inor[len-pos-1]=0;
construct3(right_level,right_inor,root->m_pRight);
}
}
//先根递归遍历
void preOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
printf("%c ",root->m_key);
preOrderRecursion(root->m_pLeft);
preOrderRecursion(root->m_pRight);
}
//中根递归遍历
void midOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
midOrderRecursion(root->m_pLeft);
printf("%c ",root->m_key);
midOrderRecursion(root->m_pRight);
}
//后根递归遍历
void postOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
postOrderRecursion(root->m_pLeft);
postOrderRecursion(root->m_pRight);
printf("%c ",root->m_key);
}
//层次遍历二叉树,使用队列实现
void breadthFirstOrder(BinaryTreeNode* root){
LinkQueue Q;
InitQueue(Q);
BinaryTreeNode p;
if (root)
EnQueue(Q,*root);
else
exit(-1);
while (!QueueEmpty(Q)) {
DeQueue(Q, p);
printf("%c ",p.m_key);
if (p.m_pLeft)
EnQueue(Q,*p.m_pLeft);
if (p.m_pRight)
EnQueue(Q,*p.m_pRight);
}
}
//返回二叉树的深度
int BiTreeDepth( BinaryTreeNode* T)
{
int i,j;
if(!T)
return 0;
if(T->m_pLeft)
i=BiTreeDepth(T->m_pLeft);
else
i=0;
if(T->m_pRight)
j=BiTreeDepth(T->m_pRight);
else
j=0;
return i>j?i+1:j+1;
}
//求二叉树的最大宽度
int LevelWidth(BinaryTreeNode* root,int level)
{
if(!root)return 0;
else
{
if(level==1)
return 1;
level=LevelWidth(root->m_pLeft,level-1)+LevelWidth(root->m_pRight,level-1);
}
return level;
}
int Width(BinaryTreeNode* root)
{
int width,i;
int w[20];
for(i=0;i<20;i++)
w[i]=0;
if(!root)
width=0;
else
{
for(i=0;i<=BiTreeDepth(root);i++)
w[i]=LevelWidth(root,i+1);
}
i=0;
while(w[i])
{
if(w[i]>width)
width=w[i];
i++;
}
return width;
}
//求度为0的节点个数
int NodeNumber_0(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if(T->m_pLeft==NULL && T->m_pRight==NULL)
{
i=1;
}
else
{
i=NodeNumber_0(T->m_pLeft) + NodeNumber_0( T->m_pRight );
}
}
return i;
}
//求度为1的节点个数
int NodeNumber_1(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if( (T->m_pLeft==NULL && T->m_pRight!=NULL) || (T->m_pLeft!=NULL && T->m_pRight==NULL))
{
i=1+NodeNumber_1(T->m_pLeft)+NodeNumber_1(T->m_pRight);
}
else
{
i=NodeNumber_1(T->m_pLeft)+NodeNumber_1(T->m_pRight);
}
}
return i;
}
//求度为2的节点个数
int NodeNumber_2(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if((T->m_pLeft!=NULL)&&(T->m_pRight!=NULL))
{
i=1+NodeNumber_2(T->m_pLeft) + NodeNumber_2(T->m_pRight);
}
else
{
i= NodeNumber_2(T->m_pLeft) + NodeNumber_2(T->m_pRight);
}
}
return i;
}
int main(){
int depth;
int width;
int num0;
int num1;
int num2;
int sum;
//二叉树1先根序列
char preOrder1[9]={'1','2','4','7','3','5','6','8'};
//二叉树1中根序列
char midOrder1[9]={'4','7','2','1','5','3','8','6'};
//二叉树1后根序列
char postOrder1[9]={'7','4','2','5','8','6','3','1'};
//二叉树1层次序列
char cengOrder1[9]={'1','2','3','4','5','6','7','8'};
//二叉树2先根序列
char preOrder2[8]={'A','B','C','D','E','G','F'};
//二叉树2中根序列
char midOrder2[8]={'C','B','E','G','D','F','A'};
//二叉树2后根序列
char postOrder2[8]={'C','G','E','F','D','B','A'};
//二叉树2层次序列
char cengOrder2[8]={'A','B','C','D','E','F','G'};
//二叉树3先根序列
char preOrder3[9]={'H','D','A','C','B','G','F','E'};
//二叉树3中根序列
char midOrder3[9]={'A','D','C','B','H','F','E','G'};
//二叉树3后根序列
char postOrder3[9]={'A','B','C','D','E','F','G','H'};
//二叉树3层次序列
char cengOrder3[9]={'H','D','G','A','C','F','B','E'};
//先根序列+中根序列建树1
printf("先根序列+中根序列建树1\n");
BinaryTreeNode* root1=construct1(preOrder1,midOrder1,8);
//先序遍历树1
printf("该二叉树的先序遍历为:");
preOrderRecursion(root1);
printf("\n");
//中序遍历树1
printf("该二叉树的中序遍历为:");
midOrderRecursion(root1);
printf("\n");
//后序遍历树1
printf("该二叉树的后序遍历为:");
postOrderRecursion(root1);
printf("\n");
//层次遍历树1
printf("该二叉树的层次遍历为:");
breadthFirstOrder(root1);
printf("\n");
//二叉树1的深度
depth=BiTreeDepth(root1);
printf("该二叉树的深度为%d\n",depth);
//二叉树1的最大宽度
width=Width(root1);
printf("该二叉树的最大宽度为%d\n",width);
//二叉树1度为0的节点个数
num0=NodeNumber_0(root1);
printf("该二叉树度为0的节点个数为%d\n",num0);
//二叉树1度为1的节点个数
num1=NodeNumber_1(root1);
printf("该二叉树度为1的节点个数为%d\n",num1);
//二叉树1度为2的节点个数
num2=NodeNumber_2(root1);
printf("该二叉树度为2的节点个数为%d\n",num2);
//二叉树1总结点个数
sum=num0+num1+num2;
printf("该二叉树度的总节点个数为%d\n",sum);
printf("\n");
// 后根序列+中根序列建树2
printf("后根序列+中根序列建树2\n");
BinaryTreeNode* root2=construct2(postOrder2,midOrder2,7);
//先序遍历树2
printf("该二叉树的先序遍历为:");
preOrderRecursion(root2);
printf("\n");
//中序遍历树2
printf("该二叉树的中序遍历为:");
midOrderRecursion(root2);
printf("\n");
//后序遍历树2
printf("该二叉树的后序遍历为:");
postOrderRecursion(root2);
printf("\n");
//层次遍历树2
printf("该二叉树的层次遍历为:");
breadthFirstOrder(root2);
printf("\n");
//二叉树2的深度
depth=BiTreeDepth(root2);
printf("该二叉树的深度为%d\n",depth);
//二叉树2的最大宽度
width=Width(root2);
printf("该二叉树的最大宽度为%d\n",width);
//二叉树2度为0的节点个数
num0=NodeNumber_0(root2);
printf("该二叉树度为0的节点个数为%d\n",num0);
//二叉树2度为1的节点个数
num1=NodeNumber_1(root2);
printf("该二叉树度为1的节点个数为%d\n",num1);
//二叉树2度为2的节点个数
num2=NodeNumber_2(root2);
printf("该二叉树度为2的节点个数为%d\n",num2);
//二叉树2总结点个数
sum=num0+num1+num2;
printf("该二叉树度的总节点个数为%d\n",sum);
printf("\n");
//层次序列+中根序列建树3
printf("层次序列+中根序列建树3\n");
BinaryTreeNode* root3;
root3=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
construct3(cengOrder3,midOrder3,root3);
//先序遍历树3
printf("该二叉树的先序遍历为:");
preOrderRecursion(root3);
printf("\n");
//中序遍历树3
printf("该二叉树的中序遍历为:");
midOrderRecursion(root3);
printf("\n");
//后序遍历树3
printf("该二叉树的后序遍历为:");
postOrderRecursion(root3);
printf("\n");
//层次遍历树3
printf("该二叉树的层次遍历为:");
breadthFirstOrder(root3);
printf("\n");
//二叉树3的深度
depth=BiTreeDepth(root3);
printf("该二叉树的深度为%d\n",depth);
//二叉树3的最大宽度
width=Width(root3);
printf("该二叉树的最大宽度为%d\n",width);
//二叉树3度为0的节点个数
num0=NodeNumber_0(root3);
printf("该二叉树度为0的节点个数为%d\n",num0);
//二叉树3度为1的节点个数
num1=NodeNumber_1(root3);
printf("该二叉树度为1的节点个数为%d\n",num1);
//二叉树3度为2的节点个数
num2=NodeNumber_2(root3);
printf("该二叉树度为2的节点个数为%d\n",num2);
//二叉树3总结点个数
sum=num0+num1+num2;
printf("该二叉树度的总节点个数为%d\n",sum);
return 0;
}
运行结果
转载于:https://www.cnblogs.com/Dearmyh/p/9976228.html
二叉树的相关操作(c语言)相关推荐
- C语言 二叉树的相关操作
C语言 二叉树的相关操作 // 头文件 #ifndef __BITREE_H__ #define __BITREE_H__ #define _CRT_SECURE_NO_WARNINGS #inclu ...
- 【数据结构】二叉树及其相关操作
二叉树的定义 二叉树是一个由结点构成的有限集合,这个集合或者为空,或者由一个根节点及两棵互不相交的分别称作这个根节点的左子树和右子树的二叉树组成. 二叉树并非一般的树形结构的特殊形式,它们是两种不同的 ...
- 二叉树的相关操作(二)
上次的文章里我们实现了二叉树的基本操作,接下类我们来研究一些其他有意思的操作,包括: 1,通过遍历序列来构建二叉树 2,实现二叉树的层次遍历法 3,判断二叉树是否为完全二叉树 4,实现求二叉树上某节点 ...
- 数据结构源码笔记(C语言):二叉平衡树的相关操作算法
//二叉平衡树的相关运算 #include<stdio.h> #include<malloc.h> #include<string.h>typedef char I ...
- 顺序队列相关操作(C语言实现)
#顺序队列相关操作(C语言实现) #include<stdio.h> #define Size 100 typedef int DataType; typedef struct {Data ...
- 面试基础算法及编程 第三弹(树(二叉树)相关:主要考察指针相关的操作)
// # -*- coding:utf-8 -*- // # @Author: Mr.chen(ai-chen2050@qq.com) // # @Date: 2018-08-17 16:32:55 ...
- 刁肥宅手笔:纯C语言实现链式队列的相关操作
先上图,以图服人: 图一 程序运行截图1 图二 程序运行截图2 上代码: 头文件LinkQueue.h: /*LinkQueue.h*/#ifndef LINKQUEUE_H_INCLUDED #de ...
- 刁肥宅手笔:纯C语言实现栈的相关操作
有一种爱不解释--我爱C语言! /*Name:纯C语言实现栈的相关操作Copyright:欢迎共享此代码Author:刁肥宅Date: 04/08/18 21:55Description:调试过程出行 ...
- 【R语言中如何去除替换NA相关操作】
R语言中如何去除替换NA相关操作 1.去除矩阵所有含NA的行 2.去除矩阵特定列中含NA的行 3.替换矩阵中的NA值为0 4.将矩阵中某一列的特殊值替换为NA 1.去除矩阵所有含NA的行 data=n ...
最新文章
- puppet(1.7-2.1)
- 首尾相连的一位数组最大子数组和
- noip2011提高组day1+day2解题报告
- Hadoop自带的一些程序示例
- Windows 中进程的相关操作
- WWN与SAS地址详解(10款SAS硬盘横评之三)
- Spring思维导图(IOC篇)
- 【ArcGIS风暴】全站仪、RTK测量坐标数据在CASS和ArcGIS中展点的区别和联系(带数据)
- Python 标准库 —— json
- CCF推荐的A类、B类、C类中文科技期刊
- windows进程 windows多进程编程
- 介绍会议中控系统模块化构成及功能作用
- 麒麟V10图形界面安装与运行人大金仓数据库
- 处理new Date()在safari浏览器上的某些日期格式导致的Invalid Date
- vulnhub靶场,Monitoring
- Mac下adb调试华为C8815问题
- 华为光猫HG8240的简单配置过程
- java 获取kafka lag,聊聊kafka consumer offset lag的监控
- 浙江大学求是科学班计算机,2018年浙江大学求是科学班(生物科学)招生简章...
- Axure中动态面板中的“推动/拉动原件”
热门文章
- CSDN上传资源时一直提示 请填写资源tag
- Cocos Creator JS 获取当前日期与时间
- php判断是否为手机设备
- SpringMVC当中的 @Transactional(readOnly = true) 的作用
- yii2: 点击编辑后,左侧的连接(a.navtab)失效,变成在新窗口打开
- jquery源码解析:proxy,access,swap,isArraylike详解
- 创建 Oracle 物理备用服务器
- log4j的相关jar包总结
- useMemo与useCallback
- 为什么我从Mac切换到Linux