看了大量网络相关的理论和程序,多数的C++ 写的,这里使用devC++
编程语言 C语言; 整合王道考研答案和理论, 还有小甲鱼的数据结构, 郝斌的数据结构,各有特点吧
最值得研究的还是后序遍历的非递归算法, 当时想了使用flag, 想到了多用一个栈, 想到了很多种方式,最后都以失败告终,经过网络查找,
感谢 https://www.cnblogs.com/rain-lei/p/3705680.html
这里使用的一个栈每个结点两次入栈,解决了后序遍历与父结点遍历的冲突,相信只有仔细思考过这个问题的朋友才会明白多有意思.
话不多说,直接上代码, 复制粘贴可用.

#include "stdio.h"
#include "stdlib.h"
#include "malloc.h"
#include "string.h"
#include "stdbool.h"/*  变量声明区  */
typedef char elemType; /*    结构体声明    */
typedef struct BitTree{ //树elemType data;struct BitTree *lChild, *rChild;int lTag, rTag;
}*PBitTree, BitTreeN; #define STACK_MAX_SIZE 50
typedef struct Stack{   //栈PBitTree data[STACK_MAX_SIZE];int top;
}Stack, *PStack;
/*注意 top=-1为空 top=max为满
*/ #define QUEUE_MAX_SIZE 50
typedef struct Queue{   //队列 PBitTree data[QUEUE_MAX_SIZE]; int rear,front;
}Queue, *PQueue;
/*注意 rear=front为空 (rear+1)%max = front为满
*//*  函数声明区  */
//common bit treevoid CreateBieTr_Pre(PBitTree*T);               /*  动态创建先序二叉树  */
/*使用递归方式,判断的输入的字符是否为' ',然后递归&(*T)->lChild,在rChild*/ PBitTree CreateBT(void);                        //静态建立二叉树
/*创建结点,在将结点相互关联到一起*/ PBitTree InitBitTree_Pre(elemType pre[], int pre0, int pren, elemType in[], int in0, int inn);
/*将先序和中序合并成先序, 使用遍历算法,
先找到先序的第一个结点,用第一个查找中序的位置,确定好中序中间位置到两端的长度,
作为递归确定左右孩子的参数, 当找不到中点表示为NULL*/ //递归遍历
void visit(elemType ch, int level);
void PreOrder_Recursion(PBitTree T, int level);  /* 先序遍历二叉树 */
void MedOrder_Recursion(PBitTree T, int level); /* 中序遍历二叉树 */
void PostOrder_Recursion(PBitTree T, int level);/* 后序遍历二叉树 *///非递归遍历
void InOrder2(PBitTree T);  //使用栈 中序遍历 非递归
void PreOrder2(PBitTree T);  //使用栈 先序遍历 非递归
void PostOrder2(PBitTree T);  //使用栈 后序遍历 非递归
void PostOrder2_2(PBitTree T);  //双次入栈 后序遍历 非递归
void LevelOrder_from_H_to_L_L_to_R(PBitTree T); //使用队列 层次遍历 非递归  void main()
{int i; PBitTree T = NULL;char val;int int_val;int level=1; //初始化二叉树1
//  printf("下面进行动态先序生成二叉树,使用空格作为NULL标记:\n");
//  CreateBieTr_Pre( &T );//初始化二叉树2
//  T =CreateBT();//初始化二叉树3 elemType pre[] = "ABCDEF"; elemType  in[] = "CBDAEF"; T = InitBitTree_Pre(pre, 0, 6, in, 0, 6);   printf("普通二叉树的前序遍历\n"); PreOrder_Recursion(T, level); printf("普通二叉树的中序遍历\n"); MedOrder_Recursion(T, level); printf("普通二叉树的后序遍历\n"); PostOrder_Recursion(T, level);  InOrder2(T); //中序非递归二叉树的遍历 PreOrder2(T);PostOrder2(T); PostOrder2_2(T);LevelOrder_from_H_to_L_L_to_R(T);return;
}/*  函数实现区  */ //---------------------------------------------------------------//动态 先序创建树
void CreateBieTr_Pre(PBitTree*T)
{elemType ch;scanf("%c",&ch);if(' ' == ch) {   *T = NULL; return; }else{(*T) = (PBitTree)malloc(sizeof(BitTreeN));(*T)->data = ch;CreateBieTr_Pre(&(*T)->lChild);CreateBieTr_Pre(&(*T)->rChild);return;}
}/*  静态建立二叉树 */
PBitTree CreateBT(void)
{   PBitTree PA = (PBitTree)malloc(sizeof(BitTreeN)); PA->data = 'A';PBitTree PB = (PBitTree)malloc(sizeof(BitTreeN)); PB->data = 'B';PBitTree PC = (PBitTree)malloc(sizeof(BitTreeN)); PC->data = 'C';PBitTree PD = (PBitTree)malloc(sizeof(BitTreeN)); PD->data = 'D';   PBitTree PE = (PBitTree)malloc(sizeof(BitTreeN)); PE->data = 'E';   PBitTree PF = (PBitTree)malloc(sizeof(BitTreeN)); PF->data = 'F';   PA->lChild = PB; PA->rChild = PE;PB->lChild = PC; PB->rChild = PD;   PE->lChild = NULL; PE->rChild = PF; PC->lChild = PC->rChild = NULL;PD->lChild = PD->rChild = NULL;PF->lChild = PF->rChild = NULL;return PA;
}
/*  给出先序和中序,求先序的二叉链表 Pre是先序 给出数组中0-n表示的位置 In是中序  */
PBitTree InitBitTree_Pre(elemType pre[], int pre0, int pren, elemType in[], int in0, int inn)
{
//  if()return; PBitTree Root = (PBitTree)malloc(sizeof(BitTreeN));Root->data = pre[pre0];int i;int lLen,rLen; for(i=in0; in[i] != Root->data; i++);   //找到中间值lLen = i-in0;  //左子树长度 rLen = inn-i;   //右子树长度 printf("in0=%d, inn=%d  pr0=%d, pren=%d data  %c  zuo %d zyo  %d \n",pre0, pren, in0, inn,  Root->data,lLen,rLen); if(lLen){Root->lChild = InitBitTree_Pre(pre, pre0+1, pre0+lLen, in, in0, in0+lLen-1);//建立左子树 }else{Root->lChild = NULL;}if(rLen){Root->rChild = InitBitTree_Pre(pre, pren-rLen+1, pren, in, inn-rLen+1, inn);//建立左子树 }else{Root->rChild = NULL;}    return Root;
}//-----以下为common Bit Tree的三种遍历----------------------------------------------------------------------------// void visit(elemType ch, int level)
{printf("树 %c 位于第 %d 层\n", ch, level);return;
} /* 先序遍历二叉树 */
void PreOrder_Recursion(PBitTree T, int level)
{if(NULL != T)  //递归缺点 浪费空间,运行时间长 {visit(T->data, level);//访问根节点 if(NULL != T->lChild) PreOrder_Recursion(T->lChild, level+1);  //先左子树 if(NULL != T->rChild) PreOrder_Recursion(T->rChild, level+1);   //后右子树      } return;
} /* 中序遍历二叉树 */
void MedOrder_Recursion(PBitTree T, int level)
{if(NULL != T)  //递归缺点 浪费空间,运行时间长 {if(NULL != T->lChild) MedOrder_Recursion(T->lChild, level+1);  //先左子树visit(T->data, level);//访问根节点        if(NULL != T->rChild) MedOrder_Recursion(T->rChild, level+1);   //后右子树      }
} /* 后序遍历二叉树 */
void PostOrder_Recursion(PBitTree T, int level)
{if(NULL != T)  //递归缺点 浪费空间,运行时间长 {if(NULL != T->lChild) PostOrder_Recursion(T->lChild, level+1);  //先左子树               if(NULL != T->rChild) PostOrder_Recursion(T->rChild, level+1);  //后右子树      visit(T->data, level);//访问根节点 }
}/*   普通二叉树 非递归 中序遍历  */
void InOrder2(PBitTree T)
{   printf("普通二叉树 非递归 中序遍历:\n");PBitTree P = T; //P是遍历指针 PStack S = (PStack)malloc(sizeof(Stack));  S->top = -1; //初始化栈while( P || ( S->top != -1 ) )  //栈不空 P不空 {if( P ){if(S->top != STACK_MAX_SIZE)  //栈不满 {S->data[ ++S->top ] = P; P = P->lChild;}}else{if(S->top != -1)  //栈不空{P = S->data[ S->top--];  //出栈 printf("%c ",P->data);P = P->rChild;}}}printf("\n");return;
}/*   普通二叉树 非递归 先序遍历  */
void PreOrder2(PBitTree T)
{printf("普通二叉树 非递归 先序遍历:\n");PBitTree P = T; //P是遍历指针PStack S = (PStack)malloc(sizeof(Stack));  S->top = -1; //初始化栈while( P || ( S->top != -1 ) ){if( P ) //遍历左孩子 {printf("%c ",P->data);S->data[++S->top] = P;  //入栈P = P->lChild;       } //出来是遇到了空 else{P = S->data[S->top--];  //出栈P = P->rChild;          }}printf("\n");return;
} /*   普通二叉树 非递归 后序遍历  */
void PostOrder2(PBitTree T)
//重点在于判定指针是从左子树返回的还是右子树, 若右子树则该结点已经到顶了
{printf("普通二叉树 非递归 后序遍历:\n");PBitTree P = T; //P是遍历指针PBitTree R = NULL; //辅助指针 PStack S = (PStack)malloc(sizeof(Stack));  S->top = -1; //初始化栈while( P || (S->top!=-1) ){if(P)   // 一直遍历到最左下面 {S->data[++S->top] = P;P = P->lChild; }else {P = S->data[S->top];    if(P->rChild != NULL && P->rChild!=R )  //如果右子树存在且未被访问过 {P = P->rChild;S->data[++S->top] = P;P = P->lChild;}else{P = S->data[S->top--];printf("%c ",P->data);R = P;P = NULL;}}}printf("\n");return;
}void PostOrder2_2(PBitTree T)
{if(T == NULL){return;}printf("通普二叉树 非递归 后序遍历\n"); PBitTree P = T; PStack S = (PStack)malloc(sizeof(Stack));S->top = -1;S->data[++S->top] = T;  //树根节点 双次入栈 S->data[++S->top] = T;while(S->top != -1){P = S->data[S->top--];  if(S->top!=-1 && P==S->data[S->top])//栈不为空,且 曾经的栈 前两层相同 {//栈顶的左右孩子如果还有,则下次循环  曾经的栈 前两层相同 继续寻找最左边//结点的左右孩子,然后继续寻找直到找到左右孩子都没有了,就开始打印/*对于每个结点都压栈两次,在循环中,每次弹出的一个结点赋给P,如果P仍然等于栈的头结点,说明P的孩子们还有没被操作过的,应该把他的孩子们入栈,否则,访问P也就是说, 第一次弹出, 将P的孩子压栈, 第二次弹出, 访问P */ if(P->rChild != NULL){S->data[++S->top] = P->rChild;S->data[++S->top] = P->rChild;}if(P->lChild != NULL){S->data[++S->top] = P->lChild;S->data[++S->top] = P->lChild;}}else                                //曾经的栈 前两层不相同  {printf("%c ",P->data); }}printf("\n");return;
} /* 普通二叉树的遍历 从上到下,从左到右 */
void LevelOrder_from_H_to_L_L_to_R(PBitTree T)
{if(!T)return; //防止空树 printf("普通二叉树的遍历 从上到下,从左到右\n");PBitTree P = T; PQueue Q = (PQueue)malloc(sizeof(Queue));  //新建队列 Q->front = Q->rear =0;Q->data[Q->rear] = P; Q->rear = (Q->rear+1)%QUEUE_MAX_SIZE; //根结点入队while( Q->rear != Q->front ){P = Q->data[Q->front]; Q->front = (Q->front+1)%QUEUE_MAX_SIZE; //出队printf("%c ",P->data);//注意 如果需要层次遍历 从下到上,从右到左 可以在这里入栈,到最后在出栈if(P->lChild) {Q->data[Q->rear] = P->lChild;  //入队 Q->rear = (Q->rear+1)%QUEUE_MAX_SIZE; } if(P->rChild) {Q->data[Q->rear] = P->rChild;Q->rear = (Q->rear+1)%QUEUE_MAX_SIZE;}} printf("\n");return;
} 

C语言-数据结构-二叉树的递归遍历和非递归遍历相关推荐

  1. 【数据结构】--- 二叉树的递归遍历和非递归遍历【C语言实现】

    目录 1. 创建一颗二叉树 2.递归前序遍历二叉树 3.递归中序遍历二叉树 4.递归后序遍历二叉树 5. 测试递归打印二叉树代码 6. 非-递归前序遍历二叉树 7. 非-递归实现中序遍历二叉树 8.  ...

  2. 信号放大器数据结构_[11/11]数据结构 二叉树应用(树型信号放大器,file transfer,遍历的非递归实现)...

    树型分布网络信号放大器 森林和二叉树的相互转换 并查集 例题:File transfer #include <iostream> using namespace std; //typede ...

  3. 二叉树前中后序遍历的非递归实现以及层次遍历、zig-zag型遍历详解

    前言 二叉树的遍历是一个比较常见的问题,递归实现二叉树的前中后序遍历比较简单,但非递归实现二叉树的前中后序遍历相对有难度.这篇博客将详述如何使用非递归的方式实现二叉树的前中后序遍历,在进行理论描述的同 ...

  4. 二叉树遍历详解(递归遍历、非递归栈遍历,Morris遍历)

    一.前言 <二叉查找树全面详细介绍>中讲解了二叉树操作:搜索(查找).遍历.插入.删除.其中遍历深度优先遍历(DFS)按照实现方法可以分为:递归遍历实现.非递归遍历实现.Morris遍历实 ...

  5. 二叉树创建,递归遍历,非递归遍历

    二叉树 博主是一个大一刚刚放暑假的大学生,大学我们只学习了c语言,现在这么卷只学c语言肯定不够,所以博主打算从零开始恶补c++顺便写文章记录一下,另外博主这个暑假还想记录一些算法基础内容欢迎关注哦.这 ...

  6. 二叉树中序遍历(递归法和迭代法(非递归法))——C++

    声明:本文原题主要来自力扣,记录此博客主要是为自己学习总结,不做任何商业等活动! 二叉树的遍历有前序遍历.中序遍历.后序遍历和层次遍历,其中二叉树基本知识点可以参考博主上篇博客(二叉树基本知识点图文介 ...

  7. 【二叉树Java】二叉树遍历前序中序后序遍历的非递归写法

    本文主要介绍二叉树前序中序后序遍历的非递归写法 在探讨如何写出二叉树的前序中序后序遍历代码之前,我们先来明确一个问题,前序中序后序遍历根据什么区分? 二叉树的前序中序后序遍历,是相较根节点说的.最先遍 ...

  8. 漫谈二叉树遍历(非递归)

    ------这篇文章旨在提出一种简单方便,易于理解时空复杂度低且风格统一的二叉树非递归遍历方法. 从二叉树先序遍历开始 二叉树的先序遍历(非递归)相比中后序是最少花哨.最统一的.一般来说先序遍历的代码 ...

  9. 4.二叉树的先序、中序以及后序遍历的递归写法与非递归写法(LeetCode第94、144、145题)

    一.递归法 这次我们要好好谈一谈递归,为什么很多同学看递归算法都是"一看就会,一写就废". 主要是对递归不成体系,没有方法论,每次写递归算法 ,都是靠玄学来写代码,代码能不能编过都 ...

  10. 遍历二叉树的各种操作(非递归遍历)

    先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序.中序.后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组 ...

最新文章

  1. 【读书笔记】代码可为维护性标准(一)
  2. 用JAVASCRIPT实现静态对象、静态方法和静态属性
  3. 《Cocos2D权威指南》——3.9 本章小结
  4. mysql 性能 索引怎么用_MySQL索引使用方法和性能優化
  5. Matlab:批量文件命名
  6. 上海技术计算机学校学费多少,上海web前端学校学费一般是多少
  7. 华为狼性文化遭质疑,那我们当个佛系程序员可好?
  8. 革新OCR结构化技术应用,揭秘百度中英文OCR结构化模型StrucTexT预训练模型
  9. 进程间的通信方式有哪些?
  10. 用scratch实现网上“超人训练”游戏
  11. C++ 中 _T 含义及用途
  12. SolidWorks中提高大型装配性能Part4— SolidWorks装配工具
  13. 一台汽车在新上市之前需要经历多少考验,才有资格驶向我们?
  14. Raft 共识算法1-Raft基础
  15. Centos7 安装VLC播放器
  16. MAC vscode 编译多个文件失败(已解决)
  17. 浅谈游戏《Cuphead茶杯头》
  18. CAD2018安装计算机黑屏,简单几步解决cad2019在win10上打不开的问题
  19. 关于动漫的HTML网页设计:期末前端web大作业——海贼王基地(6个页面)
  20. 批量删除Redis数据库中的Key

热门文章

  1. NTP网络时钟服务器(ntp网络同步时钟)在某空管局案例分析
  2. 漏洞扫描工具---Openvas
  3. 留学生计算机专业硕士,留学计算机专业硕士
  4. html 字符串包含某字符,js判断字符串包含某个字符的方法
  5. 知识点: Java FutureTask 使用详解
  6. 网络性能测试工具Iperf介绍
  7. python 引用计数 循环引用_Python对象的循环引用问题
  8. 解读 TiWorkerCoreInitialize
  9. 关于普通大学生对java的认知
  10. 淘宝裙子(追女朋友也是程序员的重要工作~!)