SCAU8608 实现二叉排序树的各种算法(综合性实验)

这篇文章给出了这道题的代码实现方式。

代码对可能的问题给出了详尽的注释,如果读者还有不明白的地方,欢迎在评论区留下你的问题。

#include <stdio.h>
#define ElemType int //二叉排序树存储数据Data类型为ElemType:int
#define Status int   //函数返回状态
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef struct BiTNode //定义二叉树结点类型
{
    ElemType Data;
    struct BiTNode *Lchild, *Rchild;
} BiTNode, *BiTree;

void InsertElem(BiTree &T, ElemType e) //插入函数:对每一个结点找到其合适位置并插入
{
    if (!T) //找到空节点
    {
        T = new BiTNode;
        T->Data = e;
        T->Lchild = T->Rchild = NULL;
    }
    else
    {
        if (T->Data > e)
            InsertElem(T->Lchild, e); //根据当前节点值与待插入值之间的大小关系,分别向左向右寻找
        else
            InsertElem(T->Rchild, e);
    }
}

void Create(BiTree &T, int ElemNum) //构建二叉排序树
{
    for (int i = 0; i < ElemNum; i++)
    {
        ElemType Element;
        scanf("%d", &Element);
        InsertElem(T, Element); //插入每一个输入的值
    }
}

void PreOrderTraverse(BiTree T) //先序遍历的递归算法
{
    if (T)
    {
        printf("%d ", T->Data);
        PreOrderTraverse(T->Lchild);
        PreOrderTraverse(T->Rchild);
    }
}

void InOrderTraverse(BiTree T) //中序遍历的递归算法
{
    if (T)
    {
        InOrderTraverse(T->Lchild);
        printf("%d ", T->Data);
        InOrderTraverse(T->Rchild);
    }
}

void PostOrderTraverse(BiTree T) //后序遍历的递归算法
{
    if (T)
    {
        PostOrderTraverse(T->Lchild);
        PostOrderTraverse(T->Rchild);
        printf("%d ", T->Data);
    }
}

void Traverse(BiTree T) //依次进行先序、中序、后序遍历
{
    PreOrderTraverse(T);
    printf("\n");
    InOrderTraverse(T);
    printf("\n");
    PostOrderTraverse(T);
    printf("\n");
}

Status Search(BiTree T, ElemType key) //寻找key的算法
{
    if (!T)
        return FALSE; //没有找到key值,返回FALSE
    else
    {
        if (T->Data == key)
            return TRUE; //找到key值,返回TRUE
        else if (T->Data > key)
            return Search(T->Lchild, key);
        else
            return Search(T->Rchild, key); //依次往左右子树寻找key值
    }
}

struct Stack //定义栈结构,用于二叉排序树的中序遍历的非递归实现
{
    BiTree base, top;
    int StackSize;
};

void InitStack(Stack &S, int MAXSIZE) //栈的初始化
{
    S.base = new BiTNode[MAXSIZE];
    S.top = S.base;
    S.StackSize = MAXSIZE;
}

Status StackEmpty(Stack S) //判断栈空函数,空则返回TRUE,非空则返回FALSE
{
    if (S.top == S.base)
        return TRUE;
    else
        return FALSE;
}

Status Push(Stack &S, BiTNode e) //栈顶插入元素e
{
    if (S.top - S.base == S.StackSize)
        return ERROR; //栈满
    else
    {
        *S.top = e;
        S.top++;
    }
}

Status Pop(Stack &S, BiTNode &e) //删除栈顶元素并返回给e
{
    if (StackEmpty(S))
        return ERROR; //栈空
    else
    {
        S.top--;
        e = *S.top;
    }
}

void InOrderTraverse_by_Stack(BiTree T, Stack &S) //中序遍历的非递归算法:利用栈实现
{
    BiTree Temp1 = T;               //Temp1用于从根结点开始,依次访问每一个结点
    BiTNode Temp2;                  //Temp2用于访问每一个结点的值
    while (Temp1 || !StackEmpty(S)) //当前结点不为NULL或者栈内仍有结点时,继续遍历
    {
        if (Temp1) //树结点非空,将其入栈,并继续访问其左子树
        {
            Push(S, *Temp1);
            Temp1 = Temp1->Lchild;
        }
        else
        {
            Pop(S, Temp2);
            printf("%d ", Temp2.Data); //左子树为空,输出其值,并开始访问其右子树
            Temp1 = Temp2.Rchild;
        }
    }
}

struct Queue //定义队列结构,实现二叉排序树的层次遍历,
{
    BiTree base;
    int front, rear, MAXQSIZE;
};

void InitQueue(Queue &Q, int MAXQSIZE) //队列初始化
{
    Q.base = new BiTNode[MAXQSIZE];
    Q.front = Q.rear = 0;
    Q.MAXQSIZE = MAXQSIZE;
}

Status QueueEmpty(Queue Q) //判断队列是否为空
{
    if (Q.rear == Q.front)
        return TRUE;
    else
        return FALSE;
}

Status GetHead(Queue &Q, BiTNode &e) //返回队列头元素给e
{
    if (QueueEmpty(Q))
        return ERROR;
    else
        e = Q.base[Q.front];
}

Status InQueue(Queue &Q, BiTNode e) //队列尾插入元素
{
    if ((Q.rear + 1) % Q.MAXQSIZE == Q.front)
        return ERROR;
    else
    {
        Q.base[Q.rear] = e;
        Q.rear = (Q.rear + 1) % Q.MAXQSIZE;
    }
}

Status DeQueue(Queue &Q) //删除队列头元素
{
    if (QueueEmpty(Q))
        return ERROR;
    else
        Q.front = (Q.front + 1) % Q.MAXQSIZE;
}

void LevelTraverse(BiTree T, Queue &Q) //二叉树的层次遍历
{
    BiTNode Temp;          //Temp用于访问每一个结点的值
    InQueue(Q, *T);        //将根结点入队
    while (!QueueEmpty(Q)) //队列非空时,继续遍历
    {
        GetHead(Q, Temp);
        printf("%d ", Temp.Data);
        if (Temp.Lchild)
            InQueue(Q, *(Temp.Lchild));
        if (Temp.Rchild)
            InQueue(Q, *(Temp.Rchild));
        DeQueue(Q);
    }
}

void ChangeBiTNode(BiTree T) //交换二叉树的左右子树算法
{
    if (T) //先对左子树交换其左右子树,再对右子树交换其左右子树,最后对其本身交换左右子树,递归调用即可
    {
        ChangeBiTNode(T->Lchild);
        ChangeBiTNode(T->Rchild);
        BiTree Temp = T->Lchild;
        T->Lchild = T->Rchild;
        T->Rchild = Temp;
    }
}

int BiTreeDepth(BiTree T) //求二叉树深度算法
{
    if (!T)
        return 0; //空子树深度为0
    else
    {
        int LchildDepth = BiTreeDepth(T->Lchild);
        int RchildDepth = BiTreeDepth(T->Rchild);
        if (LchildDepth > RchildDepth)
            return LchildDepth + 1;
        else
            return RchildDepth + 1;
    } //对于每一棵二叉排序树,其深度等于其左右子树中较深的一棵加上其本身的深度1,递归调用即可
}

int LeafNum = 0;
void LeafNumCount(BiTree T) //叶子结点统计算法
{
    if (T)
    {
        if (!T->Lchild && !T->Rchild)
            LeafNum++;
        LeafNumCount(T->Lchild);
        LeafNumCount(T->Rchild);
    }
}

int main()
{
    int ElemNum;
    scanf("%d", &ElemNum); //输入第一行:结点个数
    BiTree T = NULL;       //初始化根节点为NULL
    Create(T, ElemNum);    //根据输入构建二叉排序树
    Traverse(T);           //输出第一行到第三行
    ElemType TargetNum1, TargetNum2;
    scanf("%d", &TargetNum1);              //输入第三行:第一个待查找结点
    scanf("%d", &TargetNum2);              //输入第四行:第二个待查找结点
    printf("%d\n", Search(T, TargetNum1)); //输出第四行:是否找到第一个结点值
    printf("%d\n", Search(T, TargetNum2)); //输出第五行:是否找到第二个结点值
    ElemType Data_to_Insert;
    scanf("%d", &Data_to_Insert);  //输入第五行:待插入结点
    InsertElem(T, Data_to_Insert); //插入新结点
    Traverse(T);                   //输出第六行到第八行
    Stack S;
    InitStack(S, ElemNum);          //初始化一个栈,存储元素为二叉排序树结点
    InOrderTraverse_by_Stack(T, S); //输出第九行:插入新结点后的二叉树中序遍历的非递归形式
    printf("\n");
    Queue Q;
    InitQueue(Q, ElemNum); //初始化一个队列,存储元素为二叉排序树结点
    LevelTraverse(T, Q);   //输出第十行:插入新结点后的二叉树层次遍历序列
    printf("\n");
    ChangeBiTNode(T);               //第一次交换左右子树
    Traverse(T);                    //输出第十一到十三行
    ChangeBiTNode(T);               //第二次交换左右子树
    Traverse(T);                    //输出第十四到十六行
    printf("%d\n", BiTreeDepth(T)); //输出第十七行:二叉树的深度
    LeafNumCount(T);
    printf("%d", LeafNum); //输出第十八行:叶子结点数
    return 0;
}

  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
描述 用函数实现如下二排序算法: (1) 插入新结点 (2) 前序、中序、后序遍历二 (3) 中序遍历的非递归算法 (4) 层次遍历二 (5) 在二中查找给定关键字(函数返回值为成功1,失败0) (6) 交换各结点的左右子 (7) 求二的深度 (8) 叶子结点数 Input 第一行:准备建的结点个数n 第二行:输入n个整数,用空格分隔 第三行:输入待查找的关键字 第四行:输入待查找的关键字 第五行:输入待插入的关键字 Output 第一行:二的先序遍历序列 第二行:二的中序遍历序列 第三行:二的后序遍历序列 第四行:查找结果 第五行:查找结果 第六行~第八行:插入新结点后的二的先、中、序遍历序列 第九行:插入新结点后的二的中序遍历序列(非递归算法) 第十行:插入新结点后的二的层次遍历序列 第十一行~第十三行:第一次交换各结点的左右子后的先、中、后序遍历序列 第十四行~第十六行:第二次交换各结点的左右子后的先、中、后序遍历序列 第十七行:二的深度 第十八行:叶子结点数 Sample Input 7 40 20 60 18 50 56 90 18 35 30 Sample Output 40 20 18 60 50 56 90 18 20 40 50 56 60 90 18 20 56 50 90 60 40 1 0 40 20 18 30 60 50 56 90 18 20 30 40 50 56 60 90 18 30 20 56 50 90 60 40 18 20 30 40 50 56 60 90 40 20 60 18 30 50 90 56 40 60 90 50 56 20 30 18 90 60 56 50 40 30 20 18 90 56 50 60 30 18 20 40 40 20 18 30 60 50 56 90 18 20 30 40 50 56 60 90 18 30 20 56 50 90 60 40 4 4

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值