二叉树 (Binary Tree)的遍历

树是一种比较重要的数据结构,尤其是二叉树。二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

二叉树节点定义:

#define ElementType char
typedef struct Node {
    ElementType data;
    struct Node *lchild;
    struct Node *rchild;
}BinaryTree;

一、二叉树遍历递归遍历算法

1.先序遍历递归遍历算法

/*
 (1)先序遍历 递归解法
 遍历过程为:
    1.访问根节点
    2.遍历其左子树
    3.遍历其右子树
*/
void PreOrderTraversal(BinaryTree* BT) {
    if (BT) {
        printf("%c", BT->data);
        PreOrderTraversal(BT->lchild);
        PreOrderTraversal(BT->rchild);
    }
}

《二叉树 (Binary Tree)的遍历》

2.中序遍历递归遍历算法

/*
 (2)中序遍历 递归解法
 遍历过程:
    1.遍历其左子树
    2.访问根节点
    3.遍历其右子树
*/
void InOrderTraversal(BinaryTree* BT) {
    if (BT) {
        InOrderTraversal(BT->lchild);
        printf("%c", BT->data);
        InOrderTraversal(BT->rchild);
    }
}

《二叉树 (Binary Tree)的遍历》

3.后序遍历递归遍历算法

/*
 (3)后序遍历 递归解法
 遍历过程:
    1.遍历其左子树
    2.遍历其右子树
    3.访问根节点
*/
void PostOrderTraversal(BinaryTree* BT) {
    if (BT) {
        PostOrderTraversal(BT->lchild);
        PostOrderTraversal(BT->rchild);
        printf("%c", BT->data);
    }
}

《二叉树 (Binary Tree)的遍历》

验证如下:

#include <stdio.h>
#include <stdlib.h>

#define ElementType char
typedef struct Node {
    ElementType data;
    struct Node *lchild;
    struct Node *rchild;
}BinaryTree;

//创建二叉树节点
BinaryTree* CreateBinaryTree(data) {
    BinaryTree* t = (BinaryTree*)malloc(sizeof(BinaryTree));
    if (!t) {
        printf("空间不足!\n");
        return NULL;
    }
    t->lchild = NULL;
    t->rchild = NULL;
    t->data = data;
    return t;
}

/*
 (1)先序遍历 递归解法
 遍历过程为:
    1.访问根节点
    2.遍历其左子树
    3.遍历其右子树
*/
void PreOrderTraversal(BinaryTree* BT) {
    if (BT) {
        printf("%c", BT->data);
        PreOrderTraversal(BT->lchild);
        PreOrderTraversal(BT->rchild);
    }
}

/*
 (2)中序遍历 递归解法
 遍历过程:
    1.遍历其左子树
    2.访问根节点
    3.遍历其右子树
*/
void InOrderTraversal(BinaryTree* BT) {
    if (BT) {
        InOrderTraversal(BT->lchild);
        printf("%c", BT->data);
        InOrderTraversal(BT->rchild);
    }
}

/*
 (3)后序遍历 递归解法
 遍历过程:
    1.遍历其左子树
    2.遍历其右子树
    3.访问根节点
*/
void PostOrderTraversal(BinaryTree* BT) {
    if (BT) {
        PostOrderTraversal(BT->lchild);
        PostOrderTraversal(BT->rchild);
        printf("%c", BT->data);
    }
}

int main(int argc, const char * argv[]) {
    BinaryTree* tree_A = CreateBinaryTree('A');
    
    BinaryTree* tree_B = CreateBinaryTree('B');
    tree_A->lchild = tree_B;
    
    BinaryTree* tree_C = CreateBinaryTree('C');
    tree_A->rchild = tree_C;
    
    BinaryTree* tree_D = CreateBinaryTree('D');
    tree_B->lchild = tree_D;
    
    BinaryTree* tree_F = CreateBinaryTree('F');
    tree_B->rchild = tree_F;
    
    BinaryTree* tree_E = CreateBinaryTree('E');
    tree_F->lchild = tree_E;
    
    BinaryTree* tree_G = CreateBinaryTree('G');
    tree_C->lchild = tree_G;
    
    BinaryTree* tree_I = CreateBinaryTree('I');
    tree_C->rchild = tree_I;
    
    BinaryTree* tree_H = CreateBinaryTree('H');
    tree_G->rchild = tree_H;
    
    //先序遍历 => A B D F E C G H I
    PreOrderTraversal(tree_A);
    
    printf("\n");
    
    //中序遍历 => D B E F A G H C I
    InOrderTraversal(tree_A);
    
    printf("\n");
    
    //后序遍历 => D E F B H G I C A
    PostOrderTraversal(tree_A);
    
    return 0;
}

二、二叉树遍历非递归遍历算法

非递归算法实现的基本思路:使用栈

1.遇到一个节点,就把它压栈,并去遍历它的左子树。

2.当左子树遍历结束后,从栈顶弹出这个节点并访问它。

3.然后按其右指针再去遍历该节点的右子树。

#include <stdio.h>
#include <stdlib.h>

#define ElementType char
typedef struct Node {
    int isFirst;
    ElementType data;
    struct Node *lchild;
    struct Node *rchild;
}BinaryTree;

typedef struct StackNode {
    BinaryTree* data;
    struct StackNode* next;
}Stack;
//初始化堆栈
Stack* CreateStack() {
    Stack* s;
    s = (Stack*)malloc(sizeof(Stack));
    if (!s) {
        printf("空间不足\n");
    }
    s->next = NULL;
    return s;
}
int IsEmpty(Stack* s) {
    return (s->next == NULL);
}
//入栈
void Push(Stack* s, BinaryTree* data) {
    Stack* cell;
    cell = (Stack*)malloc(sizeof(Stack));
    if (!cell) {
        printf("空间不足\n");
    }
    cell->data = data;
    cell->next = s->next;
    s->next = cell;
}
//出栈
BinaryTree* Pop(Stack* s) {
    Stack* firstCell;
    BinaryTree* topData;
    if (IsEmpty(s)) {
        printf("空栈\n");
        return NULL;
    }
    firstCell = s->next;
    s->next = firstCell->next;
    topData = firstCell->data;
    free(firstCell);
    return topData;
}


//创建二叉树节点
BinaryTree* CreateBinaryTree(data) {
    BinaryTree* t = (BinaryTree*)malloc(sizeof(BinaryTree));
    if (!t) {
        printf("空间不足!\n");
        return NULL;
    }
    t->lchild = NULL;
    t->rchild = NULL;
    t->data = data;
    return t;
}

//先序遍历非递归遍历解法
void PreOrderTraversal(BinaryTree* BT) {
    BinaryTree* T = BT;
    Stack* s = CreateStack(); //创建并初始化栈s
    while (T || !IsEmpty(s)) {
        while (T) { //一直向左并将沿途节点压入栈
            Push(s, T);
            printf("%c", T->data);
            T = T->lchild;
        }
        if (!IsEmpty(s)) {
            T = Pop(s); //节点弹出栈
            T = T->rchild; //转向右子树
        }
    }
}

//中序遍历非递归遍历解法
void InOrderTraversal(BinaryTree* BT) {
    BinaryTree* T = BT;
    Stack* s = CreateStack(); //创建并初始化栈s
    while (T || !IsEmpty(s)) {
        while (T) { //一直向左并将沿途节点压入栈
            Push(s, T);
            T = T->lchild;
        }
        if (!IsEmpty(s)) {
            T = Pop(s); //节点弹出栈
            printf("%c", T->data);
            T = T->rchild; //转向右子树
        }
    }
}

//后序遍历非递归遍历解法
void PostOrderTraversal(BinaryTree* BT) {
    BinaryTree* T = BT;
    Stack* s = CreateStack(); //创建并初始化栈s
    while (T || !IsEmpty(s)) {
        while (T) { //一直向左并将沿途节点压入栈
            T->isFirst = 1;
            Push(s, T);
            T = T->lchild;
        }
        if (!IsEmpty(s)) {
            T = Pop(s); //节点弹出栈
            if(T->isFirst == 1) { //表示是第一次出现在栈顶
                T->isFirst = 0;
                Push(s, T);
                T = T->rchild;
            }
            else { //第二次出现在栈顶
                printf("%c", T->data);
                T = NULL;
            }
        }
    }
}

int main(int argc, const char * argv[]) {
    BinaryTree* tree_A = CreateBinaryTree('A');
    
    BinaryTree* tree_B = CreateBinaryTree('B');
    tree_A->lchild = tree_B;
    
    BinaryTree* tree_C = CreateBinaryTree('C');
    tree_A->rchild = tree_C;
    
    BinaryTree* tree_D = CreateBinaryTree('D');
    tree_B->lchild = tree_D;
    
    BinaryTree* tree_F = CreateBinaryTree('F');
    tree_B->rchild = tree_F;
    
    BinaryTree* tree_E = CreateBinaryTree('E');
    tree_F->lchild = tree_E;
    
    BinaryTree* tree_G = CreateBinaryTree('G');
    tree_C->lchild = tree_G;
    
    BinaryTree* tree_I = CreateBinaryTree('I');
    tree_C->rchild = tree_I;
    
    BinaryTree* tree_H = CreateBinaryTree('H');
    tree_G->rchild = tree_H;
    
    printf("先序遍历非递归遍历算法:");
    //先序遍历 => A B D F E C G H I
    PreOrderTraversal(tree_A);
    
    printf("\n中序遍历非递归遍历算法:");
    //中序遍历 => D B E F A G H C I
    InOrderTraversal(tree_A);
    
    printf("\n后序遍历非递归遍历算法:");
    //后序遍历 => D E F B H G I C A
    PostOrderTraversal(tree_A);
    
    return 0;
}

    原文作者:song_hui_xiang
    原文地址: https://blog.csdn.net/song_hui_xiang/article/details/47679035
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞