二叉树递归与非递归遍历

二叉树是一种常见的数据结构。二叉树有以下特点:

二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。
二叉树的第i层至多有2^{i-1}个结点;
深度为k的二叉树至多有2^k-1个结点;
对任何一棵二叉树T,如果其终端结点数为n_0,度为2的结点数为n_2,则n_0=n_2+1。

谈到二叉树,就不得不提到二叉树的遍历操作。其中,有三种比较重要的遍历方式,分别是前序遍历,中序遍历和后序遍历。我们看看一个例子:
二叉树递归与非递归遍历_第1张图片

前序遍历(先遍历中间结点,然后左结点,最后右结点):ABCDEF
中序遍历(先遍历左结点,然后中间结点,最后右结点):CBDAEF
后序遍历(先遍历左结点,然后右结点,最后中间结点):CDBFEA

以下为实现代码:

#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef int Status;
typedef char ElemType;

typedef struct BiTNode {
    ElemType data;
    struct BiTNode *lChild, *rChild; //左结点,右结点
} BiTNode, *BiTree;

typedef BiTree SElemType;
typedef struct {
    SElemType *base;  //栈底指针
    SElemType *top;   //栈顶指针
    int stacksize;
} SqStack;

//栈操作

/* *初始化栈 */
Status initStack(SqStack &s) {
    s.base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType)); //申请空间
    if (!s.base) return ERROR;
    s.top = s.base;  //栈顶指针和栈底指针指向同一地址,表示栈为空
    s.stacksize = STACK_INIT_SIZE;   //初始化栈大小
    return OK;
}

/* *出栈 */
Status pop(SqStack &s, SElemType &e) {
    if (s.top == s.base) return ERROR;
    e = *(--s.top);  //出栈,top指针下移
    return OK;
}

/* *入栈 */
Status push(SqStack &s, SElemType &e) {
    if (s.top - s.base >= s.stacksize) {  //空间不够,申请增加空间
        s.base = (SElemType*) realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(SElemType));
        if (!s.base) return ERROR;
        s.stacksize += STACKINCREMENT;
        s.top = s.base + s.stacksize;
    }
    *s.top ++ = e;  //入栈,top指针上移
    return OK;
}

/* *判断栈为空 */
Status isEmpty(SqStack S) {
    return S.top == S.base;
}
/* *销毁栈 */
Status destotyStack(SqStack &S) {
    free(S.base);
    return OK;
}
/* *获得栈顶元素 */
Status getTop(SqStack &s, SElemType &e) {
    if (s.top == s.base) return ERROR;
    e = *(s.top - 1);
    return OK;
}

//--------------------------

//二叉树操作


/* *创建二叉树 */
Status createBiTree(BiTree &T) {
    ElemType ch;
    scanf("%c", &ch);
    if (ch == '#') T = NULL;
    else {
        T = (BiTree) malloc(sizeof(BiTNode));
        T->data = ch;
        createBiTree(T->lChild);
        createBiTree(T->rChild);
    }
    return OK;
}

/* *打印元素 */
Status printElement(ElemType e) {
    printf("%c", e);
    return OK;
}


/* *递归遍历 */

/* *前序遍历 */
Status preOrderTraverse(BiTree &T) {
    if (T) {
        //遍历顺序:中,左,右
        if (printElement(T->data))
            if (preOrderTraverse(T->lChild))
                if (preOrderTraverse(T->rChild))
                    return OK;
        return ERROR;
    } else {
        return OK;
    }
}

/* *中序遍历 */
Status inOrderTraverse(BiTree &T) {
    if (T) {
            //遍历顺序:左,中,右
        if (inOrderTraverse(T->lChild))
            if (printElement(T->data))
                if (inOrderTraverse(T->rChild))
                    return OK;
        return ERROR;
    } else {
        return OK;
    }
}

/* *后序遍历 */
Status postOrderTraverse(BiTree &T) {
    if (T) {
            //遍历顺序:左,右中
        if (postOrderTraverse(T->lChild))
            if (postOrderTraverse(T->rChild))
                if (printElement(T->data))
                    return OK;
        return ERROR;
    } else {
        return OK;
    }
}
//-------------------------------------

/* *非递归遍历 */
Status preOrderTraverse_Sq(BiTree &T) {
    SqStack S;
    initStack(S);
    BiTree p = T;
    push(S, p);  //根结点入栈
    while (!isEmpty(S)) {
        pop(S, p);       //根结点出栈
        printElement(p->data);
        if (p->rChild)   //左右结点入栈
            push(S, p->rChild);
        if (p->lChild)
            push(S, p->lChild);
    }
    destotyStack(S);
    return OK;
}

Status inOrderTraverse_Sq(BiTree &T) {
    SqStack S;
    initStack(S);
    BiTree p = T;
    while (p || !isEmpty(S)) {
        if (p) {       
            push(S, p);   //根节点入栈
            p = p->lChild;  //向左前进
        } else {
            pop(S, p);   //根结点出栈
            printElement(p->data);
            p = p->rChild;  //向右前进
        }
    }
    destotyStack(S);
    return OK;
}


Status postOrderTraverse_Sq(BiTree &T) {
    SqStack S;
    initStack(S);
    BiTree p = T, q;
    push(S, p);
    while(!isEmpty(S)){
        while(getTop(S,p) && p&& (p->lChild || p->rChild)){
                //可能存在左结点或右结点是空,并且入栈了
                push(S, p->rChild);      // 右结点入栈
                push(S, p->lChild);      // 左结点入栈
        }
        if(!isEmpty(S)){
            pop(S, p);
            if (p){ 
                printElement(p->data);
            }else{      // 右结点为空,继续出栈
                pop(S, p);
                printElement(p->data);
            }
            while (getTop(S,q)&& q && p == q->rChild){ //当前为右结点,继续出栈
                pop(S, p);
                printElement(p->data);
                getTop(S, q);
            }
        }
    }
    destotyStack(S);
    return OK;
}

//----------------------------

int main()   //主函数
{
    BiTree T;
    createBiTree(T);
    printf("前序(递归):");
    preOrderTraverse(T);
    printf("\n");
    printf("前序(非递归):");
    preOrderTraverse_Sq(T);
    printf("\n");
    printf("中序(递归):");
    inOrderTraverse(T);
    printf("\n");
    printf("中序(非递归):");
    inOrderTraverse_Sq(T);
    printf("\n");
    printf("后序(递归):");
    postOrderTraverse(T);
    printf("\n");
    printf("后序(非递归):");
    postOrderTraverse_Sq(T);
    printf("\n");
    return 0;
}//main

用博文刚开始的图片数据作为测试,测试结果为:

你可能感兴趣的:(数据结构,遍历,二叉树,C语言)