二叉排序树C语言实现

版权声明:本博客为个人原创,转载请注明出处 https://blog.csdn.net/qq_33826564/article/details/81900744

目录


说明


  • 用C语言实现数据结构,二叉排序树,可动态插入二叉树结点,遍历二叉树结点到一个链表。

代码


#include<stdio.h>
#include<stdlib.h>
typedef int Tp;

//链表
typedef struct node
{
    Tp data;
    struct node * ltree, *rtree;

}Node,*Tree;

//排序二叉树
typedef struct listnode
{
    Tp data;
    struct listnode * nextnode;

}lNode,*List;



//往排序二叉树送入值
bool insertTree(Tree * T, const Tp data)
{
    Node * pnode = (Node*)malloc(sizeof(Node));
    //printf("pnode add: %p\n", pnode);

    pnode->data = data;
    pnode->ltree = NULL;
    pnode->rtree = NULL;



    if (!(*T))
    {
        *T = pnode;
        return true;
    }
    else
    {



        if (pnode->data < (*T)->data )//若小于根节点值
        {
            if ((*T)->ltree)//若左子树不为空,继续递归
            {
                Node pnodecpy = *pnode;//由于要递归,防止内存泄漏,这里需要将申请的内存堆转移出来,然后清空这个堆内存
                free(pnode);
                pnode = NULL;

                insertTree(&((*T)->ltree), pnodecpy.data);

            }
            else//若左子树为空,直接赋值
            {
                (*T)->ltree = pnode;
                return true;
            }
        }
        else if (pnode->data > (*T)->data)//若大于根节点值
        {
            if ((*T)->rtree)//若右子树不为空,继续递归
            {
                Node pnodecpy = *pnode;//由于要递归,防止内存泄漏,这里需要将申请的内存堆转移出来,然后清空这个堆内存
                free(pnode);
                pnode = NULL;

                insertTree(&((*T)->rtree), pnodecpy.data);


            }
            else//若右子树为空,直接赋值
            {
                (*T)->rtree = pnode;
                return true;
            }
        }
        else
        {
            return true;
        }

    }
}
//在链表尾部插入新元素函数
bool inserList(List *list, Tp data)
{
    lNode *datanode = (lNode*)malloc(sizeof(lNode));

    datanode->data = data;
    datanode->nextnode = NULL;

    if (!(*list))//若链表为空
    {
        *list = datanode;
        return true;

    }
    else//若链表不为空
    {
        if ((*list)->nextnode == NULL)//若插入为本链表的第二个元素
        {
            (*list)->nextnode = datanode;
            return true;
        }
        else//若插入为本链表的第3个元素及以上,迭代至最后一个元素
        {
            lNode nodecpy = *datanode;
            free(datanode);
            datanode = NULL;

            return inserList(&((*list)->nextnode), nodecpy.data);
        }
    }
}
//中序遍历二叉树函数,将遍历结果保存在一个链表里
bool inorderTraversal(Tree t, List *l)
{
    if (!t)
    {
        //printf("树为空");
        return false;
    }
    else
    {
        if (t->ltree==NULL&&t->rtree==NULL)
        {
            printf("  %d  ", t->data);
            return inserList(l, t->data);

        }
        else
        {
            inorderTraversal(t->ltree, l);//访问左子树
            printf("  %d  ", t->data);
            bool i = inserList(l, t->data);//访问根节点
            inorderTraversal(t->rtree, l);//访问右子树
            return true;
        }
    }
}
int main()
{



    Tree t = NULL;
    List l = NULL;

    //链表初始化



    bool b = false;





    b = insertTree(&t, 44);
    b = insertTree(&t, 55);
    b = insertTree(&t, 33);
    b = insertTree(&t, 20);
    b = insertTree(&t, 45);
    b = insertTree(&t, 37);



    printf("树的地:%p\n左子树地址:%p\n右子树地址:%p\n", t, t->ltree, t->rtree);



    printf("\n中序遍历结果(从小到大):");
    b = inorderTraversal(t, &l);

    printf("\n中序遍历结果(保存在链表):");

    printf("链表的头节点地址: %p\n", l);
    system("pause");
    return 0;
}

运行结果
这里写图片描述

一些思考


  • 在递归前,若是涉及在堆空间上动态开辟内存(如本文代码inserList() insertTree() 函数的malloc操作),为了防止递归的过程中不断开辟新堆空间而造成的浪费和风险,须在递归前将申请的内存中的变量保存下来(栈),再去递归。

  • 从无到有生成一个动态的数据的函数,传入参数须传入二级指针,以实现malloc,因为malloc 须赋值返回给一个指针变量,即修改一个指针变量,众说周知,修改一个指针变量需传入指针的指针,即二级指针来修改。

  • 根据上一条的结论,若函数须读,可仅仅传入一个值(值传递),若函数须读写,可以考虑传入一个指针(指针传递),若写一个值,传入指针,若写一个指针(地址,原或为NULL),传入一个二级指针,以此类推。

猜你喜欢

转载自blog.csdn.net/qq_33826564/article/details/81900744