c语言实现顺序二叉树的非递归的三种遍历算法
2015-09-03 17:51
609 查看
二叉树的概念遍地都是,就不详说了。不管是顺序的还是链式的二叉树,实现的方法基本上都是递归的例子,我就自己看着遍历的方法,写出了这一个程序,程序中每个遍历实现思想都有详细描述,代码略显繁琐,欢迎读者批评指正。使用的例子看附图,也算是自己的一个学习笔记。
运行结果示例:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #define Max_Size 100 #define null '#'//表示为空 //可以当做一个数据类型 typedef char BinaryTree[Max_Size]; //初始化二叉树中每个节点为空 void InitTree(BinaryTree tree) { int i; for(i=0;i<Max_Size-1;i++) { tree[i] = null; } tree[i] = '\0'; } void CreateTree(BinaryTree tree,char *strtree) { int len = strlen(strtree); if(strtree[0] == null) { printf("树根节点不能为空"); return ; } int i; for(i=0;i<len;i++) { tree[i] = strtree[i]; //树节点从0开始,若从1开始,则判断条件改为:tree[(i+1)/2] if((tree[(i+1)/2 - 1] == null) &&(tree[i] != null)) { printf("构造二叉树错误,子节点没有父节点.\n节点为%d %c.\n",i+1,tree[i]); exit(1); return; } } } //使用完全二叉树求深度的公式[log₂N]+1 [x]取不大于x的整数 int Length(char *strtree) { printf("二叉树字符串:%s\n完全二叉树的节点数::%d\n",strtree,strlen(strtree)); //c语言提供的函数log10 float a = log10((double)strlen(strtree)),b = log10(2.0); //计算深度函数 int len = a/b + 1; printf("二叉树深度为:%d\n",len); return len; } int Is_Empty(BinaryTree tree) { if(tree[0] == '#' || tree[0] == '\0') { printf("二叉树为空!\n"); return 1; } return 0; } //有效节点个数 int Count(BinaryTree tree) { int count=0; int len = strlen(tree); int i=0; while(i < len) { if(tree[i] != '#') { count++; } i++; } return count; } //先序遍历实现思想:(根据输出的有效节点个数来作为循环的终止条件) //一:从根节点出发,先打印根节点, //二:寻找下一个左节点, //三:若节点不为空,打印该节点并重复步骤二 //四:若节点为空,判断该节点的兄弟右节点 //五: 若不为空,从该节点开始,重复步骤二 //六: 若为空,回退至上一个节点,重复步骤四 //注:(回退时注意从左节点开始回退,避免两个不同子树的右孩子与左孩子有联系) void PreOrderTraverse(BinaryTree tree) { char Strtree[Max_Size]; strcpy(Strtree,tree); if((Is_Empty(Strtree) == 1)) { return; } int len = Count(Strtree); int k=0,i=0;//i表示节点在完全二叉树中的位置 //根据输出的有效节点个数来作为循环的终止条件 while(k < len) { while(Strtree[i] != '#') { //打印有效节点 printf("%c ",Strtree[i]); Strtree[i] = '#';//标志节点已被打印为空 k++; //继续寻找左节点 i = (i+1)*2 - 1; if(Strtree[i] == '#') { break; } } //遍历右节点 if(Strtree[i+1] != '#') { i = i + 1; } else { //回退过程 i = (i+1)/2 - 1; if(i%2 == 0 ) { i = i - 1; } } } } //中序遍历实现思想:(根据输出的有效节点个数来作为循环的终止条件) //一:对于任意一个节点,先找到它的最左节点,最左节点的下一个左节点一定是空的 //二:回退至上一个节点,判断该节点是否为空(左子树打印过程中会置空,回退时避免打印无效节点): //三: 若不为空,打印该节点,继续判断该节点的右孩子,若不为空,重复步骤一; //四: 若为空,重复步骤二。 void MidOrderTraverse(BinaryTree tree) { char Strtree[Max_Size]; strcpy(Strtree,tree); if((Is_Empty(Strtree) == 1)) { return; } int len = Count(Strtree); int i=0,k=0;//i表示节点在完全二叉树中的位置 while(k<len) { //新一个右节点就寻找该子树的最左节点 while((Strtree[i] != '#')) { i = 2*(i+1)-1; } //回退至父节点 i = (i+1)/2 - 1; if(Strtree[i] != '#') { printf("%c ",Strtree[i]); Strtree[i] = '#';//标志节点已被打印为空 k++; } if(Strtree[(i+1)*2] != '#') { i= (i+1)*2; } } } //后序遍历实现思想: //一:对于任意一个节点,先找到它的最左节点,最左节点的下一个左节点一定是空的,判断该兄弟(右)节点: //二:若为空,回退至父节点,打印并输出该节点,判断该节点的兄弟(右)节点 //三: 若不为空,重复步骤一 //四: 若为空,重复步骤二 //注:判断右节点是否为空之前,先要判断该节点是否为右节点,如果是就要跳过该判断。 //数组的方式存储完全二叉树,除开根节点,右节点所在位置都是偶数,故用:i%2判断 void PostOrderTraverse(BinaryTree tree) { char Strtree[Max_Size]; strcpy(Strtree,tree); if((Is_Empty(Strtree) == 1)) { return; } int len = Count(Strtree); int i=0,k=0;//i表示节点在完全二叉树中的位置 while(k<len) { //新一个右节点就寻找该子树的最左节点 while((Strtree[i] != '#')) { i = 2*(i+1)-1; } //如果最左节点的兄弟(右)节点不为空,继续下一轮循环 if(Strtree[i+1] != '#' && (i%2 !=0) ) { i = i + 1; continue; } //回退至父节点 i = (i+1)/2 - 1; if(Strtree[i] != '#') { //printf("i = %d\n",i); printf("%c ",Strtree[i]); Strtree[i] = '#';//标志节点已被打印为空 k++; } //判断兄弟(右)节点(在完全二叉树中,右节点一定为偶数(除开根节点)) if(Strtree[i+1] != '#') { if(i%2 != 0) { i= i+1; } } } } int main() { BinaryTree tree; char BinaryTree[Max_Size] = "-+/a*ef##b-##########cd";//第一个图 //char BinaryTree[Max_Size] = "fdgbe#iac####hj";//第二个图 //char BinaryTree[Max_Size] = "AB#CD####EF#########G"; InitTree(tree); CreateTree(tree,BinaryTree); Length(BinaryTree); printf("有效节点个数:%d\n",Count(tree)); printf("先序遍历如下:\n"); PreOrderTraverse(tree); printf("\n中序遍历如下:\n"); MidOrderTraverse(tree); printf("\n后序遍历如下:\n"); PostOrderTraverse(tree); return 0; }
运行结果示例:
相关文章推荐
- 【C语言】结构体
- C++内存管理及指针相关
- C++入门经典 笔记 (第十章)创建指针
- Qt C++中的关键字explicit
- 零基础学C语言 笔记八 二维数组
- C语言中文件包含#include使用尖括号和双引号的区别
- C++入门经典 笔记 (第九章)高级类
- c++中输入和输入语句
- c++ primer读书笔记之c++11(三)
- C语言实验题——三个数排序
- VS2010中“工具>选项中的VC++目录编辑功能已被否决”解决方法
- 关于C++中的友元函数的总结
- 关于C语言中的cons的使用。
- 零基础学C语言 笔记七 一维数组
- C++入门经典 笔记 (第八章)创建基本类
- C语言中怎么将文件里的数据创建到(读到)链表中?
- C语言中怎么将文件里的数据创建到(读到)链表中?
- c++数组宽度计算的sizeof关于指针设想
- Effective C++ 改善程序与设计的55个具体做法 二周目笔记01
- C++ I/O流文件处理(整型,字符,字符串)