非递归遍历二叉树c语言,二叉树非递归遍历(堆栈)——C语言

二叉树非递归遍历(堆栈)——C语言

二叉树非递归遍历(堆栈)——C语言

二叉树遍历根据输出根节点数据次序的不同,分为先序、中序、后序三种。用递归的方式可以很容易实现。

先序是在第一次遇到节点时就输出,中序是访问完左子树后回退时输出,后序是访问完右子树后回退时输出。

06941e3aa66cffd24d57a6d5c151423d.png

而非递归的方式,则是通过堆栈实现。

2d3cfb3f94b7e9d59afd324007d58e5e.png

#include

#include

typedef struct TreeNode *BinTree;

struct TreeNode{

int data;

BinTree lef;

BinTree rig;

};

typedef struct Node *Stack;

struct Node{

/* 堆栈的本质是一种链表关系, 通过对ElemType的灵活定义,

可以将这种关系拓展到其他数据结构元上, 如: 此处的二叉树结点

而这里的变量名tNode, last可固定化, 故通过模板(害没学..)可实现高效的堆栈复用 */

BinTree tNode;

Stack last;

};

Stack CreateStack(){

Stack s = (Stack)malloc(sizeof(Node));

s->tNode = NULL;

s->last = NULL;

return s;

}

BinTree CreateBT(){

BinTree t = (BinTree)malloc(sizeof(TreeNode));

t->rig = NULL;

t->lef = NULL;

return t;

}

void Push(Stack s, BinTree t){

Stack tmpNode = CreateStack();

tmpNode->tNode = t;

tmpNode->last = s->last;

s->last = tmpNode;

}

BinTree Pop(Stack s){

BinTree t;

Stack tmpNode;

tmpNode = s->last;

t = tmpNode->tNode;

s->last = tmpNode->last;

free(tmpNode);

return t;

}

void InOrderTraversal(BinTree tree)

{

BinTree t = tree;

Stack s = CreateStack();

BinTree visitedNode = NULL;

while(t || (s->last!=NULL))

// t isnt empty means we have not reached the end

// s isnt empty means we have not reached the top

{

while(t!=NULL){

Push(s, t);

// printf("%d", t->data);

// 先序遍历在第一次访问根节点(深挖)时输出

t = t->lef;

}

if (s->last!=NULL){

t = Pop(s);

// printf("%d", t->data);

// 中序遍历在第二次访问根节点(深挖后第一次回退)时输出

// t = t->rig;

// 后序时注释掉上行

if (!(t->rig) || (t->rig == visitedNode)){

printf("%d", t->data);

t = NULL;

}

else{

Push(s, t);

visitedNode = t->rig;

t = t->rig;

}

// 后序遍历逻辑较为复杂一点,访问完左子树后,需要访问右子树,故要将

// 出的栈再压回去,而此逻辑又将造成死循环,程序卡在右子树内(若右子树不空),

// 故引入visitedNode先记录根结点的右结点,再进行访问,这样右子结点出栈后再次遇

// 到根节点时,只需进行一次判断即可跳出死循环逻辑。

// 还有一种做法是在每个树结点内,引入状态变量记录是否访问过,

// 本质与此方法一样,但空间开销增加。

// 还有另一种截然不同的做法是,使用双栈,考虑先序输出:根->左->右,后序输出:左->右->根

// 可将二叉树左右结点互换后,先序输出并依序压栈,再依序出栈,即为后序遍历

}

}

}

int main(){

BinTree t = CreateBT();

t->data = 1;

t->lef = CreateBT();

t->lef->data = 2;

t->lef->lef = CreateBT();

t->lef->lef->data = 3;

t->lef->rig = CreateBT();

t->lef->rig->data = 4;

t->lef->rig->lef = CreateBT();

t->lef->rig->lef->data = 5;

InOrderTraversal(t);

system("pause");

return 0;

}

二叉树非递归遍历(堆栈)——C语言相关教程

LeetCode——235. 二叉搜索树的最近公共祖先

LeetCode——235. 二叉搜索树的最近公共祖先 根据二叉搜索树的性质查找节点,二叉搜索树,左子树的值小于根节点,右子树的值大于根节点,每棵树都符合这种规则,我们可以从上往下去遍历寻找,当节点的值比两个给的节点的值都大的时候,就往左子树上寻找,都小

递归 八皇后问题的一些思考

递归 八皇后问题的一些思考 大家觉得写还可以,可以 点赞、收藏、关注 一下吧! 也可以到我的个人博客参观一下,估计近几年都会一直更新!和我做个朋友吧!https://motongxue.cn 如何设计一种方案。在一个无穷大的国际棋盘的每一行每一列里都放置一个皇后,

leetcode-669. 修剪二叉搜索树

leetcode-669. 修剪二叉搜索树 修剪二叉搜索树 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。 示例 1: 输入:

什么叫递归

递归: 1、要调用自己本身; 2、要有一个趋于终止的条件。 (推荐教程:java课程) 下面以一个求阶乘的例子简单介绍一下: public class recursion { public static int fac(int n) { if(n == 1){ return 1; //终止条件 } return n * fac(n-1); //调用自身 }

递归原来可以so easy|-连载(2)

递归原来可以so easy|-连载(2) 一个简单的例子 下面用一个简单的例子来演示递进和回归。 public class Hello { static int s=1; static void rd(int n){ System.out.format(%d 递进,n:%d\n,s++,n); if(n==1) return; else{ rd(n-1); System.out.format(%d

递归原来可以so easy|-连载(1)

递归原来可以so easy|-连载(1) 引子 从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚

【树】---- 二叉树

【树】---- 二叉树 1 树的基本概念 (1)树是由若干结点组成的具有层次关系的集合,非空树有且只有一个根结点(/)。 (2)某个结点及其下面所有的结点并称为以该结点为根的子树(usr及其下的所有结点就是/的一颗子树,usr是该子树的根)。 (3)结点拥有的子

leetcode 102 剑指Offer 32 二叉树的层次遍历

leetcode 102 剑指Offer 32 二叉树的层次遍历 思路不难,直接用队列迭代就可以。 遍历过程如下: 代码如下: public class offer32 { public ListListInteger levelOrder(TreeNode root) { ListListInteger ans = new LinkedList(); DequeTreeNode deque = ne

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值