C语言实现二叉树的基本功能

两盒软妹~` 提交于 2019-11-30 09:13:00

本程序实现二叉树的如下功能
1、以先序序列和中序序列构造二叉树
2、以层序序列和中序序列构造二叉树
3、先序遍历、中序遍历、后序遍历、层序遍历
4、求二叉树高度
5、验证这个二叉树是否具备这样的性质:任何一个子树中的结点集合,树根结点的值总是最小。(按字母序)
6、拷贝二叉树
7、将二叉树左右子树交换
8、销毁二叉树
9、删除值为x的节点及其全部子孙

binary_tree.h文件
注:queue.h文件在这里

#ifndef __BINARY_TREE_H__
#define __BINARY_TREE_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "queue.h"

#define SIZE_bt 1024

struct bt
{
    char data;
    struct bt *lchild, *rchild;
};

struct bt *PreInBuild(char *pre, char *in);//以先序序列和中序序列构造二叉树
struct bt *LevelInBuild(char *level, char *in);//以层序序列和中序序列构造二叉树
void PreOdTraversal(struct bt *t, char *result);//先序遍历
void InOdTraversal(struct bt *t, char *result);//中序遍历
void PostOdTraversal(struct bt *t, char *result);//后序遍历
void LevelOdTraversal(struct bt *t, char *result);//层序遍历
int Height(struct bt *t);//求二叉树高度
bool IsRootSmallest(struct bt *t);//验证这个二叉树是否具备这样的性质:任何一个子树中的结点集合,树根结点的值总是最小。(按字母序)
struct bt *CopyTree(struct bt *source);//拷贝二叉树
void ExchangeLRChild(struct bt *t);//将二叉树左右子树交换
void DestroyTree(struct bt *t);//销毁二叉树
void Cut(struct bt *t, char x);//删除值为x的节点及其全部子孙

#endif /* __BINARY_TREE_H__ */

binary_tree.c文件

#include "binary_tree.h"

char traversal_result[SIZE_bt];//用于存储遍历结果

struct bt *PreInBuild(char *pre, char *in)
{
    int in_len;
    char *c, *d;
    char *lin, *rin, *lpre, *rpre;
    struct bt *root;

    root = (struct bt *)malloc(sizeof(struct bt));
    if (root == NULL)
        exit(-1);//内存不足
    root->lchild = NULL;
    root->rchild = NULL;

    if (*pre == '\0' && *in == '\0')
        return NULL;
    if (*pre == '\0' || *in == '\0')
        exit(2);//未知错误
    
    root->data = *pre;
    in_len = strlen(in);//截断in之前先记录其长度
    for (c = in; *c != '\0'; c++)
        if (*c == root->data)//分割左、右子树的中序序列
        {
            *c = '\0';
            break;
        }
    if ((c - in) == in_len)
        exit(1);//中序序列中未出现根节点
    
    lin = in;
    rin = c + 1;
    //拷贝左子树的前序序列
    lpre = (char *)malloc(strlen(lin) + 1);
    d = lpre;
    for (c = pre + 1; (c - pre - 1) < strlen(lin); c++)
        *d++ = *c;
    *d = '\0';
    rpre = c;
    
    root->lchild = PreInBuild(lpre, lin);
    root->rchild = PreInBuild(rpre, rin);

    return root;
}

struct bt *LevelInBuild(char *level, char *in)
{
    int in_len;
    char *c, *d, *e, *f;//遍历字符串需要的指针
    char *lin, *rin, *llevel, *rlevel;
    struct bt *root;

    root = (struct bt *)malloc(sizeof(struct bt));
    if (root == NULL)
        exit(-1);//内存不足
    root->lchild = NULL;
    root->rchild = NULL;

    if (*level == '\0' && *in == '\0')
        return NULL;
    if (*level == '\0' || *in == '\0')
        exit(2);//未知错误

    root->data = *level;
    in_len = strlen(in);//截断in之前先记录其长度
    for (c = in; *c != '\0'; c++)
        if (*c == root->data)
        {
            *c = '\0';
            break;
        }
    if ((c - in) == in_len)
        exit(1);//中序序列中未出现根节点
    
    lin = in;
    rin = c + 1;
    llevel = (char *)malloc(strlen(lin) + 1);
    rlevel = (char *)malloc(strlen(rin) + 1);
    //把层序序列中左子树和右子树的部分按原来的顺序分离开
    d = lin;
    e = llevel;
    f = rlevel;
    for (c = level + 1; *c != '\0'; c++)
    {
        for (d = lin; *d != '\0'; d++)
            if (*d == *c)
            {
                *e++ = *c;
                break;
            }

        if (*d == '\0')
        //说明遍历完左子树的所有元素都没有找到与c相同的元素,说明c在右子树中
            *f++ = *c;
    }
    *e = '\0';
    *f = '\0';
    //分离完毕

    root->lchild = LevelInBuild(llevel, lin);
    root->rchild = LevelInBuild(rlevel, rin);

    return root;
}

static void PreOrder(struct bt *t, char *result, int *p)
{
    if (t == NULL)
        return;
    if (*p == SIZE_bt)
        exit(-1);//储存遍历结果的数组溢出
    
    result[(*p)++] = t->data;
    PreOrder(t->lchild, result, p);
    PreOrder(t->rchild, result, p);
}

void PreOdTraversal(struct bt *t, char *result)
{
    int pos = 0;
    //为了避免函数在递归调用时记录位置信息的变量被反复初始化,需要将递归部分单独写为一个函数
    PreOrder(t, result, &pos);
    result[pos] = '\0';
}

static void InOrder(struct bt *t, char *result, int *p)
{
    if (t == NULL)
        return;
    if (*p == SIZE_bt)
        exit(-1);//储存遍历结果的数组溢出
    
    InOrder(t->lchild, result, p);
    result[(*p)++] = t->data;
    InOrder(t->rchild, result, p);
}

void InOdTraversal(struct bt *t, char *result)
{
    int pos = 0;
    //为了避免函数在递归调用时记录位置信息的变量被反复初始化,需要将递归部分单独写为一个函数
    InOrder(t, result, &pos);
    result[pos] = '\0';
}

static void PostOrder(struct bt *t, char *result, int *p)
{
    if (t == NULL)
        return;
    if (*p == SIZE_bt)
        exit(-1);//储存遍历结果的数组溢出
    
    PostOrder(t->lchild, result, p);
    PostOrder(t->rchild, result, p);
    result[(*p)++] = t->data;
}

void PostOdTraversal(struct bt *t, char *result)
{
    int pos = 0;
    //为了避免函数在递归调用时记录位置信息的变量被反复初始化,需要将递归部分单独写为一个函数
    PostOrder(t, result, &pos);
    result[pos] = '\0';
}

static void LevelOrder(struct bt *t, struct queue *q, char *result, int *p)
{
    struct bt *m;

    InQueue(q, t);

    while (!IsEmptyQueue(q))
    {
        if (*p == SIZE_bt)
            exit(-1);//储存遍历结果的数组溢出

        m = OutQueue(q);
        if (m != NULL)
        {
            result[(*p)++] = m->data;
            InQueue(q, m->lchild);
            InQueue(q, m->rchild);
        }
    }
}

void LevelOdTraversal(struct bt *t, char *result)
{
    int pos = 0;
    struct queue *q;

    q = InitQueue();
    LevelOrder(t, q, result, &pos);
    DestroyQueue(q);
    result[pos] = '\0';
}

int Height(struct bt *t)
{
    int height, lheight, rheight;

    if (t == NULL)
        return 0;
    
    lheight = Height(t->lchild);
    rheight = Height(t->rchild);

    return (lheight > rheight ? lheight : rheight) + 1;
}

static void ChangeRootSmallestFlag(struct bt *t, bool *flag)
{
    if (*flag == false)
        return;
    if (t == NULL)
        return;
    
    if (t->lchild == NULL && t->rchild == NULL)
        return;
    else if (t->lchild == NULL)
    {
        if (t->data > t->rchild->data)
        {
            *flag = false;
            return;
        }
    }
    else if (t->rchild == NULL)
    {
        if (t->data > t->lchild->data)
        {
            *flag = false;
            return;
        }
    }
    else if (t->data > t->lchild->data || t->data > t->rchild->data)
    {
        *flag = false;
        return;
    }

    ChangeRootSmallestFlag(t->lchild, flag);
    ChangeRootSmallestFlag(t->rchild, flag);
}

bool IsRootSmallest(struct bt *t)
{
    bool root_smallest_flag = true;
    ChangeRootSmallestFlag(t, &root_smallest_flag);
    return root_smallest_flag;
}

struct bt *CopyTree(struct bt *source)
{
    //利用源二叉树的先序和中序序列构造目标二叉树,达到拷贝二叉树的目的
    char *pre, *in;
    struct bt *dest;

    PreOdTraversal(source, traversal_result);
    pre = (char *)malloc(strlen(traversal_result) + 1);
    strcpy(pre, traversal_result);

    InOdTraversal(source, traversal_result);
    in = (char *)malloc(strlen(traversal_result) + 1);
    strcpy(in, traversal_result);

    dest = PreInBuild(pre, in);

    free(pre);
    free(in);

    return dest;
}

void ExchangeLRChild(struct bt *t)
{
    struct bt *temp;

    if (t == NULL)
        return;
    
    temp = t->lchild;
    t->lchild = t->rchild;
    t->rchild = temp;

    ExchangeLRChild(t->lchild);
    ExchangeLRChild(t->rchild);
}

void DestroyTree(struct bt *t)
{
    //通过层序遍历销毁二叉树
    struct bt *m;
    struct queue *q;

    q = InitQueue();
    InQueue(q, t);

    while (!IsEmptyQueue(q))
    {
        m = OutQueue(q);
        if (m != NULL)
        {
            InQueue(q, m->lchild);
            InQueue(q, m->rchild);
            free(m);
        }
    }
    DestroyQueue(q);
}

void Cut(struct bt *t, char x)
{
    struct bt *to_destory;

    if (t == NULL)
        return;
    
    if (t->lchild == NULL && t->rchild == NULL)
        return;
    else if (t->lchild == NULL)
    {
        if (t->rchild->data == x)
        {
            to_destory = t->rchild;
            t->rchild = NULL;
            DestroyTree(to_destory);
        }
    }
    else if (t->rchild == NULL)
    {
        if (t->lchild->data == x)
        {
            to_destory = t->lchild;
            t->lchild = NULL;
            DestroyTree(to_destory);
        }
    } 
    else if (t->lchild->data == x)
    {
        to_destory = t->lchild;
        t->lchild = NULL;
        DestroyTree(to_destory);
    }
    else if (t->rchild->data == x)
    {
        to_destory = t->rchild;
        t->rchild = NULL;
        DestroyTree(to_destory);
    }

    Cut(t->lchild, x);
    Cut(t->rchild, x);
}

main.c文件

#include "binary_tree.h"

int main()
{
    extern char traversal_result[SIZE_bt];
    char traversal[SIZE_bt], in[SIZE_bt];//traversal为除中序遍历以外的任意遍历
    struct bt *tree1, *tree2;

    printf("Enter level-order traversal:");
    scanf("%s", traversal);
    getchar();
    printf("Enter in-order    traversal:");
    scanf("%s", in);
    getchar();
    putchar('\n');

    tree1 = LevelInBuild(traversal, in);
    tree2 = CopyTree(tree1);
    ExchangeLRChild(tree2);

    printf("Tree 1:\n");
    PreOdTraversal(tree1, traversal_result);
    printf("Pre-order   traversal:%s\n", traversal_result);
    InOdTraversal(tree1, traversal_result);
    printf("In-order    traversal:%s\n", traversal_result);
    PostOdTraversal(tree1, traversal_result);
    printf("Post-order  traversal:%s\n", traversal_result);
    LevelOdTraversal(tree1, traversal_result);
    printf("Level-order traversal:%s\n", traversal_result);
    printf("Height:%d\n", Height(tree1));
    printf("Have quality:%s\n", IsRootSmallest(tree1) ? "YES." : "NO.");

    printf("\nTree 2:\n");
    PreOdTraversal(tree2, traversal_result);
    printf("Pre-order   traversal:%s\n", traversal_result);
    InOdTraversal(tree2, traversal_result);
    printf("In-order    traversal:%s\n", traversal_result);
    PostOdTraversal(tree2, traversal_result);
    printf("Post-order  traversal:%s\n", traversal_result);
    LevelOdTraversal(tree2, traversal_result);
    printf("Level-order traversal:%s\n", traversal_result);

    printf("\nEnter a node to cut:");
    Cut(tree1, getchar());
    printf("Tree 1(after cut):\n");
    PreOdTraversal(tree1, traversal_result);
    printf("Pre-order   traversal:%s\n", traversal_result);
    InOdTraversal(tree1, traversal_result);
    printf("In-order    traversal:%s\n", traversal_result);
    PostOdTraversal(tree1, traversal_result);
    printf("Post-order  traversal:%s\n", traversal_result);
    LevelOdTraversal(tree1, traversal_result);
    printf("Level-order traversal:%s\n", traversal_result);

    DestroyTree(tree1);
    DestroyTree(tree2);

    system("pause");
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!