二叉树部分的常见算法与实现

二叉树

二叉树的遍历非常重要,一定要熟练掌握。

  • 因为二叉树的层序创建,层序遍历均用到了队列结构,二叉树的非递归遍历用到了堆栈结构,这部分的代码在后面单独给出。
  • 二叉树的后序非递归遍历有两种实现思路,在下面的代码中只实现了一种。

二叉树的链表结构为:

struct TNode
{
    int Data;  //节点的数据
    struct TNode* Left;  //指向左子树
    struct TNode* Right;  //指向右子树
};

typedef struct TNode* ElementType;

二叉树部分的算法与相关代码实现

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"queue.h"
#include"Stack.h"
#define NoInfo 0  //用0表示没有节点

//struct TNode
//{
//  int Data;  //节点的数据
//  struct TNode* Left;  //指向左子树
//  struct TNode* Right;  //指向右子树
//};

//作用:层序生成二叉树
struct TNode* CreatBinTree()
{
    int Data;
    struct QNode* Q = CreatQueue(10);  //创建空队列
    struct TNode* T;
    struct TNode* BT;

    //建立第一个节点,即根节点
    scanf("%d",&Data);
    if (Data != NoInfo)
    {
        //动态分配一个结点单元,并存入数据,同时将该结点地址放入队列
        BT = (struct TNode *)malloc(sizeof(struct TNode));
        BT->Data = Data;
        BT->Left = NULL;
        BT->Right = NULL;
        AddQ(Q,BT);
    }
    else
    {
        return NULL;
    }

    while (!IsEmpty(Q))
    {
        T = DeleteQ(Q);  //从队列中取出一节点地址
        scanf("%d",&Data);
        if (Data != NoInfo)
        {
            //动态分配一个结点单元,并存入数据,同时将该结点地址放入队列
            T->Left = (struct TNode *)malloc(sizeof(struct TNode));
            T->Left->Data = Data;
            T->Left->Left = NULL;
            T->Left->Right = NULL;
            
            AddQ(Q, T->Left);
        }
        else
        {
            T->Left = NULL;
        }
        //读入右孩子的数据
        scanf("%d", &Data);
        if (Data != NoInfo)
        {
            //动态分配一个结点单元,并存入数据,同时将该结点地址放入队列
            T->Right = (struct TNode *)malloc(sizeof(struct TNode));
            T->Right->Data = Data;
            T->Right->Left = NULL;
            T->Right->Right = NULL;

            AddQ(Q, T->Right);
        }
        else
        {
            T->Right = NULL;
        }   
    } //end while (!IsEmpty(Q))
    return BT;
}
//作用:二叉树的递归后序遍历
void PostorderTraversal(struct TNode* BT)
{
    if (BT)
    {
        PostorderTraversal(BT->Left);
        PostorderTraversal(BT->Right);
        printf("%d. ", BT->Data);
    }
}
//作用:二叉树的递归先序遍历
void PreorderTraversal(struct TNode* BT)
{
    if (BT)
    {
        printf("%d. ", BT->Data);
        PreorderTraversal(BT->Left);
        PreorderTraversal(BT->Right);
    }
}
//作用:二叉树的递归中序遍历
void InorderTraversal(struct TNode* BT)
{
    if (BT)
    {
        InorderTraversal(BT->Left);
        printf("%d. ", BT->Data);
        InorderTraversal(BT->Right);
    }
}
//作用:二叉树的非递归中序遍历
void InorderTraversal2(struct TNode* BT)
{
    struct TNode* T;

    struct SNode* S = CreatStack(10);

    T = BT;
    
    while (T || !IsStackEmpty(S))
    {
        while (T)
        {
            Push(S, T);
            T = T->Left;
        }
        T = Pop(S);
        printf("%d. ",T->Data);
        T = T->Right;  //转向右子树
    }
}
//作用:二叉树的非递归先序遍历
void PreorderTraversal2(struct TNode* BT)
{
    struct TNode* T;

    struct SNode* S = CreatStack(10);

    T = BT;

    while (T || !IsStackEmpty(S))
    {
        while (T)
        {
            printf("%d. ", T->Data);
            Push(S, T);
            T = T->Left;
        }
        T = Pop(S);
        T = T->Right;  //转向右子树
    }
}
//作用:二叉树的非递归后序遍历
//思路1 将先序遍历的算法进行更改
void PostorderTraversal2(struct TNode* BT)
{
    struct TNode* T;

    struct SNode* S1 = CreatStack(10);
    struct SNode* S2 = CreatStack(10);

    T = BT;

    while (T || !IsStackEmpty(S1))
    {
        while (T)
        {
            //printf("%d. ", T->Data);
            Push(S2, T);  //压入根节点
            Push(S1, T);
            T = T->Right;
        }
        T = Pop(S1);
        T = T->Left;  //转向左子树
    }
    while (!IsStackEmpty(S2))
    {
        T = Pop(S2);
        printf("%d. ",T->Data);
    }
}
//作用:二叉树的非递归后序遍历
//思路2 
//ToDo: 参考博客园博客,这里有一个思路2还没有写
void PostorderTraversal3(struct TNode* BT)
{



}
//作用:层序遍历
void LevelorderTraversal(struct TNode* BT)
{
    struct QNode* Q;
    struct TNode* T;
    if (!BT)
    {
        return;  //若是空树,直接返回
    }
    Q = CreatQueue(10);
    AddQ(Q, BT);  //首先将根节点入队

    while (!IsEmpty(Q))
    {
        T = DeleteQ(Q);
        printf("%d. ", T->Data);
        if (T->Left != NULL)
        {
            AddQ(Q, T->Left);
        }
        if (T->Right != NULL)
        {
            AddQ(Q,T->Right);
        }
    }

}
//作用:输出二叉树的叶子结点
void PreorderPrintLeaves(struct TNode* BT)
{
    if (BT)
    {
        if (BT->Left == NULL && BT->Right == NULL)
        {
            printf("%d. ", BT->Data);
        }
        PreorderPrintLeaves(BT->Left);
        PreorderPrintLeaves(BT->Right);
    }
}
//作用:求二叉树的高度
int GetHeight(struct TNode* BT)
{
    int HL;
    int HR;
    int MaxH;
    if (BT)  //BT非空进行遍历
    {
        HL = GetHeight(BT->Left);
        HR = GetHeight(BT->Right);
        MaxH = HL > HR ? HL : HR;
         return MaxH + 1;
    }
    else
    {
        return 0;
    }
    
}
int main()
{
    struct TNode* BT = CreatBinTree();
    printf("中序递归遍历:\n");
    InorderTraversal(BT);
    printf("\n先序递归遍历:\n");
    PreorderTraversal(BT);
    printf("\n后序递归遍历:\n");
    PostorderTraversal(BT);

    printf("\n非递归中序遍历:\n");
    InorderTraversal2(BT);
    printf("\n非递归先序遍历:\n");
    PreorderTraversal2(BT);
    printf("\n非递归后序遍历:\n");
    PostorderTraversal2(BT);
    printf("\n层序遍历\n");
    LevelorderTraversal(BT);
    printf("\n输出二叉树中所有的叶子结点\n");
    PreorderPrintLeaves(BT);
    printf("二叉树的高度: %d.\n", GetHeight(BT));
    system("pause");
    return 0;
}

实现链表部分的代码:

queue.h

//二叉树的创建需要队列
//该文件实现队列的一系列操作
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>

struct TNode
{
    int Data;  //节点的数据
    struct TNode* Left;  //指向左子树
    struct TNode* Right;  //指向右子树
};

typedef struct TNode* ElementType;

struct QNode 
{
    ElementType* Data;  //存储元素的数组
    int Front;  //队列的头指针
    int Rear;  //队列的尾指针
    int MaxSize;  //队列的最大容量
};

struct QNode* CreatQueue(int MaxSize);
bool IsFull(struct QNode* Q);
bool AddQ(struct QNode* Q, ElementType x);
bool IsEmpty(struct QNode* Q);
ElementType DeleteQ(struct QNode* Q);

queue.c

#include<stdio.h>
#include"queue.h"
//作用:创建一个队列
//参数:队列的大小
struct QNode* CreatQueue(int MaxSize)
{
    struct QNode* Q = (struct QNode *)malloc(sizeof(struct QNode));
    Q->Data = (ElementType *)malloc(MaxSize * sizeof(int));
    Q->Front = Q->Rear = 0;
    Q->MaxSize = MaxSize;
    return Q;
}
//作用:判断当前队列是否满
//参数:待判断的队列
bool IsFull(struct QNode* Q)
{
    return ((Q->Rear + 1) % Q->MaxSize == Q->Front);
}
//作用:向队列中插入元素
//参数:struct QNode* Q 待插入的队列
//      int x 待插入的元素
bool AddQ(struct QNode* Q, ElementType x)
{
    if (IsFull(Q))  //判断队列是否为空
    {
        printf("队列满,不能再插入元素\n");
        return false;
    }
    else
    {
        Q->Rear = (Q->Rear + 1) % Q->MaxSize;
        Q->Data[Q->Rear] = x;
        return true;
    }
}
//作用:判断队列是否为空
//参数:
//返回值: true   空
//         false  非空
bool IsEmpty(struct QNode* Q)
{
    return (Q->Front == Q->Rear);
}
//作用:
//参数:
ElementType DeleteQ(struct QNode* Q)
{
    if (IsEmpty(Q))
    {
        printf("队列为空\n");
        return NULL;
    }
    else
    {
        Q->Front = (Q->Front + 1) % Q->MaxSize;
        return Q->Data[Q->Front];
    }
}

实现堆栈部分的代码:

Stack.h

#pragma once
#include<stdbool.h>
#include"queue.h"

struct SNode
{
    ElementType* Data;  //存储元素的数组
    int Top;  //栈顶指针
    int MaxSize;  //堆栈的最大容量
};

struct SNode* CreatStack(int MaxSize);
bool IsStackFull(struct SNode* S);
bool Push(struct SNode* S,ElementType x);
bool IsStackEmpty(struct SNode* S);
ElementType Pop(struct SNode* S);

Stack.c

#include"Stack.h"
#include<stdlib.h>

struct SNode* CreatStack(int MaxSize)
{
    struct SNode* S = (struct SNode *)malloc(sizeof(struct SNode));
    S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    S->MaxSize = MaxSize;
    S->Top = -1;
    return S;
}
//作用:判断当前堆栈是否满
//返回值: ture 当前堆栈满
//         false 当前堆栈非满
bool IsStackFull(struct SNode* S)
{
    return S->Top == S->MaxSize - 1;
}
bool Push(struct SNode* S, ElementType x)
{
    if (IsStackFull(S))
    {
        printf("当前堆栈已满.\n");
        return false;
    }
    else
    {
        S->Top = S->Top + 1;
        S->Data[S->Top] = x;
        return true;
    }

}
//作用:判断当前堆栈是否为空
//返回值:true 空
//        false 非空
bool IsStackEmpty(struct SNode* S)
{
    return S->Top == -1;

}
ElementType Pop(struct SNode* S)
{
    if (IsStackEmpty(S))
    {
        printf("堆栈为空.\n");
        return false;
    }
    else
    {
        return S->Data[(S->Top)--];
    }
}

运行结果:
1327401-20190808162545010-380964479.png

转载于:https://www.cnblogs.com/Manual-Linux/p/11315776.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值