二叉树的实现以及递归遍历的精确模拟
来源:互联网 发布:新网域名怎么转到万网 编辑:程序博客网 时间:2024/06/03 23:44
对于一个二叉树,我们来精确模拟他的递归遍历过程
后序递归遍历的代码如下:
void posttravel(BinTree t){ if(!t){ posttravel(t->left); posttravel(t->right); printf("%c "t->data); }}
我们知道,递归遍历要借助堆栈,并且前序、中序、后序遍历经过节点的次序是一样的,不同的是在不同的时刻访问他们(即打印出来),对于下面的一颗二叉树,我们按照上面的递归代码走一遍首先,先将A入栈(A并没有执行完,需要先保存起来),
栈中是这样:
A |
执行posttravel(t->left),
A | B
执行posttravel(t->left),
A | B | D
执行posttravel(t->left)
A | B | D | NULL;
由于此时的t = NULL. 所以退出posttravel(t->left), 退到上一层,D的左子树执行完了
D先出栈再进栈, t = D,执行posttravel(t->right)
A | B | D | F
由于F的左右子树都空,就不详述了,D最后出栈,返回上一层, t = D,此时D的左右子树都已经执行完了,D出栈
从D我们可以看到,每个元素都是两次进栈,两次入栈的。第一次遇到D,D第一次入栈,遍历完他的左子树后,D第一次出栈,要遍历他的右子树前,D第二次入栈,遍历完他的右子树后,D第二次出栈
一下的过程相同,有兴趣可以自己走一遍。
下面我们就根据这个过程用非递归方式精确模拟遍历二叉树的过程,注意,这里的遍历单单指遍历二叉树的每个节点,并不是要访问(打印)它,我们要知道,无论哪种遍历方式,走过的路线是一样的,只是打印的时间不同而已.
enum State{ start, return_from_left, return_from_right// 访问左子树、右子树前都要经过根节点,我们以这两次“经过”为标准,将根节点划分为访问了自己,访问完左子树,访问完// 右子树,即过程是:第一次经过自己->访问左子树->第二次经过自己->访问右子树-第三次经过自己(返回上层)};typedef struct StackElem{enum State state; // 节点状态 BinTree t; // 节点 }StackElem;void postorder(BinTree t){// if(!t) return;StackElem item = {start, t}; // 根节点 stack s = createstack(MAX); // 遍历要借助堆栈实现 while(1){ // 退出条件是所有节点都遍历完(每个节点两进两出) if(item.t){if(item.state == start){ // 遍历左子树push(s, item);item.t = item.t->left;item.state = start; }else if(item.state == return_from_left){ // 遍历右子树push(s, item);item.t = item.t->right;item.state = start;}else{// 返回上一层// 左(右)子树遍历完后返回他的根节点(上一层) if(!isempty(s)){item = pop(s);item.state++;}else{break;}}}else{// 当前为空的话,也要返回上一层 if(!isempty(s)){item = pop(s);item.state++;}else{break;}}}return;}
下面是一个后序遍历的具体实现:
#include<stdio.h>#include<stdlib.h>#include<stdbool.h>#define ElementType char#define MAX 50enum State{ start, return_from_left, return_from_right// 访问左子树、右子树前都要经过根节点,我们以这两次“经过”为标准,将根节点划分为访问了自己,访问完左子树,访问完// 右子树,即过程是:第一次经过自己->访问左子树->第二次经过自己->访问右子树-第三次经过自己(返回上层)};typedef struct TNode *BinTree;struct TNode{ElementType data;struct TNode *left;struct TNode *right;};typedef struct StackElem{enum State state;BinTree t;}StackElem;typedef struct Stack{StackElem *data;int MAXSIZE;int top;} *stack;/*******************************/BinTree createtree(BinTree t, bool isroot);stack createstack(int max);void push(stack s, StackElem se);StackElem pop(stack s);int isempty(stack s);void postorder(BinTree t);BinTree createtree(BinTree t, bool isroot);void freetree(BinTree t);/********************************/int main(){BinTree t;t = createtree(t, true);postorder(t);freetree(t);return 0;}// 创建空栈stack createstack(int max){stack s = (stack)malloc(sizeof(struct Stack));s->data = (StackElem *)malloc(sizeof(StackElem) *max);s->MAXSIZE = max;s->top = -1;return s;}// 进栈void push(stack s, StackElem se){if(s->top+1 == s->MAXSIZE)return;s->data[++(s->top)] = se;}// 出栈StackElem pop(stack s){StackElem tmp = s->data[s->top];--s->top;return tmp;}// 判空int isempty(stack s){return s->top == -1;}// 后序遍历void postorder(BinTree t){// if(!t) return;StackElem item = {start, t};stack s = createstack(MAX);while(1){if(item.t){if(item.state == start){ // 遍历左子树push(s, item);item.t = item.t->left;item.state = start;}else if(item.state == return_from_left){ // 遍历右子树push(s, item);item.t = item.t->right;item.state = start;}else{// 返回上一层printf("%c ", item.t->data);if(!isempty(s)){item = pop(s);item.state++;}else{break;}}}else{if(!isempty(s)){item = pop(s);item.state++;}else{break;}}}return;}// 建立二叉树BinTree createtree(BinTree t, bool isroot){ElementType data;if(isroot){printf("root is:");}fflush(stdin);scanf("%c", &data); fflush(stdin);if(data != '#'){ isroot = false;t = (BinTree )malloc(sizeof(struct TNode));t->data = data;t->left = NULL; t->right = NULL;printf("%c s left child is : ", t->data);t->left = createtree(t->left, isroot);printf("%c s right child is : ", t->data);t->right = createtree(t->right, isroot);}return t;}// 释放二叉树void freetree(BinTree t){if(!t){freetree(t->left);freetree(t->right);free(t);}return;}
阅读全文
0 0
- 二叉树的实现以及递归遍历的精确模拟
- 二叉树的链表实现以及非递归遍历
- 二叉树的非递归遍历以及递归遍历
- 二叉树的递归遍历以及非递归遍历
- 二叉树的创建,递归遍历以及非递归遍历
- 二叉树(一):二叉树的创建以及三种遍历方法的递归实现
- 二叉树的先序递归以及非递归遍历
- 二叉树的递归,层次,以及非递归遍历
- 二叉树的遍历 递归以及非递归
- 遍历二叉树的递归算法与非递归算法以及C语言实现
- 二叉树分层遍历(递归以及非递归的实现)
- <数据结构>二叉树的递归、非递归以及层次遍历算法C语言实现
- 二叉树的递归遍历以及层次遍历
- 二叉树的非递归遍历以及层次遍历
- 二叉树的非递归中序遍历以及层序遍历实现
- 二叉树的建立,以及递归前中后序遍历二叉树
- 非递归实现二叉树的遍历
- 二叉树遍历的递归实现图解
- 整形单链表中的最大值,结点个数,平均值
- HTTPS协议详解
- 【二分+莫比乌斯函数】BZOJ2440 [中山市选2011]完全平方数
- RabbitMq Ubuntu 安装
- host client登录地址
- 二叉树的实现以及递归遍历的精确模拟
- 如何正确使用J-Link调试MCUXpresso项目
- PAT 1041. 考试座位号(15)
- NO.2 Spring IOC架构及概念
- [转]系统吞吐量(TPS)、用户并发量、性能测试概念和公式
- 1062. 最简分数(20)
- 【Momentum,Decay】关于动量和权衰减率
- python图像处理入门
- bind和new