递归非递归的二叉树遍历(递归前中后,非递归前中后,层次遍历,凹入打印法等)

由于所有的递归算法都可以借助于堆栈转换成循环结构的非递归算法。方法一:形式化模拟转换。方法二:根据要求解问题的特点设计借助于堆栈的循环结构算法。而此次正好是利用第二种按方法求解。


1.1非递归前序遍历:

首先利用下图来设计非递归前序遍历算法思想:

堆栈结构体如下:

#define size 100
typedef struct
{
     DataType  data[size];
     int tag[100];     //这个是在非递归后序中用到
     int top ;
}SeqStack ;

(1)初始化设置一个堆栈。

(2)把根结点指针入栈。

(3)当堆栈非空,循环执行步骤①到步骤③:

①出栈取得一个结点指针,访问该结点;

②若该结点的右子树非空,则将该结点的右子树指针入栈;

③若该结点的左子树非空,则将该结点的左子树指针入栈;

void preOrder2(BiTreeNode *root)
{
    BiTreeNode *t;
    SeqStack S;          //定义一个顺序堆栈
    StackInitiate(S);
    StackPush(&S,root);
    while(StackNotEmpty(S)!=NULL)
    {
        SatckPop(&S,&t);           //出栈访问
        printf("%3c",t->data);
        if(root->rightChild!=NULL)   //右孩子非空,右孩子入栈
        {
            SatckPush(&S,root->rightChild);
        }
        if(root->leftChild!=NULL)   //左孩子非空,左孩子入栈
        {
            StackPush(&S,root->leftChild);
        }
    }
}

1.2递归法前序遍历

递归法先序遍历思想:

若二叉树为空,则算法结束;否则:

①访问根结点;

②先序遍历根结点的左子树;

③先序遍历根结点的右子树

void PreOrder(BiTreeNode *root)
{
    if(root!=NULL)            //二叉树非空
    {
        printf("%c ",root->data);    //访问根结点;
        PreOrder(root->leftChild);   //先序遍历根结点的左子树
        PreOrder(root->rightChild);  //先序遍历根结点的右子树
    }
}

1.3层次遍历(与前序遍历基本相同,就是前序使用堆栈,层次遍历使用队列)

void LayOrder(BiTreeNode *root)           //层次遍历
{
    BiTreeNode *d;
    SeqCQueue Q;
    QueueInitiate(&Q);
    QueueAppend(&Q,root);
    while(QueueNotEmpty(Q))
    {
        QueueDelete(&Q,&d);
        printf("%3c",d->data);
        if(d->leftChild) QueueAppend(&Q,d->leftChild);
        if(d->rightChild) QueueAppend(&Q,d->rightChild);
    }

}

2.1非递归法中序遍历

利用下图来设计非递归中序遍历算法思想:

堆栈结构体如下:

#define size 100
typedef struct
{
     DataType  data[size];
     int tag[100];     //这个是在非递归后序中用到
     int top ;
}SeqStack ;

(1)初始化设置一个堆栈。

(2)把根结点指针入栈。

(3)当堆栈非空或则指针t非空,循环执行步骤①到步骤③:

①若指针t非空,则将t入栈,一直遍历其左孩子;

②若堆栈非空,则弹出栈顶元素并访问,并指向其右孩子;

void InOrder(BiTreeNode *root)
{
    BiTreeNode *t;
    SeqStack S;
    StackInitiate(&S);
    StackPush(&S,root);
    t=root->leftChld;
    while(StackNotEmpty(S)!=NULL||t!=NULL)    //当堆栈非空或则指针t非空
    {
        while(t!=NULL)
        {
            StackPush(&S,t);     //t入栈
            t=t->leftChild;      //遍历其左孩子
        }
        if(StackNotEmpty(S))
        {
            StackPop(&S,&t);    //弹出栈顶元素并访问,并指向其右孩子
            printf("%c",t->data);
            t=t->rightChild;
        }
    }
}

2.2二叉树的中序递归算法

递归法中序遍历思想:

若二叉树为空,则算法结束;否则:

①中序遍历根结点的左子树;

②访问根结点;

③中序遍历根结点的右子树

void InOrder(BiTreeNode *root)
{
    if(root!=NULL)      //二叉树非空
    {
        InOrder(root->leftChild);    //先序遍历根结点的左子树
        printf("%c",root->data);      //访问根结点;
        InOrder(root->rightChild);    //先序遍历根结点的右子树
    }
}

3.1二叉树的后序非递归遍历算法

后序遍历算法要明白的是,当访问结点的左子树是,该结点标志位0,之后获取(非弹出栈中的结点),访问其右子树,这是标志位为1.

void PostOrder2(BiTreeNode *root)
{
    SeqStack S;
    StackInitiate(&S);
    while((root!=NULL)||StackNotEmpty(S))
    {
        while(root)
        {
            StackPush(&S,root);       //访问结点的左子树时,tag为0
            S.tag[S.top]=0;
            root=root->leftChild;
        }

        while((StackNotEmpty(S))&&(S.tag[S.top]==1))
        {
            StackPop(&S,&root);
            printf("%3c",root->data);
        }
        if(StackNotEmpty(S))
        {
            StackTop(S,&root);      //获取栈顶元素
            S.tag[S.top]=1;         //tag为1
                root= root->rightChild;

        }
        else root=NULL;
    }
}

由于后序遍历的算法叫其他的遍历难,所以一定得自己画图,边体会代码的运行过程

3.2二叉树的递归后序

递归法后序遍历思想:

若二叉树为空,则算法结束;否则:

①后序遍历根结点的左子树;

②后序序遍历根结点的右子树;

③访问根结点

void PostOrder(BiTreeNode *root)
{
    if(root!=NULL)      //二叉树非空
    {
        InOrder(root->leftChild);    //先序遍历根结点的左子树
        InOrder(root->rightChild);    //先序遍历根结点的右子树
        printf("%c",root->data);      //访问根结点;
    }
}

4应用

main函数

#include<stdlib.h>
#include<stdio.h>
typedef char DataType;
#define MaxQueueSize 100
#define MaxStackSize 100
#include"BiTree.h"
#include"Queue.h"
#include"SeqStack.h"
#include"BiTreeTraverse.h"

void Visit(DataType item)        //用来输出字符,就是个printf语句
{
    printf("%c ",item);
}

void PrintBiTree(BiTreeNode *root,int n)     //打印二叉树,这里使用的是凹入表示法
{
    int i;
    if(root==NULL) return;
    PrintBiTree(root->rightChild,n+1);
    for(i=0;i<n-1;i++) printf("  ");
    if(n>0)
    {
        printf("---");
        printf("%c\n",root->data);
    }
    PrintBiTree(root->leftChild,n+1);
}

BiTreeNode *Search(BiTreeNode *root,DataType x)        //查找二叉树的某一个字符是否在该树种
{
    BiTreeNode *find=NULL;
    if(root!=NULL)
    {
        if(root->data==x)
            find=root;
        else
        {
            find=Search(root->leftChild,x);
            if(find==NULL)
                find=Search(root->rightChild,x);
        }
    }
    return find;
}

main()
{
    BiTreeNode *root,*p,*find;
    char x=‘E‘;
    Initiate(&root);
    p=InsertLeftNode(root,‘A‘);
    p=InsertLeftNode(p,‘B‘);
    p=InsertLeftNode(p,‘D‘);
    p=InsertRightNode(p,‘G‘);
    p=InsertRightNode(root->leftChild,‘C‘);
    InsertLeftNode(p,‘E‘);
    InsertRightNode(p,‘F‘);
    PrintBiTree(root,0);
    printf("前序遍历:");
    PreOrder(root->leftChild,Visit);
    printf("\n中序遍历:");
    InOrder(root->leftChild,Visit);
    printf("\n后序遍历:");
    PostOrder(root->leftChild,Visit);
    printf("\n非递归前序遍历:");
    PreOrder2(root->leftChild);
    printf("\n非递归中序遍历:");
    InOrder2(root->leftChild);
    printf("\n非递归后序遍历:");
    PostOrder2(root->leftChild);
    printf("\n层次遍历:");
    LayOrder(root->leftChild);
    find=Search(root,x);
    if(find!=NULL)
        printf("\n数据元素%c在二叉树中\n",x);
    else
        printf("\n数据元素%c不在二叉树中\n",x);
    Destroy(&root);
}

队列

typedef struct
{
    BiTreeNode *queue[MaxQueueSize];
    int rear;
    int front;
    int count;
}SeqCQueue;

void QueueInitiate(SeqCQueue *Q)
{
    Q->rear=0;
    Q->front=0;
    Q->count=0;
}

int QueueNotEmpty(SeqCQueue Q)
{
    if(Q.count!=0) return 1;
    else return 0;
}

int QueueAppend(SeqCQueue *Q,BiTreeNode *x)
{
    if(Q->count>0&&Q->rear==Q->front)
    {
        printf("队列已满无法插入!\n");
        return 0;
    }
    else
    {
        Q->queue[Q->rear]=x;
        Q->rear=(Q->rear+1)%MaxQueueSize;
        Q->count++;
        return 1;
    }
}

int QueueDelete(SeqCQueue *Q,BiTreeNode **d)
{
    if(Q->count==0)
    {
        printf("队列已空无数据元素出队列!\n");
        return 0;
    }
    else
    {
        *d=Q->queue[Q->front];
        Q->front=(Q->front+1)%MaxQueueSize;
        Q->count--;
        return 1;
    }
}

堆栈

typedef struct
{
    BiTreeNode *stack[MaxStackSize];
    int tag[100];
    int top;       //top表示顺序堆栈数组stack的当前栈顶位置
}SeqStack;

void StackInitiate(SeqStack *S)
{
    S->top=0;    //初始化栈顶下标值
}

int StackNotEmpty(SeqStack S)  //判断顺序堆栈S是否为空,非空返回1,否则返回0
{
    if(S.top<=0)return 0;
    else return 1;
}

int StackPush(SeqStack *S,BiTreeNode *x)//把数据元素x存入顺序堆栈S中,入栈成功返回1,否则返回0
{
    if(S->top>=MaxStackSize)
    {
        printf("堆栈已满,无法插入!\n");
        return 0;
    }
    else
    {
        S->stack[S->top]=x;
        S->top++;
        return 1;
    }
}

int StackPop(SeqStack *S,BiTreeNode **d) //取出顺序堆栈S的栈顶元素值由参数d带回,出栈成功则返回1,否则返回0
{
    if(S->top<=0)
    {
        printf("堆栈已空无数据元素出栈!\n");
        return 0;
    }
    else
    {
        S->top--;        //得注意top--,--top的差别
        *d=S->stack[S->top];
        return 1;
    }
}

 int StackTop(SeqStack S,BiTreeNode **d) //取栈顶数据元素值由参数d带回,成功返回1,不成功返回0
{
        if(S.top<=0)
        {
            printf("堆栈已空!\n");
            return 0;
        }
        else
        {
            *d=S.stack[S.top-1];
            return 1;
        }
}

树的遍历等函数BiTreeTraverse.h

void PreOrder(BiTreeNode *root,void visit(DataType item))    //递归前序遍历
{
    if(root!=NULL)
    {
        visit(root->data);
        PreOrder(root->leftChild,visit);
        PreOrder(root->rightChild,visit);
    }
}

void InOrder(BiTreeNode *root,void visit(DataType item))     //递归中序遍历
{
    if(root!=NULL)
    {
        InOrder(root->leftChild,visit);
        visit(root->data);
        InOrder(root->rightChild,visit);
    }
}

void PostOrder(BiTreeNode *root,void visit(DataType item))     //递归后序遍历
{
    if(root!=NULL)
    {
        PostOrder(root->leftChild,visit);
        PostOrder(root->rightChild,visit);
        visit(root->data);
    }
}

void InOrder2(BiTreeNode *root)             //非递归中序遍历
{
    BiTreeNode *t;
    SeqStack S;
    StackInitiate(&S);
    StackPush(&S,root);
    t=root->leftChild;
    while(StackNotEmpty(S)||t!=NULL)
    {
        while(t!=NULL)
        {
            StackPush(&S,t);
            t=t->leftChild;
        }
        if(StackNotEmpty(S))
        {
            StackPop(&S,&t);
            printf("%3c",t->data);
            t=t->rightChild;
        }
    }
}

void PreOrder2(BiTreeNode *root)      //非递归中序遍历
{
    BiTreeNode *t;
    SeqStack S;
    StackInitiate(&S);
    StackPush(&S,root);
    while(StackNotEmpty(S))
    {
        StackPop(&S,&t);
        printf("%3c",t->data);
        if(t->rightChild!=NULL)
        {
            StackPush(&S,t->rightChild);
        }
        if(t->leftChild!=NULL)
        {
            StackPush(&S,t->leftChild);
        }
    }
}

void PostOrder2(BiTreeNode *root)    //非递归后序遍历
{
    SeqStack S;
    StackInitiate(&S);
    while((root!=NULL)||StackNotEmpty(S))
    {
        while(root)
        {
            StackPush(&S,root);
            S.tag[S.top]=0;
            root=root->leftChild;
        }

        while((StackNotEmpty(S))&&(S.tag[S.top]==1))
        {
            StackPop(&S,&root);
            printf("%3c",root->data);
        }
        if(StackNotEmpty(S))
        {
            StackTop(S,&root);
            S.tag[S.top]=1;
                root= root->rightChild;

        }
        else root=NULL;
    }
}

void LayOrder(BiTreeNode *root)           //层次遍历
{
    BiTreeNode *d;
    SeqCQueue Q;
    QueueInitiate(&Q);
    QueueAppend(&Q,root);
    while(QueueNotEmpty(Q))
    {
        QueueDelete(&Q,&d);
        printf("%3c",d->data);
        if(d->leftChild) QueueAppend(&Q,d->leftChild);
        if(d->rightChild) QueueAppend(&Q,d->rightChild);
    }

}

二叉树创建BiTree.h

typedef struct Node       //结构体的定义
{
    DataType data;
    struct Node *leftChild;
    struct Node *rightChild;
} BiTreeNode;

void Initiate(BiTreeNode **root)       //初始化
{
    *root=(BiTreeNode *)malloc(sizeof(BiTreeNode));
    (*root)->leftChild=NULL;
    (*root)->rightChild=NULL;
}

BiTreeNode *InsertLeftNode(BiTreeNode *curr,DataType x)    //左插入结点
{
    BiTreeNode *s,*t;
    if(curr==NULL) return NULL;
    t=curr->leftChild;
    s=(BiTreeNode *)malloc(sizeof(BiTreeNode));
    s->data=x;
    s->leftChild=t;
    s->rightChild=NULL;
    curr->leftChild=s;
    return curr->leftChild;
}

BiTreeNode *InsertRightNode(BiTreeNode *curr,DataType x)    //右插入结点
{
    BiTreeNode *s,*t;
    if(curr==NULL) return NULL;
    t=curr->rightChild;
    s=(BiTreeNode *)malloc(sizeof(BiTreeNode));
    s->data=x;
    s->rightChild=t;
    s->leftChild=NULL;
    curr->rightChild=s;
    return curr->rightChild;
}

void Destroy(BiTreeNode **root)               //撤销二叉树
{
    if((*root)!=NULL&&(*root)->leftChild!=NULL)
        Destroy(&(*root)->leftChild);
    if((*root)!=NULL&&(*root)->rightChild!=NULL)
        Destroy(&(*root)->rightChild);
    free(*root);
}

BiTreeNode *DeleteLeftTree(BiTreeNode *curr)        //左删除子树
{
    if(curr==NULL||curr->leftChild==NULL) return NULL;
    Destroy(&curr->leftChild);
    curr->leftChild=NULL;
    return curr;
}

BiTreeNode *DeleteRightTree(BiTreeNode *curr)       //右删除子树
{
    if(curr==NULL||curr->rightChild==NULL) return NULL;
    Destroy(&curr->rightChild);
    curr->rightChild=NULL;
    return curr;
}

【程序运行结果】

以上内容参考《数据结构——使用C语言(第五版)》,可能有些地方解释的不太清楚,欢迎指出

时间: 2024-11-15 16:55:28

递归非递归的二叉树遍历(递归前中后,非递归前中后,层次遍历,凹入打印法等)的相关文章

采用先序遍历 和层次遍历递归建立二叉树--进行封装

1 package com.offer; 2 3 public class TreeNode { 4 5 int val = 0; 6 TreeNode left = null; 7 TreeNode right = null; 8 9 public TreeNode(int val) 10 { 11 this.val=val; 12 } 13 14 public TreeNode() 15 { 16 CreateBinaryTree();// 采用默认的 17 //preShow(this.r

二叉树的前中后以及层次遍历

#include "stdio.h" #include "malloc.h" #define datatype char  typedef struct bT { datatypedata; struct bT *lt,*rt; }* bitree,BiNode; void preExCreate(bitree bt); /*递归实现*/ void FprePost(bitree bt) { if(bt) { printf("%c",bt->

非递归算法实现二叉树高度

思路: 嘻嘻,请读者自己手动模拟.博主这里不知道怎么用语言说. 拓展: 算法思路适用于 (1)每层的结点个数 (2)树的最大宽度 (3)节点位于某一层 int height(BiTree T){ if(T==null) return 0; int front=-1, rear=-1;//front 出队指针 rear 入队指针 int last = 0, level=0;//last 每一层的最右指针(front==last时候一层遍历结束 level++) BiTree Q[Maxsize];

LeetCode 第103题 二叉树的锯齿形层次遍历

给定一个二叉树,返回其节点值的锯齿形层次遍历.(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行). 例如:给定二叉树 [3,9,20,null,null,15,7], 3 / 9 20 / 15 7 返回锯齿形层次遍历如下: [ [3], [20,9], [15,7] ] 思路: 与层次遍历类似,可以直接将特定层次的结果倒置 1 class Solution103 { 2 3 public List<List<Integer>> zigzagLevelOrde

树——二叉树的层次遍历

1,二叉树的遍历: 1,二叉树的遍历(Traversing Binary Tree)是指从根结点出发,按照某种次序依次访问二叉树中的所有结点,使得每个结点被访问一次,且仅被访问一次: 1,层次就是访问的次序,层次遍历是先访问第一层.再第二层等: 2,考虑的问题: 1,通用树结构的层次遍历算法是否可以用在二叉树结构上?如果可以,代码需要做怎样的改动? 1,可以的,二叉树是一种特别的树: 2,通用树使用的算法可以移植到二叉树使用的场合: 3,设计思路(游标): 1,提供一组遍历相关的函数,按层次访问

二叉树遍历算法——包含递归前、中、后序和层次,非递归前、中、后序和层次遍历共八种

首先,要感谢网上的参考资料. http://mengliao.blog.51cto.com/876134/1178079(作者:BlackAlpha) http://blog.csdn.net/fzh1900/article/details/14056735(作者:_云淡风轻) http://blog.csdn.net/stpeace/article/details/8138458(作者:stpeace) 二叉树是使用的比较广泛的一种数据结构,这里我写了二叉树的相关操作,包括初始化.新建.以及遍

二叉树的前中后序递归和非递归遍历操作【代码】

“遍历”是二叉树各种操作的基础,可以在遍历过程中对节点进行各种操作,如:求节点的双亲,求节点的孩子,判断节点的层次,当然,还有一些更重要的操作,例如,依据遍历序列建立二叉树,,再如,对建立的二叉树进行线索化,等等. 二叉树的各种遍历操作必须了然于心,无论是递归的,还是非递归的.递归算法的优点是形式简单,当然,正如一句话所说“迭代是人,递归是神.”递归算法的整个详细过程还是很烧脑的,每一步都把未知当作已知,每一步又在把未知变为已知.想不到描述起来又用上了递归的概念,生活中其实有很多递归的现象,我印

数据结构二叉树——建立二叉树、中序递归遍历、非递归遍历、层次遍历

数据结构二叉树-- 编写函数实现:建立二叉树.中序递归遍历.借助栈实现中序非递归遍历.借助队列实现层次遍历.求高度.结点数.叶子数及交换左右子树. ("."表示空子树) #include<stdio.h> #include<stdlib.h> //***********二叉树链表节点结构 typedef char DataType; typedef struct Node {  DataType data;  struct Node*LChild;  struc

二叉树的建立、三种(递归、非递归)遍历方法

二叉树定义: 1.有且仅有一个特定的称之为根root的结点 2.当n>1时,除根结点之外的其余结点分为两个互不相交的子集.他们称为二叉树的左子树和右子树. 二叉树的一种建立方法: 若对有n个结点的完全二叉树进行顺序编号(1<=i<=n),那么,对于编号为i(i>=1)的结点. 当i=1时,该结点为根,它无双亲结点; 当i>1时,该节点的双亲编号为[i/2]; 若2i<=n,该结点为编号为2i的左孩子,否则没有左孩子 当2i+1<=n,该结点有编号为2i+1的右孩子