二叉树非递归实现,完整程序
- 格式:docx
- 大小:15.09 KB
- 文档页数:3
后序遍历的非递归算法(C详细)后序遍历是二叉树遍历的一种方式,它的顺序是先遍历左子树,然后遍历右子树,最后访问根节点。
非递归实现后序遍历的算法可以使用栈来辅助实现。
首先,我们需要定义一个树节点的数据结构,例如:```cstruct TreeNodeint val;struct TreeNode* left;struct TreeNode* right;};```接下来,我们使用一个辅助栈来进行非递归后序遍历。
首先需要创建一个空栈,并将根节点入栈。
然后开始循环,直到栈为空为止。
在循环中,首先取出栈顶节点,如果该节点没有左子树且没有右子树,说明该节点是叶子节点,可以直接输出该节点的值。
如果该节点有左子树或者右子树,需要判断是否已经遍历过该节点的子节点。
为了实现后序遍历的顺序,我们需要一个标记变量来记录上次访问的节点。
如果上次访问的节点是该节点的右子树,说明该节点的左右子节点都已经访问过了,可以直接输出该节点的值。
反之,如果上次访问的节点不是该节点的右子树,将该节点重新入栈,并以右、左、中的顺序将其右子树、左子树入栈。
下面给出完整的代码实现:```c#include <stdio.h>#include <stdlib.h>struct TreeNodeint val;struct TreeNode* left;struct TreeNode* right;};void postOrderTraversal(struct TreeNode* root)if (root == NULL)return;}struct TreeNode* lastVisited = NULL; // 上次访问的节点struct TreeNode* node = root; // 当前遍历的节点struct TreeNode* stack[100]; // 栈int top = -1; // 栈顶指针while (node != NULL , top != -1)if (node != NULL)stack[++top] = node; // 入栈node = node->left; // 访问左子树} elsestruct TreeNode* temp = stack[top]; // 取出栈顶节点if (temp->right == NULL , temp->right == lastVisited) printf("%d ", temp->val);top--; // 出栈lastVisited = temp; // 记录上次访问的节点} elsenode = temp->right; // 访问右子树}}}struct TreeNode* createNode(int val)struct TreeNode* node = (structTreeNode*)malloc(sizeof(struct TreeNode));if (node != NULL)node->val = val;node->left = NULL;node->right = NULL;}return node;int mai//创建一个二叉树struct TreeNode* root = createNode(1); root->left = createNode(2);root->right = createNode(3);root->left->left = createNode(4);root->left->right = createNode(5); root->right->left = createNode(6); root->right->right = createNode(7);//后序遍历二叉树printf("后序遍历结果:"); postOrderTraversal(root);printf("\n");return 0;```以上代码中,我们使用了一个辅助数组作为栈来实现非递归遍历。
实验5:二叉树的建立及遍历(第十三周星期三7、8节)一、实验目的1.学会实现二叉树结点结构和对二叉树的基本操作。
2.掌握对二叉树每种操作的具体实现,学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。
二、实验要求1.认真阅读和掌握和本实验相关的教材内容。
2.编写完整程序完成下面的实验内容并上机运行。
3.整理并上交实验报告。
三、实验内容1.编写程序任意输入二叉树的结点个数和结点值,构造一棵二叉树,采用三种递归遍历算法(前序、中序、后序)对这棵二叉树进行遍历并计算出二叉树的高度。
2 .编写程序生成下面所示的二叉树,并采用中序遍历的非递归算法对此二叉树进行遍历。
四、思考与提高1.如何计算二叉链表存储的二叉树中度数为1的结点数?2.已知有—棵以二叉链表存储的二叉树,root指向根结点,p指向二叉树中任一结点,如何求从根结点到p所指结点之间的路径?/*----------------------------------------* 05-1_递归遍历二叉树.cpp -- 递归遍历二叉树的相关操作* 对递归遍历二叉树的每个基本操作都用单独的函数来实现* 水上飘2009年写----------------------------------------*/// ds05.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <iostream>typedef char ElemType;using namespace std;typedef struct BiTNode {ElemType data;//左右孩子指针BiTNode *lchild, *rchild;}BiTNode, *BiTree;//动态输入字符按先序创建二叉树void CreateBiTree(BiTree &T) {char ch;ch = cin.get();if(ch == ' ') {T = NULL;}else {if(ch == '\n') {cout << "输入未结束前不要输入回车,""要结束分支请输入空格!" << endl;}else {//生成根结点T = (BiTNode * )malloc(sizeof(BiTNode));if(!T)cout << "内存分配失败!" << endl;T->data = ch;//构造左子树CreateBiTree(T->lchild);//构造右子树CreateBiTree(T->rchild);}}}//输出e的值ElemType PrintElement(ElemType e) { cout << e << " ";return e;}//先序遍历void PreOrderTraverse(BiTree T) { if (T != NULL) {//打印结点的值PrintElement(T->data);//遍历左孩子PreOrderTraverse(T->lchild);//遍历右孩子PreOrderTraverse(T->rchild);}}//中序遍历void InOrderTraverse(BiTree T) {if (T != NULL) {//遍历左孩子InOrderTraverse(T->lchild);//打印结点的值PrintElement(T->data);//遍历右孩子InOrderTraverse(T->rchild);}}//后序遍历void PostOrderTraverse(BiTree T) { if (T != NULL) {//遍历左孩子PostOrderTraverse(T->lchild);//遍历右孩子PostOrderTraverse(T->rchild);//打印结点的值PrintElement(T->data);}}//按任一种遍历次序输出二叉树中的所有结点void TraverseBiTree(BiTree T, int mark) {if(mark == 1) {//先序遍历PreOrderTraverse(T);cout << endl;}else if(mark == 2) {//中序遍历InOrderTraverse(T);cout << endl;}else if(mark == 3) {//后序遍历PostOrderTraverse(T);cout << endl;}else cout << "选择遍历结束!" << endl;}//输入值并执行选择遍历函数void ChoiceMark(BiTree T) {int mark = 1;cout << "请输入,先序遍历为1,中序为2,后序为3,跳过此操作为0:";cin >> mark;if(mark > 0 && mark < 4) {TraverseBiTree(T, mark);ChoiceMark(T);}else cout << "此操作已跳过!" << endl;}//求二叉树的深度int BiTreeDepth(BiTNode *T) {if (T == NULL) {//对于空树,返回0并结束递归return 0;}else {//计算左子树的深度int dep1 = BiTreeDepth(T->lchild);//计算右子树的深度int dep2 = BiTreeDepth(T->rchild);//返回树的深度if(dep1 > dep2)return dep1 + 1;elsereturn dep2 + 1;}}int _tmain(int argc, _TCHAR* argv[]){BiTNode *bt;bt = NULL; //将树根指针置空cout << "输入规则:" << endl<< "要生成新结点,输入一个字符,""不要生成新结点的左孩子,输入一个空格,""左右孩子都不要,输入两个空格,""要结束,输入多个空格(越多越好),再回车!"<< endl << "按先序输入:";CreateBiTree(bt);cout << "树的深度为:" << BiTreeDepth(bt) << endl;ChoiceMark(bt);return 0;}/*----------------------------------------* 05-2_构造二叉树.cpp -- 构造二叉树的相关操作* 对构造二叉树的每个基本操作都用单独的函数来实现* 水上飘2009年写----------------------------------------*/// ds05-2.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <iostream>#define STACK_INIT_SIZE 100 //栈的存储空间初始分配量#define STACKINCREMENT 10 //存储空间分配增量typedef char ElemType; //元素类型using namespace std;typedef struct BiTNode {ElemType data; //结点值BiTNode *lchild, *rchild; //左右孩子指针}BiTNode, *BiTree;typedef struct {BiTree *base; //在栈构造之前和销毁之后,base的值为空BiTree *top; //栈顶指针int stacksize; //当前已分配的存储空间,以元素为单位}SqStack;//构造一个空栈void InitStack(SqStack &s) {s.base = (BiTree *)malloc(STACK_INIT_SIZE * sizeof(BiTree));if(!s.base)cout << "存储分配失败!" << endl;s.top = s.base;s.stacksize = STACK_INIT_SIZE;}//插入元素e为新的栈顶元素void Push(SqStack &s, BiTree e) {//栈满,追加存储空间if ((s.top - s.base) >= s.stacksize) {s.base = (BiTree *)malloc((STACK_INIT_SIZE+STACKINCREMENT) * sizeof(BiTree));if(!s.base)cout << "存储分配失败!" << endl;s.top = s.base + s.stacksize;s.stacksize += STACK_INIT_SIZE;}*s.top++ = e;}//若栈不空,则删除s的栈顶元素,并返回其值BiTree Pop(SqStack &s) {if(s.top == s.base)cout << "栈为空,无法删除栈顶元素!" << endl;s.top--;return *s.top;}//按先序输入字符创建二叉树void CreateBiTree(BiTree &T) {char ch;//接受输入的字符ch = cin.get();if(ch == ' ') {//分支结束T = NULL;} //if' 'endelse if(ch == '\n') {cout << "输入未结束前不要输入回车,""要结束分支请输入空格!(接着输入)" << endl;} //if'\n'endelse {//生成根结点T = (BiTNode * )malloc(sizeof(BiTree));if(!T)cout << "内存分配失败!" << endl;T->data = ch;//构造左子树CreateBiTree(T->lchild);//构造右子树CreateBiTree(T->rchild);} //Create end}//输出e的值,并返回ElemType PrintElement(ElemType e) {cout << e << " ";return e;}//中序遍历二叉树的非递归函数void InOrderTraverse(BiTree p, SqStack &S) {cout << "中序遍历结果:";while(S.top != S.base || p != NULL) {if(p != NULL) {Push(S,p);p = p->lchild;} //if NULL endelse {BiTree bi = Pop(S);if(!PrintElement(bi->data))cout << "输出其值未成功!" << endl;p = bi->rchild;} //else end} //while endcout << endl;}int _tmain(int argc, _TCHAR* argv[]){BiTNode *bt;SqStack S;InitStack(S);bt = NULL; //将树根指针置空cout << "老师要求的二叉树序列(‘空’表示空格):""12空空346空空空5空空,再回车!"<< endl << "请按先序输入一个二叉树序列(可另输入,但要为先序),""无左右孩子则分别输入空格。
c语言非递归二叉树节点总数解释说明以及概述1. 引言1.1 概述这篇长文将介绍非递归二叉树节点总数的概念、实现方法以及其在应用领域中的重要性。
通过使用C语言编写代码示例,我们将展示如何利用循环迭代来计算二叉树节点的总数。
此外,还会包括一些总结论点,以便更好地理解和应用这个知识。
1.2 文章结构这篇文章分为四个主要部分:引言、非递归二叉树节点总数解释说明、C语言实现非递归二叉树节点总数的代码示例以及结论。
每个部分都会详细说明相关内容,并提供必要的代码示例和解释。
1.3 目的本文旨在帮助读者了解什么是非递归二叉树节点总数,并提供一种使用C语言进行计算的方法。
通过掌握这些概念和技巧,读者可以更好地理解并应用于相关领域,如数据结构和算法设计等。
2. 非递归二叉树节点总数解释说明:2.1 什么是非递归二叉树节点总数:非递归二叉树节点总数指的是在一棵二叉树中,通过使用非递归的方式计算出该二叉树所含有的节点数量。
节点总数是衡量一棵二叉树规模的重要指标之一,对于算法和数据结构的研究和应用具有重要意义。
2.2 实现非递归二叉树节点总数的方法:实现非递归二叉树节点总数可以通过遍历整个二叉树并计算遍历过程中经过的节点个数来实现。
常用的遍历方式包括先序遍历、中序遍历和后序遍历。
在进行非递归遍历时,通常会利用辅助数据结构,如栈或队列来存储待访问的节点,并通过循环迭代的方式完成遍历。
2.3 应用领域和重要性:非递归二叉树节点总数在计算机科学中有着广泛的应用。
它可以被应用于数据分析、图像处理、机器学习等领域。
在对大规模数据进行处理时,使用非递归方法可以提高计算效率,避免了递归调用产生的函数调用开销。
通过准确计算二叉树节点总数,可以更好地评估二叉树结构的复杂度,并对其进行优化。
以上是对非递归二叉树节点总数的解释说明,接下来将通过C语言实现一个非递归二叉树节点总数的代码示例,以进一步说明和展示如何实现该功能。
3. C语言实现非递归二叉树节点总数的代码示例:在这一部分,我们将详细介绍如何使用C语言来实现非递归二叉树节点总数的计算。
一、实验目的选择二叉链式存储结构作为二叉树的存储结构,设计一个程序实现二叉树的基本操作(包括建立、输出、前序遍历、中序遍历、后序遍历、求树高、统计叶子总数等)二、实验开发环境Windows 8.1 中文版Microsoft Visual Studio 6.0三、实验内容程序的菜单功能项如下:1------建立一棵二叉树2------前序遍历递归算法3------前序遍历非递归算法4------中序遍历递归算法5------中序遍历非递归算法6------后序遍历递归算法7------后序遍历非递归算法8------求树高9------求叶子总数10-----输出二叉树11-----退出四、实验分析1、建立一棵二叉树2、输入二叉树各节点数据cout<<"请按正确顺序输入二叉树的数据:";cin.getline(t,1000); //先把输入的数据输入到一个t数组3、递归前序遍历void BL1(ECS_data *t){if(NULL!=t){cout<<t->data<<",";BL1(t->l);BL1(t->r);}}4、非递归前序遍历void preOrder2(ECS_data *t){stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){cout<<p->data<<" ";s.push(p);p=p->l;}if(!s.empty()){p=s.top();s.pop();p=p->r;}}}5、递归中序遍历void BL2(ECS_data *t){if(NULL!=t){BL2(t->l);cout<<t->data<<",";BL2(t->r);}}6、非递归中序遍历void inOrder2(ECS_data *t) //非递归中序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){s.push(p);p=p->l;}if(!s.empty()){p=s.top();cout<<p->data<<" ";s.pop();p=p->r;}}}7、递归后序遍历void BL3(ECS_data *t){if(NULL!=t){BL3(t->l);BL3(t->r);cout<<t->data<<",";}}8、非递归后序遍历void postOrder3(ECS_data *t){stack<ECS_data*> s;ECS_data *cur; //当前结点ECS_data *pre=NULL; //前一次访问的结点s.push(t);while(!s.empty()){cur=s.top();if((cur->l==NULL&&cur->r==NULL)||(pre!=NULL&&(pre==cur->l||pre==cur->r))){cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过s.pop();pre=cur;}else{if(cur->r!=NULL)s.push(cur->r);if(cur->l!=NULL)s.push(cur->l);}}}9、求树高int Height (ECS_data *t){if(t==NULL) return 0;else{int m = Height ( t->l );int n = Height(t->r);return (m > n) ? (m+1) : (n+1);}}10、求叶子总数int CountLeaf(ECS_data *t){static int LeafNum=0;//叶子初始数目为0,使用静态变量if(t)//树非空{if(t->l==NULL&&t->r==NULL)//为叶子结点LeafNum++;//叶子数目加1else//不为叶子结点{CountLeaf(t->l);//递归统计左子树叶子数目CountLeaf(t->r);//递归统计右子树叶子数目}}return LeafNum;}五、运行结果附:完整程序源代码://二叉树链式存储的实现#include<iostream>#include<cstring>#include <stack>using namespace std;struct ECS_data //先定义好一个数据的结构{char data;ECS_data *l;ECS_data *r;};class ECS{private://int level; //树高int n; //表示有多少个节点数int n1; //表示的是数组的总长度值,(包括#),因为后面要进行删除判断ECS_data *temp[1000];public:ECS_data *root;ECS() //初始化{ECS_data *p;char t[1000];int i;int front=0,rear=1; //front表示有多少个节点,rear表示当前插入的点的父母cout<<"请按正确顺序输入二叉树的数据:";cin.getline(t,1000); //先把输入的数据输入到一个t数组//cout<<t<<" "<<endl;int n1=strlen(t); //测量数据的长度n=0;for(i=0;i<n1;i++){if(t[i]!='#'){p=NULL;if(t[i]!=',') //满足条件并开辟内存{n++;p=new ECS_data;p->data=t[i];p->l=NULL;p->r=NULL;}front++;temp[front]=p;if(1 == front){root=p;}else{if((p!=NULL)&&(0==front%2)){temp[rear]->l=p;//刚开始把这里写成了==}if((p!=NULL)&&(1==front%2)){temp[rear]->r=p;}if(1==front%2)rear++; //就当前的数据找这个数据的父母}}}}~ECS() //释放内存{int i;for(i=1;i<=n;i++)if(temp[i]!=NULL)delete temp[i];}void JS() //记录节点的个数{int s;s=n;cout<<"该二叉树的节点数为:"<<s<<endl;}void BL1(ECS_data *t)//递归前序遍历{if(NULL!=t){cout<<t->data<<",";BL1(t->l);BL1(t->r);}}void preOrder2(ECS_data *t) //非递归前序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){cout<<p->data<<" ";s.push(p);p=p->l;}if(!s.empty()){p=s.top();s.pop();p=p->r;}}}void BL2(ECS_data *t)//递归中序遍历{if(NULL!=t){BL2(t->l);cout<<t->data<<",";BL2(t->r);}}void inOrder2(ECS_data *t) //非递归中序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){s.push(p);p=p->l;}if(!s.empty()){p=s.top();cout<<p->data<<" ";s.pop();p=p->r;}}}void BL3(ECS_data *t)//递归后序遍历{if(NULL!=t){BL3(t->l);BL3(t->r);cout<<t->data<<",";}}void postOrder3(ECS_data *t) //非递归后序遍历{stack<ECS_data*> s;ECS_data *cur; //当前结点ECS_data *pre=NULL; //前一次访问的结点s.push(t);while(!s.empty()){cur=s.top();if((cur->l==NULL&&cur->r==NULL)||(pre!=NULL&&(pre==cur->l||pre==cur->r))){cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过s.pop();pre=cur;}else{if(cur->r!=NULL)s.push(cur->r);if(cur->l!=NULL)s.push(cur->l);}}}int Height (ECS_data *t) //求树高{if(t==NULL) return 0;else{int m = Height ( t->l );int n = Height(t->r);return (m > n) ? (m+1) : (n+1);}}int CountLeaf(ECS_data *t) //求叶子总数{static int LeafNum=0;//叶子初始数目为0,使用静态变量if(t)//树非空{if(t->l==NULL&&t->r==NULL)//为叶子结点LeafNum++;//叶子数目加1else//不为叶子结点{CountLeaf(t->l);//递归统计左子树叶子数目CountLeaf(t->r);//递归统计右子树叶子数目}}return LeafNum;}};int main(){ECS a;a.JS();cout<<"递归前序遍历:";a.BL1(a.root);cout<<endl;cout<<"非递归前序遍历:";a.preOrder2(a.root);cout<<endl;cout<<"递归中序遍历:";a.BL2(a.root);cout<<endl;cout<<"非递归中序遍历:";a.inOrder2(a.root);cout<<endl;cout<<"递归后序遍历:";a.BL3(a.root);cout<<endl;cout<<"非递归后序遍历:";a.postOrder3(a.root);cout<<endl;cout<<"树高为:"<<a.Height(a.root)<<endl;cout<<"叶子总数为:"<<a.CountLeaf(a.root)<<endl;return 0;}。
golang 中序遍历递归非递归中序遍历是二叉树遍历的一种方式,以左子树、根节点、右子树的顺序访问节点。
在Golang中,我们可以使用递归和非递归两种方式实现中序遍历。
一、递归实现中序遍历递归实现中序遍历是最简单直观的方式。
我们可以定义一个递归函数,用于按中序遍历访问树的节点。
```gopackage mainimport "fmt"type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode}func inorderTraversal(root *TreeNode) {if root != nil {inorderTraversal(root.Left)fmt.Printf("%d ", root.Val)inorderTraversal(root.Right)}}func main() {// 构造一棵二叉树root := &TreeNode{Val: 1}root.Left = &TreeNode{Val: 2}root.Right = &TreeNode{Val: 3}root.Left.Left = &TreeNode{Val: 4}root.Left.Right = &TreeNode{Val: 5}fmt.Println("中序遍历结果:")inorderTraversal(root)}```以上代码中,我们先构造了一棵二叉树,然后调用`inorderTraversal`函数进行中序遍历。
递归函数首先检查根节点是否为空,如果不为空,则按照左子树、根节点、右子树的顺序递归调用自身。
二、非递归实现中序遍历非递归实现中序遍历使用栈来模拟递归的过程。
具体实现过程如下:```gopackage mainimport "fmt"type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode}func inorderTraversal(root *TreeNode) { stack := []*TreeNode{}cur := rootfor len(stack) > 0 || cur != nil {for cur != nil {stack = append(stack, cur)cur = cur.Left}cur = stack[len(stack)-1]stack = stack[:len(stack)-1]fmt.Printf("%d ", cur.Val)cur = cur.Right}}func main() {// 构造一棵二叉树root := &TreeNode{Val: 1}root.Left = &TreeNode{Val: 2}root.Right = &TreeNode{Val: 3}root.Left.Left = &TreeNode{Val: 4}root.Left.Right = &TreeNode{Val: 5}fmt.Println("中序遍历结果:")inorderTraversal(root)}```以上代码中,我们定义了一个栈和一个指针`cur`,其中栈用于存储遍历过程中的节点。
二叉树节点个数非递归算法二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。
在二叉树中,节点的个数是非常重要的一个指标,它反映了二叉树的规模大小。
本文将介绍一种非递归算法,用于计算二叉树的节点个数。
为了清晰地展示算法的思路和实现过程,先来定义二叉树节点的数据结构。
一个二叉树节点包含三个属性:值、左子节点和右子节点。
下面是对应的C++代码:```struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}};```现在我们来介绍算法的实现。
为了计算二叉树的节点个数,我们可以使用广度优先搜索(BFS)的方式遍历整棵树。
具体步骤如下:1. 首先,我们定义一个队列,用于存储待遍历的节点。
将根节点入队。
2. 然后,进入一个循环,直到队列为空。
在循环中,依次执行以下操作:- 弹出队首节点,并将其计数器加1。
- 检查弹出的节点是否有左子节点,如果有,则将左子节点入队。
- 检查弹出的节点是否有右子节点,如果有,则将右子节点入队。
3. 当队列为空时,遍历结束。
此时的计数器就是二叉树的节点个数。
下面是对应的C++代码实现:```cppint countNodes(TreeNode* root) {if (root == nullptr) {return 0;}int count = 0;queue<TreeNode*> q;q.push(root);while (!q.empty()) {TreeNode* node = q.front();q.pop();count++;if (node->left) {q.push(node->left);}if (node->right) {q.push(node->right);}}return count;}```通过这个非递归算法,我们可以高效地计算二叉树的节点个数。
二叉树后序遍历的非递归算法
二叉树后序遍历是指按照左子树、右子树、根节点的顺序遍历二叉树的过程。
与前序遍历和中序遍历不同,后序遍历需要考虑根节点的位置,因此需要使用栈来存储节点信息。
非递归算法一般使用栈来实现,因为后序遍历的过程中需要先遍历左子树和右子树,最后才遍历根节点,所以存储节点信息的栈需要进行一些特殊处理。
下面是二叉树后序遍历的非递归算法:
1. 创建一个空栈,并将根节点入栈。
2. 创建一个辅助变量pre表示上一个被遍历的节点。
3. 当栈不为空时,取出栈顶元素top,判断它是否为叶子节点或者它的左右子节点都被遍历过了(被遍历过的节点可以通过辅助变量pre来判断)。
4. 如果top为叶子节点或者它的左右子节点都被遍历过了,则将top出栈,并将它的值输出。
5. 如果不满足条件3,判断top的右子节点是否为pre,如果是,则说明右子树已经遍历完了,此时可以直接输出top的值,并将top出栈;如果不是,则将top的右子节点入栈。
6. 将top的左子节点入栈。
7. 将上一个被遍历的节点pre更新为top。
根据这个算法,我们可以分别对左子树和右子树进行遍历,并保证根节点最后被遍历到,从而实现二叉树的后序遍历。
这个算法的时间复杂度为O(n),空间复杂度为O(n)。
总的来说,二叉树的后序遍历是一种比较复杂的遍历方式,需要使用栈保存节点信息,并且需要特殊处理根节点的位置。
使用非递归算法实现后序遍历可以优化空间复杂度和避免栈溢出的问题。
二叉树非递归实现#include<iostream>
#include<stdlib.h>
using namespace std;
typedef char ElemType;
typedef struct Bintree
{
ElemType data;
struct Bintree *lc,*rc;
}Bintree,*BT;
Bintree *Create(BT &T)
{
char c;
cin>>c;
if(c=='*') T=NULL;
else
{
if(!(T=(Bintree *)malloc(sizeof(Bintree)))) exit(-1);
T->data=c;
Create(T->lc);
Create(T->rc);
}
return T;
}
void PreOrder(BT T)
{
Bintree *stack[20],*p;
int top=-1;
if(T!=NULL)
{
top++;
stack[top]=T;
while(top>-1)
{
p=stack[top];
top--;
cout<<p->data;
if(p->rc!=NULL)
{
top++;
stack[top]=p->rc;
}
if(p->lc!=NULL)
top++;
stack[top]=p->lc;
}
}
}
}
void MidOrder(BT T)
{
Bintree *stack[20],*p;
int top=-1;
if(T!=NULL)
{
p=T;
while(top>-1||p!=NULL)
{
while(p!=NULL)
{
top++;
stack[top]=p;
p=p->lc;
}
if(top>-1)
{
p=stack[top];
top--;
cout<<p->data;
p=p->rc;
}
}
}
}
void PostOrder(BT T)
{
Bintree *stack[20],*p;
int sign,top=-1;
if(T!=NULL)
{
do{
while(T!=NULL)
{
top++;
stack[top]=T;
T=T->lc;
p=NULL;
sign=1;
while(top!=-1&&sign)
{
T=stack[top];
if(T->rc==p)
{
cout<<T->data;
top--;
p=T;
}
else
{
T=T->rc;
sign=0;
}
}
}while(top!=-1);
}
}
int main()
{
BT T;
cout<<"输入字符,先序建立二叉树:"<<endl;
T=Create(T);
cout<<"二叉树的先序遍历为:"<<endl;
PreOrder(T);
cout<<endl;
cout<<"二叉树的中序遍历为:"<<endl;
MidOrder(T);
cout<<endl;
cout<<"二叉树的后序遍历为:"<<endl;
PostOrder(T);
return 0;
}
认真看,静下心来看懂后才发现前辈们真的很有才华,思维真的很严谨。