平衡二叉树 c/c++实现

一直觉得平衡二叉树是非常麻烦的数据结构,关于树的旋转非常麻烦,最近特殊情况学了一下,参考了网上的代码,写这个让我对指针有了更加深入的了解,感觉收益匪浅,恶心的地方就是,当我程序无法运行出我的期望结果时,我debug就苦逼了,真的比较苦逼,一点小的注释在代码中,目前就自己出了几组样例测试了一下,感觉没什么大问题,比较低级,勿喷,如果发现代码中的bug,欢迎留言告知


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct stud{
   int val;
   int height;
   struct stud* left;
   struct stud* right;
};

stud * Empty(stud * cur)//删除树
{
    if(cur==NULL) return NULL;
    Empty(cur->left);
    Empty(cur->right);
    free(cur);
    return NULL;
}

inline int Height(stud * cur)//计算高度
{
    if(cur==NULL) return 0;
    return cur->height;
}

stud* LLchange(stud * cur) //LL旋转操作
{
     stud * temp=cur->left;
     cur->left=temp->right;
     temp->right=cur;

     cur->height=max(Height(cur->left),Height(cur->right))+1;
     temp->height=max(Height(temp->left),Height(temp->right))+1;
     return temp;
}

stud* RRchange(stud* cur)//RR旋转操作
{
    stud * temp=cur->right;
    cur->right=temp->left;
    temp->left=cur;

    cur->height=max(Height(cur->left),Height(cur->right))+1;
    temp->height=max(Height(temp->left),Height(temp->right))+1;
    return temp;
}

stud* LRchange(stud* cur)  //LR旋转操左
{
     cur->left=RRchange(cur->left);
     return LLchange(cur);
}

stud* RLchange(stud * cur)
{
    cur->right=LLchange(cur->right);
    return RRchange(cur);
}

stud* Insert(stud * cur,int va)
{
     if(cur==NULL) //如果到底了,那么创建新的节点
     {
         cur=(stud*)malloc(sizeof(stud));
         cur->left=cur->right=NULL;
         cur->val=va;
         cur->height=1;
         return cur;
     }
     if(cur->val==va) return cur;//有相同的
     if(cur->val>va)
     {
         cur->left=Insert(cur->left,va);//注意这里是cur->left=   ,请认真思考为什么这么写
         if(Height(cur->left)-Height(cur->right)==2)//插入后看是否平衡,如果不平衡显然是插入的那一边高度大
         {
              if(va<cur->left->val)//判断是LL还是LR,即插入的是left节点的left 还是right
                  cur=LLchange(cur);
              else
                  cur=LRchange(cur);
         }
     }
     else//同理
     {
        cur->right=Insert(cur->right,va);
        if(Height(cur->right)-Height(cur->left)==2)
        {
            if(va>cur->right->val)
                cur=RRchange(cur);
            else
                cur=RLchange(cur);
        }
     }
     cur->height=max(Height(cur->left),Height(cur->right))+1;
     return cur;
}

stud * adjust(stud *cur)//对于删除了一个节点,那么是需要判断是否还是平衡,如果不平衡,就要调整
{
     if(cur==NULL) return NULL;
     //printf("adjust %d\n",cur->val);
     if(Height(cur->left)-Height(cur->right)==2)//哪边高度高,那么调节哪一边
     {
         if(Height(cur->left->left)>=Height(cur->left->right))
             cur=LLchange(cur);
         else
            cur=LRchange(cur);
     }
     if(Height(cur->right)-Height(cur->left)==2)
     {
         if(Height(cur->right->right)>=Height(cur->right->left))
              cur=RRchange(cur);
         else
            cur=RLchange(cur);
     }
     cur->height=max(Height(cur->left),Height(cur->right))+1;
     return cur;
}

stud * Delete(stud * cur,int va)
{
    if(cur==NULL) return NULL;
    if(cur->val==va)//如果找到删除节点
    {
        if(cur->right==NULL)//如果该节点的右孩子为NULL,那么直接删除
        {
            stud * temp=cur;
            cur=cur->left;
            free(temp);
        }
        else//否则,将其右子树的最左孩子作为这个节点,并且递归删除这个节点的值
        {
           stud * temp;
           temp=cur->right;
           while(temp->left)
              temp=temp->left;
           cur->val=temp->val;
           cur->right=Delete(cur->right,cur->val);
           cur->height=max(Height(cur->right),Height(cur->left))+1;
        }
        return cur;
    }

    if(cur->val>va)//调节删除节点后可能涉及的节点
        cur->left=Delete(cur->left,va);

    if(cur->val<va)
        cur->right=Delete(cur->right,va);

    cur->height=max(Height(cur->left),Height(cur->right))+1;

    if(cur->left)
        cur->left=adjust(cur->left);

    if(cur->right)
        cur->right=adjust(cur->right);

    if(cur) cur=adjust(cur);
    return cur;
}

void show(stud *cur)//前序遍历方便看树的结果
{
    if(cur==NULL) return ;
    printf("%d %d\n",cur->val,cur->height);
    show(cur->left);
    show(cur->right);
}

int main()
{
    int i,j;
    int n,x;
    stud * root=NULL;
    while(~scanf("%d",&n))
    {
         root=Empty(root);
         for(int i=0;i<n;i++)
         {
             scanf("%d",&x);
             root=Insert(root,x);
         }
         printf("\n");
         show(root);
         printf("\n");
         scanf("%d",&x);
         root=Delete(root,x);
         show(root);
    }
    return 0;
}

/*

5
5 3 6 2 4
6


4
5 3 6 7
6

4
5 3 6 7
3

5
5 4 6 3 2
3

5
5 4 6 2 3
3

*/






  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
平衡二叉树(AVL树)是一种自平衡的二叉搜索树,它保持左右子树的高度差不超过1。下面是用C语言实现平衡二叉树的示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义二叉树节点 struct Node { int data; struct Node* left; struct Node* right; int height; // 节点的高度 }; // 获取节点的高度 int getHeight(struct Node* node) { if (node == NULL) return 0; return node->height; } // 获取两个数中较大的数 int max(int a, int b) { return (a > b) ? a : b; } // 创建一个新节点 struct Node* newNode(int data) { struct Node* node = (struct Node*)malloc(sizeof(struct Node)); node->data = data; node->left = NULL; node->right = NULL; node->height = 1; // 新节点的高度为1 return node; } // 右旋操作 struct Node* rightRotate(struct Node* y) { struct Node* x = y->left; struct Node* T2 = x->right; // 执行旋转操作 x->right = y; y->left = T2; // 更新节点的高度 y->height = max(getHeight(y->left), getHeight(y->right)) + 1; x->height = max(getHeight(x->left), getHeight(x->right)) + 1; return x; } // 左旋操作 struct Node* leftRotate(struct Node* x) { struct Node* y = x->right; struct Node* T2 = y->left; // 执行旋转操作 y->left = x; x->right = T2; // 更新节点的高度 x->height = max(getHeight(x->left), getHeight(x->right)) + 1; y->height = max(getHeight(y->left), getHeight(y->right)) + 1; return y; } // 获取节点的平衡因子 int getBalanceFactor(struct Node* node) { if (node == NULL) return 0; return getHeight(node->left) - getHeight(node->right); } // 将节点插入到平衡二叉树中 struct Node* insert(struct Node* node, int data) { // 执行二叉搜索树的插入操作 if (node == NULL) return newNode(data); if (data < node->data) node->left = insert(node->left, data); else if (data > node->data) node->right = insert(node->right, data); else // 不允许插入重复的节点 return node; // 更新节点的高度 node->height = 1 + max(getHeight(node->left), getHeight(node->right)); // 获取当前节点的平衡因子 int balanceFactor = getBalanceFactor(node); // 进行平衡操作 // 左左情况,进行右旋操作 if (balanceFactor > 1 && data < node->left->data) return rightRotate(node); // 右右情况,进行左旋操作 if (balanceFactor < -1 && data > node->right->data) return leftRotate(node); // 左右情况,先进行左旋操作,再进行右旋操作 if (balanceFactor > 1 && data > node->left->data) { node->left = leftRotate(node->left); return rightRotate(node); } // 右左情况,先进行右旋操作,再进行左旋操作 if (balanceFactor < -1 && data < node->right->data) { node->right = rightRotate(node->right); return leftRotate(node); } // 返回未经调整的节点指针 return node; } // 中序遍历平衡二叉树(升序输出) void inOrder(struct Node* root) { if (root != NULL) { inOrder(root->left); printf("%d ", root->data); inOrder(root->right); } } // 释放二叉树节点的内存 void freeTree(struct Node* root) { if (root != NULL) { freeTree(root->left); freeTree(root->right); free(root); } } int main() { struct Node* root = NULL; // 插入示例数据 root = insert(root, 10); root = insert(root, 20); root = insert(root, 30); root = insert(root, 40); root = insert(root, 50); root = insert(root, 25); // 中序遍历平衡二叉树 printf("中序遍历结果:"); inOrder(root); printf("\n"); // 释放二叉树内存 freeTree(root); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值