建立二叉树,实现二叉树的先序遍历、中序和后序遍历的非递归算法

先序遍历:若二叉树为空,则空操作;否则访问根节点;先序遍历左子树;先序遍历右子树。
中序遍历:若二叉树为空,则空操作;否则中序遍历左子树;访问根节点;中序遍历右子树。
后序遍历:若二叉树为空,则空操作;否则后序遍历左子树;后序遍历右子树;访问根节点。

/*
* Created by Microsoft Visual Studio 2013
* @author: Teresa
* @date: 2017-10-22
* @description: 二叉树遍历 非递归 
*/

#include <stdio.h>
#include <stdlib.h>
/*函数状态码*/
#define TRUE 1	//成功
#define OK 1
#define FALSE 0	//失败 
#define ERROR 0	//错误 
#define INFEASIBLE -1	//不可行的
#define OVERFLOW -2 	//溢出

typedef int Status;	//函数的返回值类型 
 
//二叉树的二叉链表存储表示
typedef char TElemType;
typedef struct BiNode{
    TElemType data;
    struct BiNode *lchild, *rchild;
} BiNode , *BiTree;
 
//栈的顺序存储结构
#define STACK_INIT_SIZE 100      //存储空间初始分配量
#define STACKINCREMENT 10       //存储空间分配增量
 
typedef struct{
    BiTree *base;
    BiTree *top;
    int stacksize;
} Stack;

//初始化栈
Status InitStack(Stack *s){
    s->base = (BiTree*)malloc(sizeof(BiTree)*STACK_INIT_SIZE);
    s->top = s->base;
    s->stacksize = STACK_INIT_SIZE;
    return OK;
}

//判断栈是否为空
Status StackEmpty(Stack *s){
    if (s->base == s->top)
        return OK;
    return ERROR;
}
 
//获得栈顶元素
Status GetTop(Stack *s, BiTree *c){
    if (StackEmpty(s))
        return ERROR;
    *c = *(s->top - 1);
    return OK;
}
 

//进栈
Status Push(Stack *s, BiTree c)
{
    //如果空间不够,增加空间的分配
    if (s->top - s->base >= s->stacksize){
        s->base = (BiTree*)realloc(s->base, sizeof(BiTree)*(s->stacksize + STACKINCREMENT));
        s->stacksize = s->stacksize + STACKINCREMENT;
    }
 
    *(s->top++) = c;
    return OK;
}
 
//出栈
Status Pop(Stack *s, BiTree *c){
    if (StackEmpty(s))
        return ERROR;
    *c = *(--s->top);
    return OK;
}
 
//遍历数据元素时所调用函数
Status PrintElement(TElemType e){
    putchar(e);
    return OK;
}
  

//按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树,构造二叉链表表示的二叉树T。
Status CreatBiTree(BiTree *T){
    char ch;
    scanf("%c", &ch);
 
    //如果当前输入的字符为空格,则(*T)指向空树。
    if (ch == ' '){
        (*T) = NULL;
    }
    else{
        if (!((*T) = (BiTree)malloc(sizeof(BiNode))))
            exit(OVERFLOW);
        (*T)->data = ch;             //生成根结点
        CreatBiTree(&((*T)->lchild));    //构造左子树
        CreatBiTree(&((*T)->rchild));    //构造右子树
    }
    return OK;
}

 
//先序遍历二叉树,非递归算法。
Status PreOrderTraverse_NonRecursive(BiTree T, Status(*Visit)(TElemType e)){
    Stack *S;   //栈S中存储指向树结点的指针。
    BiTree p;
    S = (Stack*)malloc(sizeof(Stack));
    InitStack(S);
    Push(S, T); //根指针进栈。
    while (!StackEmpty(S)){
        //获取栈顶指针,如果栈顶指针不为空,访问该结点。并将该结点的左子树进栈。
        if (GetTop(S, &p) && p){
            if (!Visit(p->data))
                return ERROR;
            Push(S, p->lchild);
        }
        //栈顶指针为空,表明之前压入的左子树或者右子树为空。
        else{
            Pop(S, &p); //空指针退栈
            if (!StackEmpty(S)){
                Pop(S, &p); //已被访问过的根结点退栈。此时,该退栈结点的左子树已被全部访问过。
                Push(S, p->rchild);  //右子树进栈。
            }
        }
    }
    return OK;
}
 
 
//采用二叉链表存储结构,Visit是对数据元素进行操作的应用函数,
//中序遍历二叉树的非递归算法,对每个数据元素调用函数Visit。
Status InOrderTraverse_NonRecursive(BiTree T, Status(*Visit)(TElemType e)){
    Stack *S;
    BiTree p;
    S = (Stack *)malloc(sizeof(Stack));
    InitStack(S);
    Push(S, T); //根指针进栈
    while (!StackEmpty(S)){
        //向左走到尽头
        while (GetTop(S, &p) && p){
            Push(S, p->lchild);
        }
 
        //空指针退栈
        Pop(S, &p);
        //访问节点,并向右一步
        if (!StackEmpty(S)){
            Pop(S, &p);
            if (!Visit(p->data))
                return ERROR;
            Push(S, p->rchild);
        }
    }
    return OK;
}
 

//采用二叉链表存储结构,Visit是对数据元素进行操作的应用函数,
//中序遍历二叉树的非递归算法,对每个数据元素调用函数Visit。
Status InOrderTraverse_NonRecursive_2(BiTree T, Status(*Visit)(TElemType e))
{
    Stack *S;
    BiTree p = T;
    S = (Stack *)malloc(sizeof(Stack));
    InitStack(S);
    while (p || !StackEmpty(S)){
        //根指针进栈,遍历左子树
        if (p){
            Push(S, p);
            p = p->lchild;
        }
        //根指针退栈,访问根结点,遍历右子树
        else{
            Pop(S, &p);
            if (!Visit(p->data))
                return ERROR;
            p = p->rchild;
        }
    }
    return OK;
}
 
//后序遍历二叉树,非递归算法
Status PostOrderTraverse_NonRecursive(BiTree T, Status(*Visit)(TElemType e)){
    Stack *S;
    BiTree p, pre=NULL;//pre指向已访问过的最后一个结点。
    S = (Stack*)malloc(sizeof(Stack));
    InitStack(S);
    Push(S, T);//根指针进栈
    while (!StackEmpty(S)){
        //获取栈顶指针,如果当前结点有左子树,并且左子树结点不是刚被访问的节点。如果当前结点有右子树,并且右子树结点不是刚被访问的结点。
        //表明栈顶指针指向的树结点未被访问,且左子树和右子树均未被访问。此时,将结点的左子树进栈。
        if (GetTop(S, &p) && p->lchild && pre != p->lchild && !(p->rchild && pre == p->rchild))
            Push(S, p->lchild);
        //如果栈顶指针的右子树存在,且未被访问。则将右子树进栈
        else if (p->rchild && pre != p->rchild)
            Push(S, p->rchild);
//如果左子树和右子树均被访问过,则结点退栈,并进行访问。更新pre。
        else{
            Pop(S, &p);
            if (!Visit(p->data))
                return ERROR;
            pre = p;
        }
    }
    return OK;
}

int main()
{
    BiTree T;
    CreatBiTree(&T);
    //先序
    printf("先序:\n");
    PreOrderTraverse_NonRecursive(T, PrintElement);
    printf("\n");
    //中序
	printf("中序:\n"); 
    InOrderTraverse_NonRecursive(T, PrintElement); 
    printf("\n");
    InOrderTraverse_NonRecursive_2(T, PrintElement);
    printf("\n");
    //后序
    printf("后序:\n"); 
    PostOrderTraverse_NonRecursive(T, PrintElement);
    printf("\n");
    system("pause");
    return 0;
}

这里写图片描述

当然,二叉树遍历有三种主要方式:先序遍历(根-左-右)、中序遍历(左-根-右)和后序遍历(左-右-根)。非递归的层次遍历(也叫广度优先遍历,从上到下、从左到右)通常使用队列来辅助实现。 这里分别给出这些遍历非递归算法代码: 1. 层序遍历(广度优先遍历): ```c #include <stdio.h> #include <stdlib.h> #include <queue> struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; void levelOrder(struct TreeNode* root) { if (root == NULL) return; // 使用队列存储每一层的节点 queue<struct TreeNode*> q; q.push(root); while (!q.empty()) { int size = q.size(); for (int i = 0; i < size; i++) { struct TreeNode* node = q.front(); q.pop(); printf("%d ", node->val); // 打印当前节点值 if (node->left != NULL) q.push(node->left); if (node->right != NULL) q.push(node->right); } printf("\n"); // 换行表示新的一层 } } ``` 2. 先序遍历(递归和非递归两种方式,这里是非递归版本,使用栈): ```c void preorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s; s.push(root); while (!s.empty()) { struct TreeNode* node = s.top(); s.pop(); printf("%d ", node->val); // 打印当前节点值 if (node->right != NULL) s.push(node->right); if (node->left != NULL) s.push(node->left); } } ``` 3. 中序遍历非递归,同样使用栈): ```c void inorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s; struct TreeNode* curr = root; while (curr != NULL || !s.empty()) { while (curr != NULL) { s.push(curr); curr = curr->left; } curr = s.top(); s.pop(); printf("%d ", curr->val); // 打印当前节点值 curr = curr->right; } } ``` 4. 后序遍历非递归,使用两个栈): ```c void postorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s1, s2; s1.push(root); while (!s1.empty()) { struct TreeNode* node = s1.top(); s1.pop(); s2.push(node); if (node->left != NULL) s1.push(node->left); if (node->right != NULL) s1.push(node->right); } while (!s2.empty()) { struct TreeNode* node = s2.top(); s2.pop(); printf("%d ", node->val); // 打印当前节点值 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值