• 树的遍历及应用(C-数据结构)


    扩展先序序列创建树

    Tree* create(Tree *root){ //扩展先序创建树  
    	char ch;
    	ch=getchar();
    	if(ch=='#'){
    		return NULL;
    	}else{
    		root=(Tree*)malloc(sizeof(Tree));
    		root->data=ch;
    		root->left=create(root->left);
    		root->right=create(root->right);
    	}
    	return root;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    输出树状图

    void printTree(Tree *root,int h) //输出树状图 
    {
    	if(root==NULL){
    		return;
    	}
    	printTree(root->right,h+1);
    	for(int i=0;idata);
    	printTree(root->left,h+1);	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    递归遍历

    先序遍历

    void preOut(Tree *root) //先序遍历 
    {
    	if(!root) return;
    	printf("%c",root->data);
    	preOut(root->left);
    	preOut(root->right);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    中序遍历

    void midOut(Tree *root) //中序遍历 
    {
    	if(!root) return;	
    	midOut(root->left);
    	printf("%c",root->data);
    	midOut(root->right);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    后序遍历

    void rearOut(Tree *root) //后序遍历 
    {
    	if(!root) return;	
    	rearOut(root->left);
    	rearOut(root->right);
    	printf("%c",root->data);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    非递归遍历

    结合源码中创建的栈分析代码。

    先序遍历

    访问当前节点,并将其右节点和左节点依次入栈(先进后出)。重复以上操作,直到栈空并且当前节点为空。

    void preOut1(Tree *root,Stack *stack) //先序遍历 
    {
    	if(!root) return;
    	Tree *temp;
    	pushStack(stack,root);
    	while(stack->top>-1){
    		popStack(stack,&temp);
    		printf("%c",temp->data);
    		if(temp->right){
    			pushStack(stack,temp->right);
    		}
    		if(temp->left){
    			pushStack(stack,temp->left);
    		}
    		
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    中序遍历

    先将当前节点所有左节点入栈,,然后出栈,访问当前节点信息,再访问右节点。重复以上操作,直到栈空并且当前节点为空。

    void midOut1(Tree *root,Stack *stack) //中序遍历 
    {
    	if(!root) return;
    	Tree *temp=root;	
    	while(temp||stack->top > -1){
    		while(temp){
    			pushStack(stack,temp);
    			temp=temp->left;
    		}
    		popStack(stack,&temp);
    		printf("%c",temp->data);
    		temp=temp->right;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    后序遍历

    先将当前节点的所有的左节点入栈,然后取栈顶元素并判断qi右节点的状态,当右节点已经访问或者为空时,输出根节点,将栈顶退一位,记录当前节点,然后将当前节点置为空;否则将当前节点指向其右节点。重复以上操作,直到栈空并且当前节点为空。

    void rearOut1(Tree *root,Stack *stack) //后序遍历 
    {
    	if(!root) return;
    	Tree *temp=root;
    	Tree *visted=NULL;
    	while(temp||stack->top > -1){
    		while(temp){
    			pushStack(stack,temp);
    			temp=temp->left;
    		}
    		temp=stack->data[stack->top];
    		if(temp->right==NULL||temp->right==visted){
    			printf("%c",temp->data);
    			stack->top--;
    			visted=temp;
    			temp=NULL;
    		}else{
    			temp=temp->right;
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    后序遍历(简单版—先序改写)

    在先序遍历中,将左右节点入栈顺序颠倒,并将每次的根节点信息不输出,然后记录到新的数组中,那么最后得到的将是根-右-左模式,将其逆序输出即可得左-右-根模式(后序遍历)结果
    在这里插入图片描述

    void rearOut2(Tree *root,Stack *stack) //后序遍历(简单版—先序改写) 
    {
    	if(!root) return;
    	Tree *temp;
    	char data[MAXSIZE];
    	int cnt=0; 
    	pushStack(stack,root);
    	while(stack->top>-1){
    		popStack(stack,&temp);
    		data[cnt++]=temp->data;
    		if(temp->left){
    			pushStack(stack,temp->left);
    		}
    		if(temp->right){
    			pushStack(stack,temp->right);
    		}		
    	}
    	for(int i=cnt-1;i>=0;i--){
    		printf("%c",data[i]);
    	} 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    统计二叉树中叶子结点的个数

    void getCount(Tree *root)//统计二叉树中叶子结点的个数 
    {
    	if(!root) return;
    	if(root->left==NULL&&root->right==NULL) count++;
    	getCount(root->left);
    	getCount(root->right);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    计算二叉树的高度

    void getHigh(Tree *root,int h)//计算二叉树的高度 
    {
    	if(!root) return;
    	if(deepleft,h+1);
    	getHigh(root->right,h+1);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    计算指定的某一层k的叶子节点个数

    void getCountK(Tree *root,int h,int k)//计算指定的某一层k的叶子节点个数 
    {
    	if(!root) return;
    	if(root->left==NULL&&root->right==NULL&&h==k) countK++;
    	getCountK(root->left,h+1,k);
    	getCountK(root->right,h+1,k);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    源码

    #include
    #include
    #define MAXSIZE 1000
    
    typedef struct tree{
    	char data;
    	struct tree *left;
    	struct tree *right;
    }Tree; //定义树的节点 
     
    typedef struct {
    	Tree* data[MAXSIZE];
    	int top; //栈顶 
    }Stack; 
     
    
    int deep=0; //二叉树的高度 
    int count=0; //二叉树中叶子节点的个数 
    int countK=0;  //第k层的叶子节点个数 
    
    void InitStack(Stack *p); //初始化栈 
    void pushStack(Stack*p,Tree* c); //入栈
    void popStack(Stack*p,Tree**c); //出栈
    Tree* create(Tree *root); //扩展先序序列创建树 
    //递归遍历 
    void preOut(Tree *root); //先序遍历 
    void midOut(Tree *root); //中序遍历
    void rearOut(Tree *root); //后序遍历
    //非递归遍历 
    void preOut1(Tree *root,Stack *stack); //先序遍历 
    void midOut1(Tree *root,Stack *stack); //中序遍历
    void rearOut1(Tree *root,Stack *stack); //后序遍历
    void rearOut2(Tree *root,Stack *stack); //后序遍历(简单版—先序改写)
    void printTree(Tree*root,int h);  //输出树状图
    void getCount(Tree *root);//统计二叉树中叶子结点的个数
    void getHigh(Tree *root,int h);//计算二叉树的高度 
    void getCountK(Tree *root,int h,int k);//计算指定的某一层k的叶子节点个数 
    
    int main()
    {
    	Tree *root=create(root); //扩展先序序列建立树 
    	printf("树状输出:\n");
    	printTree(root,1); // 以树状形式打印输出 
    	printf("\n");
    	printf("递归先序:");
    	preOut(root); //递归先序 
    	printf("\n");
    	printf("递归中序:");
    	midOut(root); //递归中序 
    	printf("\n");
    	printf("递归后序:");
    	rearOut(root); //递归后序 
    	printf("\n");
    	Stack stack;
    	InitStack(&stack);
    	printf("非递归先序:");
    	preOut1(root,&stack); //非递归先序
    	printf("\n");
    	InitStack(&stack);
    	printf("非递归中序:");
    	midOut1(root,&stack); //非递归中序
    	printf("\n");
    	InitStack(&stack);
    	printf("非递归后序:");
    	rearOut1(root,&stack); //非递归后序
    	printf("\n");
    	InitStack(&stack);
    	printf("非递归后序:");
    	rearOut2(root,&stack); //非递归后序-简单版 
    	printf("\n");
    	getCount(root); //统计二叉树中叶子结点的个数
    	printf("二叉树的叶子节点数量为%d\n",count);
    	getHigh(root,1); //计算二叉树的高度 
    	printf("二叉树的高度为%d\n",deep);
    	int k;
    	printf("计算第k层的叶子节点个数,请输入k:");
    	while(1){
    		scanf("%d",&k);
    		if(k<1||k>deep){
    			printf("没有这一层,请重新输入\n"); 
    		}else{
    			getCountK(root,1,k); //计算指定的某一层k的叶子节点个数
    			printf("第%d层的叶子节点个数为%d",k,countK); 
    			break;
    		}
    	}	 
    }
    
    void InitStack(Stack *p) //初始化栈 
    {
    	p->top=-1;	 
    } 
    
    void pushStack(Stack*p,Tree *c) //入栈
    {
    	if(p->top+1>=MAXSIZE) return;
    	p->data[++(p->top)]=c;
    }
    
    void popStack(Stack*p,Tree**c) //出栈
    {
    	if(p->top<0) return;
    	*c=p->data[(p->top)--];
    }
    
     
    Tree* create(Tree *root){ //扩展先序创建树  
    	char ch;
    	ch=getchar();
    	if(ch=='#'){
    		return NULL;
    	}else{
    		root=(Tree*)malloc(sizeof(Tree));
    		root->data=ch;
    		root->left=create(root->left);
    		root->right=create(root->right);
    	}
    	return root;
    }
    //递归遍历 
    void preOut(Tree *root) //先序遍历 
    {
    	if(!root) return;
    	printf("%c",root->data);
    	preOut(root->left);
    	preOut(root->right);
    }
    void midOut(Tree *root) //中序遍历 
    {
    	if(!root) return;	
    	midOut(root->left);
    	printf("%c",root->data);
    	midOut(root->right);
    }
    void rearOut(Tree *root) //后序遍历 
    {
    	if(!root) return;	
    	rearOut(root->left);
    	rearOut(root->right);
    	printf("%c",root->data);
    }
    void printTree(Tree *root,int h) //输出树状图 
    {
    	if(root==NULL){
    		return;
    	}
    	printTree(root->right,h+1);
    	for(int i=0;idata);
    	printTree(root->left,h+1);	
    }
    //非递归遍历 
    void preOut1(Tree *root,Stack *stack) //先序遍历 
    {
    	if(!root) return;
    	Tree *temp;
    	pushStack(stack,root);
    	while(stack->top>-1){
    		popStack(stack,&temp);
    		printf("%c",temp->data);
    		if(temp->right){
    			pushStack(stack,temp->right);
    		}
    		if(temp->left){
    			pushStack(stack,temp->left);
    		}
    		
    	}
    }
    void midOut1(Tree *root,Stack *stack) //中序遍历 
    {
    	if(!root) return;
    	Tree *temp=root;	
    	while(temp||stack->top > -1){
    		while(temp){
    			pushStack(stack,temp);
    			temp=temp->left;
    		}
    		popStack(stack,&temp);
    		printf("%c",temp->data);
    		temp=temp->right;
    	}
    }
    void rearOut1(Tree *root,Stack *stack) //后序遍历 
    {
    	if(!root) return;
    	Tree *temp=root;
    	Tree *visted=NULL;
    	while(temp||stack->top > -1){
    		while(temp){
    			pushStack(stack,temp);
    			temp=temp->left;
    		}
    		temp=stack->data[stack->top];
    		if(temp->right==NULL||temp->right==visted){
    			printf("%c",temp->data);
    			stack->top--;
    			visted=temp;
    			temp=NULL;
    		}else{
    			temp=temp->right;
    		}
    	}
    }
    void rearOut2(Tree *root,Stack *stack) //后序遍历(简单版—先序改写) 
    {
    	if(!root) return;
    	Tree *temp;
    	char data[MAXSIZE];
    	int cnt=0; 
    	pushStack(stack,root);
    	while(stack->top>-1){
    		popStack(stack,&temp);
    		data[cnt++]=temp->data;
    		if(temp->left){
    			pushStack(stack,temp->left);
    		}
    		if(temp->right){
    			pushStack(stack,temp->right);
    		}		
    	}
    	for(int i=cnt-1;i>=0;i--){
    		printf("%c",data[i]);
    	} 
    }
    void getCount(Tree *root)//统计二叉树中叶子结点的个数 
    {
    	if(!root) return;
    	if(root->left==NULL&&root->right==NULL) count++;
    	getCount(root->left);
    	getCount(root->right);
    }
    void getHigh(Tree *root,int h)//计算二叉树的高度 
    {
    	if(!root) return;
    	if(deepleft,h+1);
    	getHigh(root->right,h+1);
    }
    void getCountK(Tree *root,int h,int k)//计算指定的某一层k的叶子节点个数 
    {
    	if(!root) return;
    	if(root->left==NULL&&root->right==NULL&&h==k) countK++;
    	getCountK(root->left,h+1,k);
    	getCountK(root->right,h+1,k);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249

    运行结果样例

    在这里插入图片描述

  • 相关阅读:
    SpringBoot+Vue3外卖项目构思
    MAYA教程之建模基础命令介绍
    DPD(Digital Pre-Distortion,数字预失真)
    springboot logback-spring.xml 整合apollo实现动态配置日志级别
    vue 组件拖拽vue-slicksort应用
    MySQL数据脱敏(Data masking plugin functions)
    [附源码]java毕业设计基于的城镇住房公积金管理系统
    后端项目连接数据库-添加MyBatis依赖并检测是否成功
    INI 配置文件
    计算机组成原理-----定点数原码和补码的乘法与除法
  • 原文地址:https://blog.csdn.net/m0_61122217/article/details/127652346