二叉树的创建,前、中、后序遍历以及层次遍历

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LunaW/article/details/78961577

二叉树的创建

对于二叉树的创建,可能很多人不知道如何去初始化一个二叉树,其实初始化二叉树非常简单,需要引入一个扩展二叉树的概念

扩展二叉树

扩展二叉树:让二叉树的所有节点都具有左右孩子,没有孩子的,我们手动将其填满,例如#,即如下所示
扩展二叉树
扩展二叉树主要的目的是为了确定一颗二叉树,我们都知道,只有前序加中序或者后序加中序才能确定一棵树,但是我们同样可以通过扩展二叉树的前序确定一棵树,即:
ABC###DE##F##

创建二叉树代码

BiTree CreateTreeNode(void)
{
    char c;
    BiTree T;
    scanf("%c", &c);
    if (c == '#') {
        T = NULL;
    } else {
        T = (BiTree) calloc(sizeof(BiTNode), 1);
        T->data = c;
        T->lchild = CreateTreeNode();
        T->rchild = CreateTreeNode();
    }
    return T;
}

二叉树的前中后序遍历

二叉树的创建采用的是递归的方式,那么同样二叉树的遍历同样可以采取递归的方式,而且简单明了

前序遍历:若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树。按照上面创建的二叉树,则遍历顺序为:ABCDEF

中序遍历:若二叉树为空,则空操作返回,否则从根节点开始(不是先访问根节点),中序遍历根节点的左子树,然后是访问根节点,最后中序遍历右子树。按照上面创建的二叉树,则遍历顺序为:CBAEDF

后序遍历:若二叉树为空,则空操作返回,否则从左到右先叶子后节点的方式先后遍历左右子树,最后遍历根节点。按照上面创建的二叉树,则遍历顺序为:CBEFDA

前中后序遍历代码

void PreOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    printf("%c", T->data);
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
}

void InOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    InOrderTraverse(T->lchild);
    printf("%c", T->data);
    InOrderTraverse(T->rchild);
}

void PostOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    printf("%c", T->data);
}

二叉树层次遍历(队列方式实现)

二叉树层次遍历,即按从上至下从左至右按层次遍历,这个遍历就和上面有所不同,不过采用队列也是非常容易理解和实现的
若根节点为空,直接返回;若根节点非空,则将根节点入队,然后,判断队列是否为空,若不为空,则将队首节点出队,访问,并判断其左右子节点是否为空,若不为空,则压入队列,然后循环上面操作直到队列为空

二叉树层次遍历代码

void LevelOrderTraverse(BiTree T)
{
    QNode Tmp, tmp;
    LinkQueue Q;
    tmp.next = NULL;
    Tmp.next = NULL;
    Q.front = NULL;
    Q.rear = NULL;

    InitQueue(&Q);
    tmp.Tree = T;
    EnQueue(&Q, &tmp);  // 根节点入队
    while (DeQueue(&Q, &Tmp)) { // 依次出队,直到队列为空
        printf("%c", Tmp.Tree->data);
        if (Tmp.Tree->lchild != NULL) { // 若出队节点有左孩子,则左孩子入队
            tmp.Tree = Tmp.Tree->lchild;
            EnQueue(&Q, &tmp);
        }
        if (Tmp.Tree->rchild != NULL) { // 若出队节点有右孩子,则右孩子入队
            tmp.Tree = Tmp.Tree->rchild;
            EnQueue(&Q, &tmp);
        }
    }
    FreeQueue(&Q);
}

完整代码


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  > Author: xiaojunyu/LunaW
  > Mail  : [email protected]
  > Gmail : [email protected]
  > Blog  : http://blog.csdn.net/lunaw
  > Web   : http://lunaw.cn

 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/

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

#define True 1
#define False 0

typedef struct BiTNode {
    int data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

BiTree CreateTreeNode(void);    // 先变为扩展二叉树,前序递归输入
void PreOrderTraverse(BiTree T);    // 前序遍历,递归
void InOrderTraverse(BiTree T); // 中序遍历,递归
void PostOrderTraverse(BiTree T);   // 后序遍历,递归
void LevelOrderTraverse(BiTree T);  // 层次遍历,队列
void DestroyTree(BiTree T); // 销毁树,后序递归

/* 队列 */
typedef struct QNode {
    BiTree Tree;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct Queue {
    QueuePtr front, rear;
} LinkQueue;

int IsEmpt(LinkQueue * queue);  // 判断是否为空
int InitQueue(LinkQueue * queue);   //初始化队列
int FreeQueue(LinkQueue * queue);   // 释放队列
int EnQueue(LinkQueue * queue, QueuePtr Q); // 进队列
int DeQueue(LinkQueue * queue, QueuePtr Q); // 出队列

int main(void)
{
    BiTree T = NULL;
    printf("请输入扩展二叉树: ");
    T = CreateTreeNode();
    printf("\n前序遍历: ");
    PreOrderTraverse(T);
    printf("\n中序遍历: ");
    InOrderTraverse(T);
    printf("\n后序遍历: ");
    PostOrderTraverse(T);
    printf("\n层次遍历: ");
    LevelOrderTraverse(T);
    DestroyTree(T);
    return 0;
}

BiTree CreateTreeNode(void)
{
    char c;
    BiTree T;
    scanf("%c", &c);
    if (c == '#') {
        T = NULL;
    } else {
        T = (BiTree) calloc(sizeof(BiTNode), 1);
        T->data = c;
        T->lchild = CreateTreeNode();
        T->rchild = CreateTreeNode();
    }
    return T;
}

void DestroyTree(BiTree T)
{
    if (T == NULL) {
        return;
    }
    DestroyTree(T->lchild);
    DestroyTree(T->rchild);
    free(T);        // 采用后序遍历递归销毁
    T = NULL;
}

void PreOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    printf("%c", T->data);
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
}

void InOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    InOrderTraverse(T->lchild);
    printf("%c", T->data);
    InOrderTraverse(T->rchild);
}

void PostOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    printf("%c", T->data);
}

void LevelOrderTraverse(BiTree T)
{
    QNode Tmp, tmp;
    LinkQueue Q;
    tmp.next = NULL;
    Tmp.next = NULL;
    Q.front = NULL;
    Q.rear = NULL;

    InitQueue(&Q);
    tmp.Tree = T;
    EnQueue(&Q, &tmp);  // 根节点入队
    while (DeQueue(&Q, &Tmp)) { // 依次出队,直到队列为空
        printf("%c", Tmp.Tree->data);
        if (Tmp.Tree->lchild != NULL) { // 若出队节点有左孩子,则左孩子入队
            tmp.Tree = Tmp.Tree->lchild;
            EnQueue(&Q, &tmp);
        }
        if (Tmp.Tree->rchild != NULL) { // 若出队节点有右孩子,则右孩子入队
            tmp.Tree = Tmp.Tree->rchild;
            EnQueue(&Q, &tmp);
        }
    }
    FreeQueue(&Q);
}

int DeQueue(LinkQueue * queue, QueuePtr Q)
{
    QueuePtr P;
    if (IsEmpt(queue)) {
        return False;
    }
    P = queue->front->next;
    memcpy(Q, P, sizeof(QNode));    // 将队头数据保存
    queue->front->next = P->next;   // 队头下移一位
    if (queue->rear == P) { // 若队尾是队头,则将队尾指向头节点
        queue->rear = queue->front;
    }
    free(P);
    return True;
}

int EnQueue(LinkQueue * queue, QueuePtr Q)
{
    QueuePtr S = (QueuePtr) calloc(sizeof(QNode), 1);
    memcpy(S, Q, sizeof(QNode));
    queue->rear->next = S;
    queue->rear = S;
    return 0;
}

int InitQueue(LinkQueue * queue)
{
    queue->front = (QueuePtr) calloc(sizeof(QNode), 1);
    queue->front->next = NULL;
    queue->rear = queue->front;
    return 0;
}

int IsEmpt(LinkQueue * queue)
{
    if (queue->front == NULL || queue->front == queue->rear) {
        return True;
    } else {
        return False;
    }
}

int FreeQueue(LinkQueue * queue)
{
    QueuePtr A, B;
    for (A = queue->front; A != NULL; B = A->next, free(A), A = B) ;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LunaW/article/details/78961577