非递归遍历二叉树(先序、中序、后序、层序)

/*递归算法虽然简洁,但一般而言,其执行效率不高
 *所占用的空间与运行的时间都比非递归算法多
 *在这里把二叉树非递归遍历(先序、中序、后序、层序)实现(使用了栈和队列)
 *这里我们约定:空的节点用#表示,按照前序遍历来创建树!
*/
/****************测试数据*************************
 please input BiTree for PreOrder:
 abc##de#g##f###

 preOrderNoRe: a b c d e g f
 inOrderNoRe: c b e g d f a
 postOrderNoRe: c g e f d b a
 leverOrderNoRe: a b c d e f g
/**************************************************/

#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;

#define MAXSIZE 100

int pos=0;  //二叉树读取字符串的位置

typedef struct node {   //树的节点
    char data;
    struct node *lchild;
    struct node *rchild;
} BiNode,*BiTree;

typedef struct node1 {  //栈
    BiTree data[MAXSIZE];
    int top;
} Stack;

typedef struct node2{   //队列
    BiTree data[MAXSIZE];
    int front,rear;
} Queue;

void initstack(Stack *&st);         //创建栈
bool isempty(Stack *st);            //判断是否为空
bool isfull(Stack *st);             //判断是否为满
void push(Stack *st,BiTree T);      //压栈
BiTree pop(Stack *st);              //出栈
BiTree gettop(Stack *st);           //返回栈顶元素

void initQueue(Queue *&Q);          //创建队列
void enQueue(Queue *Q, BiTree T);   //入队
BiTree deQueue(Queue *Q);           //出队
bool isemptyQ(Queue *Q);            //判断队列是否为空

void createTree(BiTree &T,string s);         //先序创建二叉树
void preOrderNoRe(BiTree T);        //先序遍历二叉树
void inOrderNoRe(BiTree T);         //中序遍历二叉树
void postOrderNoRe(BiTree T);       //后序遍历二叉树
void leverOrderNoRe(BiTree T);      //层序遍历二叉树

/*************************************栈操作函数开始************************************/
void initstack(Stack *&st) {
    st=(Stack *)malloc(sizeof(Stack));
    st->top=-1;
}
bool isempty(Stack *st) {
    return st->top==-1;
}
bool isfull(Stack *st) {
    return st->top==MAXSIZE;
}
void push(Stack *st,BiTree T) {
    if (!isfull(st))
        st->data[++st->top]=T; //栈顶指针始终指向堆栈最上面可用的一个元素,因此入栈时候,先要将指针加1,然后再执行入栈操作!
    else cout<<"已满"<<endl;
}
BiTree pop(Stack *st) {
    if (!isempty(st)) return st->data[st->top--];
}
BiTree gettop(Stack *st) {
    if (!isempty(st)) return st->data[st->top]; //出栈时,先取出栈顶指针指向的元素,然后再将指针减1,使其指向栈中下一个可用元素!
}
/*************************************栈操作函数结束************************************/

/*************************************队列操作函数开始************************************/
void initQueue(Queue *&Q){
    Q = (Queue *)malloc(sizeof(Queue));
    Q->front = Q->rear = MAXSIZE-1;
}
void enQueue(Queue *Q, BiTree T){
    if((Q->rear+1)%MAXSIZE==Q->front) throw "上溢";
    Q->rear = (Q->rear+1)%MAXSIZE;
    Q->data[Q->rear] = T;
}
BiTree deQueue(Queue *Q){
    if(Q->rear==Q->front) throw "下溢";
    Q->front = (Q->front+1)%MAXSIZE;
    return Q->data[Q->front];
}

bool isemptyQ(Queue *Q){
    return Q->rear==Q->front;
}
/*************************************队列操作函数结束************************************/

/*************************************树操作函数开始************************************/

void createTree(BiTree &T, string s) { //先序递归创建树,这里注意参数的类型,T的类型是 "*&" ,如果是 "**" 代码稍加改动就OK...
    if(s[pos]=='\0') return;
    if (s[pos]=='#') {T=NULL;pos++;} //这里首先判断是不是#,如果是,则为该节点赋NULL
    else {
        T=(BiTree)malloc(sizeof(BiNode));
        T->data=s[pos++];
        createTree(T->lchild,s);
        createTree(T->rchild,s);
    }
}

void preOrderNoRe(BiTree T) { // 前序遍历
    Stack *st;
    initstack(st);
    BiTree p=T;
    while (p!=NULL||!isempty(st)) {
        while (p!=NULL) {
            cout<<p->data<<" ";
            push(st,p);
            p=p->lchild;
        }
        if (!isempty(st)) {
            p=pop(st);
            p=p->rchild;
        }

    }
}

void inOrderNoRe(BiTree T) { //中序遍历
    Stack *st;
    initstack(st);
    BiTree p=T;
    while (p!=NULL||!isempty(st)) {
        while (p!=NULL) {
            push(st,p);
            p=p->lchild;
        }
        if (!isempty(st)) {
            p=pop(st);
            cout<<p->data<<" ";
            p=p->rchild;
        }

    }
}

void postOrderNoRe(BiTree T) { //后序遍历
    BiTree p=T;
    Stack *st;
    initstack(st);
    int flag[MAXSIZE]; //用于标识从左(0)或右(1)返回
    while (p!=NULL || !isempty(st)) {
        while (p!=NULL) {
            push(st,p);
            flag[st->top]=0;
            p=p->lchild;
        }
        while (!isempty(st)&&flag[st->top]==1) {
            p=pop(st);
            cout<<p->data<<" ";
        }
        if (!isempty(st)) {
            flag[st->top]=1; //设置标记右子树已经访问
            p=gettop(st);
            p=p->rchild;
        } else break;
    }
}

void leverOrderNoRe(BiTree T){  //层序遍历
    Queue *Q;
    initQueue(Q);
    BiTree p=T, q=NULL;
    if(p==NULL) return;
    enQueue(Q,p);           //根指针入队
    while(!isemptyQ(Q)){    //当队列非空时
        q = deQueue(Q);     //出队
        cout<<q->data<<' ';
        if(q->lchild!=NULL) enQueue(Q,q->lchild);
        if(q->rchild!=NULL) enQueue(Q,q->rchild);
    }
}
/*************************************树操作函数结束************************************/

int main() {
    cout<<"please input BiTree for PreOrder:"<<endl;
    string s;
    cin>>s;
    BiNode *T;
    createTree(T,s);
    cout<<endl;

    cout<<"preOrderNoRe: ";
    preOrderNoRe(T);
    cout<<endl;
    cout<<"inOrderNoRe: ";
    inOrderNoRe(T);
    cout<<endl;
    cout<<"postOrderNoRe: ";
    postOrderNoRe(T);
    cout<<endl;
    cout<<"leverOrderNoRe: ";
    leverOrderNoRe(T);
    cout<<endl;
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值