c语言二叉树非递归实现

有了递归实现为啥还要用非递归呢?你会不会有疑惑?如果有,请接着看。

函数的调用需要用到栈,一个应用分配到的栈空间一般为1M大小,在数据很大的情况会造成栈溢出,所以要少用递归。

不用递归实现的原理是模拟栈的运行机制------先进后出,如果这个不会的话,可以看我写的数组模拟栈(现在还没写)。

头文件

#ifdef __cplusplus
extern "C" {
#endif

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//bool
#include <stdbool.h>
//字节封装的模拟栈
#include "SeqStack.h"
/* 
*自定义结构体必须包含BiNode结构体,且位于结构体最上方
*struct Person
*{

* struct BiNode data;

* int age;
  };
  *增加必须提供返回值int型的比较函数,参数为(void* ,void*),函数内强转自己定义的结构体
  *int init(void* d1, void* d2)
  *{

* struct Person* p1 = (struct Person*)d1;

* struct Person* p2 = (struct Person*)d2;

* int tmp = (p1->age) - (p2->age);

* return tmp;
  *}
  *遍历需要提供遍历函数,参数为void*,函数内强转自己定义的结构体
  *void myprint(void* node)
  *{

* if (NULL == node)

* {

* return;

* }

* struct Person* p = (struct Person*)node;

* 

* myprint(p->data.lchild);
  *
  *printf("%c\n", p->age);
  *

* myprint(p->data.rchild);
  *}
  *
  */
  //定义结构体
  struct BiNode {
  //父节点用于删除
    struct BiNode* parent;
    struct BiNode* rchild;
    struct BiNode* lchild;
    //用于遍历
    bool flag;
  };

  //初始化树,外部调用
  void* Init_BBTree();
  //插入根数据,外部调用
  void Insert_BBTree(void* tree,void *data,int(*compare)(void *,void *));
  //返回树高度,内部使用
  int getHight(struct BiNode* node);
  //左旋,内部使用
  struct BiNode* LeftHand(struct BiNode* data);
  //右旋,内部使用
  struct BiNode* RightHand(struct BiNode* data);
  //平衡树节点,内部使用
  struct BiNode* AdjTree(struct BiNode* data);
  //遍历二叉树
  void foreachTree(void* tree, void(*myprint)(void*));
  //删除节点,外部使用
  void RemoveTree(void* tree, void* data,int(*compare)(void* ,void*));
  //销毁,外部使用
  void DestroyTree(void* tree);

  

#ifdef __cplusplus
}
#endif

初始化

void* Init_BBTree()
{//开辟一个新空间
    struct ABLTree* tree = malloc(sizeof(struct ABLTree));
    //开辟失败返回NULL
    if (NULL == tree)
    {
        return NULL;
    }//初始化根节点为NULL
    tree->root = NULL;
    //返回空间指针
    return tree;
}

插入数据

void Insert_BBTree(void* tree, void* data, int(*compare)(void*, void*))
{//判断参数是否为空
    if (NULL == tree)
    {
        return;
    }
    if (NULL == data)
    {
        return;
}
    if (NULL == compare)
    {
        return;
    }
    //强转
    struct ABLTree* newtree = (struct ABLTree*)tree;
    //判断根节点是否为空,若为空,把数据赋值给根节点,并返回
    if (NULL == newtree->root)
    {
        newtree->root = data;
        return;
    }
    //不为空,初始化一个栈
    void* stack = Init_SeqStack();
    //把根节点压入栈中
    Push_SeqStack(stack, newtree->root);
    //判断栈中是否还有数据
    while (Size_SeqStack(stack) > 0)
    {//获取栈顶元素
        struct BiNode* info = (struct BiNode*)Top_SeqStack(stack);
        //弹出栈顶元素
        Pop_SeqStack(stack);
        //判断栈顶元素与数据的大小
        if(compare(info,data)>0)
        {//如果栈顶元素大,判断栈顶元素的左子节点是否为空
            if (NULL == info->lchild)
            {//为空,赋值并返回
                info->lchild = data;
                info->lchild->parent = info;
                break;
            }
            //不为空,把左子节点压入栈中,并中断当前循环,进入下次循环
            Push_SeqStack(stack, info->lchild);
            continue;
        }
        else
        {//如果栈顶元素小,判断栈顶元素的右子节点是否为空
            if (NULL == info->rchild)
            {//为空,赋值并返回
                info->rchild = data;
                info->rchild->parent = info;
                break;
            }
                    //不为空,把右子节点压入栈中,并中断当前循环,进入下次循环
            Push_SeqStack(stack, info->rchild);
            continue;
        }

    }
    //销毁栈
    Destroy_SeqStack(stack);
    //平衡树节点
    newtree->root = AdjTree(newtree->root);
}

调节平衡

//获取树高度
int getHight(struct BiNode* node)
{
    if (NULL == node)
    {
        return 0;
    }
    int n = getHight(node->lchild);
    int m = getHight(node->rchild);
    return n > m ? ++n : ++m;
}

//左旋转
struct BiNode* LeftHand(struct BiNode* data)
{
    struct BiNode* temp = data;
     
    data = data->rchild;
    data->parent = temp->parent;
    struct BiNode* pCurror = data->lchild;
    temp->rchild = data->lchild;
    if (pCurror)
    {
        pCurror->parent = temp;
    }

    data->lchild = temp;
    temp->parent=data;
    return data;
}
//右旋转
struct BiNode* RightHand(struct BiNode* data)
{
    struct BiNode* temp = data;
    data = data->lchild;
    data->parent= temp->parent;
    struct BiNode* pCurror = data->rchild;
    temp->lchild = data->rchild;
    if (data->rchild)
    {
        pCurror->parent = temp;
    }
    data->rchild = temp;

    temp->parent = data;
    
    return data;
}
//平衡节点
struct BiNode* AdjTree(struct BiNode* data)
{//判断节点是否为空,为空返回该节点
    if (NULL == data)
    {
        return data;
    }
    //判断子节点是否有一个不为空,都为空不需要调整
    if (NULL != data->lchild || NULL != data->rchild)
    {
    //初始化栈
        void* stack = Init_SeqStack();
        //把节点压入栈
        Push_SeqStack(stack, data);
        //栈中节点不为0就循环
        while (Size_SeqStack(stack) > 0)
        {//获取栈顶元素
            struct BiNode* info = (struct BiNode*)Top_SeqStack(stack);
            //判断右子节点是否为空
            if (NULL != info->rchild)
            {//不为空,压入栈中
                Push_SeqStack(stack, info->rchild);
            }
//判断左子节点是否为空
            if (NULL != info->lchild)
            {
            //不为空,压入栈中
                Push_SeqStack(stack, info->lchild);
            }
            //弹出栈顶元素
            Pop_SeqStack(stack);
            
                //判断节点左右子节点高度差
                    int l = getHight(info->lchild);
                    int r = getHight(info->rchild);
                    //如果左高度-右高度大于1,要进行右旋
                    if ((l - r) > 1)
                    {
                        struct BiNode* d1 = info->lchild;
                        int ll = getHight(d1->lchild);
                        int rl = getHight(d1->rchild);
                        //如果子节点的右节点高度大于左节点高度,要先进行左旋
                        if (rl > ll)
                        {//左旋
                            info->lchild = LeftHand(d1);
                        }
                        //右旋
                        info = RightHand(info);
                    }
                    //右高度比左高度大1,要进行左旋
                    else if ((r - l) > 1)
                    {
                        struct BiNode* d1 = info->rchild;

                        int ll = getHight(d1->lchild);
                        int rl = getHight(d1->rchild);
                        //如果左子节点高度大于右子节点高度
                        if (ll > rl)
                        {//右旋
                            info->rchild = RightHand(d1);
                        }
                        //左旋
                        info = LeftHand(info);
                    }
                                        
        
                    返回交换后的节点        
                return info;
            }
            //销毁栈
        Destroy_SeqStack(stack);
    
        }
    //不满足条件,返回传入的节点
    return data;
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容