14 C语言实现平衡二叉树

//LL型失衡 右旋
//RR型失衡 左旋
//RL型失衡 先右旋 再左旋
//LR型失衡 先左旋 再右旋
#include "stdio.h"
#include "stdlib.h"typedef int ElemType;
typedef struct node {ElemType data;int height;struct node *left;struct node *right;
} Node;Node *create_node(ElemType value) {Node *node = (Node *) malloc(sizeof(Node));if (node == NULL) {exit(-1);}node->data = value;node->height = 1;node->left = NULL;node->right = NULL;return node;
}//获取树的高度
int getHeight(Node *node) {if (node == NULL) {return 0;}return node->height;
}int max(int a, int b) {return a > b ? a : b;
}int getTreeHeight(Node *node) {if (node == NULL) {return 0;}return max(getTreeHeight(node->left), getTreeHeight(node->right)) + 1;
}//左旋转
Node *leftRotate(Node *root) {Node *newroot = root->right;//当前结点的右子节点作为新的树根root->right = newroot->left;//将新树根的左子树作为原根的右子树newroot->left = root;//将原根作为新根的左子树root->height = 1 + max(getHeight(root->left), getHeight(root->right));newroot->height = 1 + max(getHeight(newroot->left), getHeight(newroot->right));return newroot;
}//右旋转
Node *rightRotate(Node *root) {Node *newroot = root->left;//当前结点的左节点作为新的树根root->left = newroot->right;//将新节点右边的子树作为原根结点的左子树newroot->right = root;//新节点的右子树为原根结点root->height = 1 + max(getHeight(root->left), getHeight(root->right));newroot->height = 1 + max(getHeight(newroot->left), getHeight(newroot->right));return newroot;
}//获取平衡因子
int getBalance(Node *node) {return getHeight(node->left) - getHeight(node->right);
}//插入
Node *insert_node(Node *node, ElemType value) {if (node == NULL) {return create_node(value);}if (node->data > value) {node->left = insert_node(node->left, value);} else if (node->data < value) {node->right = insert_node(node->right, value);} else {return node;}//更新树高node->height = 1 + max(getHeight(node->left), getHeight(node->right));// 获取平衡因子int balance = getBalance(node);//LL型失衡if (balance > 1 && getBalance(node->left) > 0) {return rightRotate(node);}//LR型失衡if (balance > 1 && getBalance(node->left) < 0) {node->left = leftRotate(node->left);return rightRotate(node);}//RR型失衡if (balance < -1 && getBalance(node->right) < 0) {return leftRotate(node);}//RL型失衡if (balance < -1 && getBalance(node->right) > 0) {node->right = rightRotate(node->right);return leftRotate(node);}return node;
}void preOrder(Node *node) {if (node == NULL) {return;}printf("%d ", node->data);preOrder(node->left);preOrder(node->right);
}void inOrder(Node *node) {if (node == NULL) {return;}inOrder(node->left);printf("%d ", node->data);inOrder(node->right);
}Node *find(Node *node, ElemType value, int *counter) {Node *current = node;while (current != NULL) {if (current->data > value) {current = current->left;(*counter)++;} else if (current->data < value) {current = current->right;(*counter)++;} else {(*counter)++;return current;}}return NULL;
}//删除节点恢复平衡
/** 前半部分 二叉搜索树的删除* 后半部分 插入节点导致失衡的修改,稍作调整* */
Node *delete_node(Node *node, int value) {if (node == NULL) {return NULL;}if (node->data > value) {node->left = delete_node(node->left, value);} else if (node->data < value) {node->right = delete_node(node->right, value);} else if (node->data == value) {//情况一 要删除的节点就是叶子结点if (node->left == NULL && node->right == NULL) {Node *temp = node;node = NULL;free(temp);} else if (node->left == NULL && node->right != NULL) {//情况二 只有一个方向有节点 直接用有节点的数据进行替换就可以了Node *temp = node;node = node->right;free(temp);} else if (node->left != NULL && node->right == NULL) {//情况二 只有一个方向有节点Node *temp = node;node = node->left;free(temp);} else if (node->left != NULL && node->right != NULL) {//情况三 要删除的节点有左孩子也有右孩子Node *current = node->right;while (current->left != NULL) {current = current->left;}node->data = current->data;node->right = delete_node(node->right, current->data);}}//删除完成 下面开始调整if (node == NULL) {return node;}//更新树高node->height = 1 + max(getHeight(node->left), getHeight(node->right));// 获取平衡因子int balance = getBalance(node);//LL型失衡if (balance > 1 && getBalance(node->left) >= 0) {return rightRotate(node);}//LR型失衡if (balance > 1 && getBalance(node->left) < 0) {node->left = leftRotate(node->left);return rightRotate(node);}//RR型失衡if (balance < -1 && getBalance(node->right) <= 0) {return leftRotate(node);}//RL型失衡if (balance < -1 && getBalance(node->right) > 0) {node->right = rightRotate(node->right);return leftRotate(node);}return node;
}void test() {Node *root = insert_node(NULL, 1);root = insert_node(root, 2);root = insert_node(root, 3);root = insert_node(root, 4);root = insert_node(root, 5);root = insert_node(root, 6);root = insert_node(root, 7);root = insert_node(root, 8);root = insert_node(root, 9);root = insert_node(root, 10);int counter = 0;Node *result = find(root, 6, &counter);if (result) {printf("找了%d次", counter);}printf("\n前序遍历\n");preOrder(root);printf("\n中序遍历\n");inOrder(root);//    root = delete_node(root, 1);
//    root = delete_node(root, 2);
//    root = delete_node(root, 7);//    printf("\n前序遍历\n");
//    preOrder(root);
//    printf("\n中序遍历\n");
//    inOrder(root);printf("\n树高为%d", getTreeHeight(root));
}int main() {test();return 0;
}

运行效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/417236.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot生成ETH和ERON钱包

首先大家需要先引入相关依赖包&#xff0c;这个maven里面是没有的&#xff0c;需要我们自行导入才可以。在项目路径下面创建lib&#xff0c;将所有需要使用的包导入即可。给大家一个包的下载链接&#xff1a;https://download.csdn.net/download/qq_38935605/89715772 因为放在…

scrapy 爬取微博(一)【最新超详细解析】:创建微博爬取工程

本项目属于个人学习记录&#xff0c;爬取的数据会于12小时内销毁&#xff0c;且不可用于商用。 1 初始化环境 首先我们需要有python环境&#xff0c;先安装一下python&#xff0c;然后配置环境变量&#xff0c;这边给出windows的配置&#xff1a; 我这边的安装目录是D:\pyt…

关于SPI通信失败的一种情况(CRC校验不匹配的问题)

问题 该项目中&#xff0c;使用外置的ADC芯片采集电压电流&#xff0c;主控MCU通过SPI与ADC芯片通信。调试时&#xff0c;SPI通信一直失败&#xff0c;与之前成功的项目对比&#xff0c;发现是SPI配置的问题。 void MX_SPI2_Init(void) {/* USER CODE BEGIN SPI2_Init 0 *//*…

WIFI贴项目到底是不是“骗局”呢?由我来揭秘!

各位亲爱的朋友们&#xff0c;大家好&#xff01;我是你们的老朋友鲸天科技千千&#xff0c;一直在这片互联网的热土上耕耘。相信你们对我都不会陌生&#xff0c;因为我常常分享一些互联网上的新奇项目和实用技巧。如果你对我的内容感兴趣&#xff0c;别忘了点个关注哦&#xf…

【案例67】Npart批量启动服务卡顿严重分析过程

问题现象 通过Npart启动NC服务&#xff0c;发现只启动一个&#xff0c;大概3min左右即可启动成功。但是批量启动服务需要几十分钟才可以把服务启动成功&#xff0c;启动卡在获取“wenjian”图标处。 绕过Npart直接写脚本并行启动相关服务&#xff0c;发现也需要30min 问题分析…

数组与贪心算法——605、121、122、561、455、575(5简1中)

605. 种花问题&#xff08;简单&#xff09; 假设有一个很长的花坛&#xff0c;一部分地块种植了花&#xff0c;另一部分却没有。可是&#xff0c;花不能种植在相邻的地块上&#xff0c;它们会争夺水源&#xff0c;两者都会死去。 给你一个整数数组 flowerbed 表示花坛&#xf…

网络传输加密及openssl使用样例(客户端服务器)

文章目录 背景常用加密方式SSLOpenSSL主要功能 库结构 交互流程证书生成生成 RSA 私钥私钥的主要组成部分私钥的格式 创建自签名证书: 签发证书服务器端代码客户端代码常见错误版本问题证书问题证书格式 背景 网络传输中为保证数据安全&#xff0c;通常需要加密 常用加密方式…

1.初识ChatGPT:AI聊天机器人的革命(1/10)

引言 在当今的数字化世界中&#xff0c;人工智能&#xff08;AI&#xff09;正以其独特的方式重塑我们的生活和工作。其中&#xff0c;AI聊天机器人作为人机交互的前沿技术&#xff0c;已经成为企业与客户沟通、提供个性化服务的重要工具。这些机器人通过模拟人类的对话方式&a…

【Unity3D优化】优化内置shader的内存占用

一、性能分析 监控项目线上的崩溃情况&#xff0c;绝大多数崩溃都是因为低端设备&#xff0c;运行时内存不足&#xff0c;在运行过程中申请开辟新的内存时Crash了。因此&#xff0c;不定期继续优化内存占用。 性能分析首先主要靠Unity3d的Memory Profiler监控一些可追踪到的内存…

Java 方法的定义

目录 1.Java的方法类似于其他语言的函数&#xff0c;是一段用来完成特定功能的代码片段。 2.方法包含一个方法头和方法体&#xff0c;下面是一个方法的所有部分&#xff1a; &#xff08;1&#xff09;修饰符&#xff1a;可选。告诉编译器如何调用该方法&#xff0c;定义了该…

基于微信小程序的挂号管理系统-小程序端

微信小程序端系统功能实现 登录功能 系统登录功能中&#xff0c;用户只需在登录界面输入正确的用户名和密码&#xff0c;即可快速进入系统。登录功能还采用了先进的加密技术&#xff0c;保障用户信息的安全性&#xff0c;让用户能够放心使用。 注册功能 系统注册功中&#xf…

Vue项目“npm run serve”总卡住的问题 已解决

Vue项目“npm run serve”总卡住的问题 已解决 概述 如果卡住进度在51% 直接看这篇 https://blog.csdn.net/qq_34419312/article/details/141681307?spm1001.2014.3001.5501 在使用Vue.js进行项目开发时&#xff0c;npm run serve命令是我们常用的启动本地开发服务器的方式…

使用docker compose一键部署 Openldap

使用docker compose一键部署 Openldap LDAP&#xff08;轻量级目录访问协议&#xff0c;Lightweight Directory Access Protocol&#xff09;是一种用于访问分布式目录服务的网络协议&#xff0c;OpenLDAP 是 LDAP 协议的一个开源实现&#xff0c;由 OpenLDAP 项目提供&#x…

虚幻5|技能栏UI优化(3)——优化技能UI并实现显示背景UI,实现技能界面设计,实现技能栏的删除和添加

实现技能栏添加&#xff1a;将技能界面里的技能拖到技能栏格子 一.调整&#xff0c;在拖出技能的时候&#xff0c;还会有边框 1.打开拖拽的技能格子UI 除了技能按钮&#xff0c;下面的子级都放到垂直框的子级&#xff0c;然后删除技能按钮 2.将垂直框替换成包裹框 你会发现有…

设计一个栈返回栈元素中的最小值python(简单)

请设计一个栈&#xff0c;除了常规栈支持的pop与push函数以外&#xff0c;还支持min函数&#xff0c;该函数返回栈元素中的最小值。执行push、pop和min操作的时间复杂度必须为O(1)。简单但经典 示例&#xff1a; MinStack minStack new MinStack(); minStack.push(-2); minSta…

数学建模强化宝典(2)linprog

一、介绍 linprog 是 MATLAB 中用于解决线性规划问题的函数。线性规划是一种优化方法&#xff0c;它尝试在满足一组线性等式或不等式约束的条件下&#xff0c;找到一个线性目标函数的最大值或最小值。linprog 函数适用于求解形如以下问题的线性规划问题&#xff1a; minimizecT…

OpenCV 旋转矩形边界

边界矩形是用最小面积绘制的&#xff0c;所以它也考虑了旋转。使用的函数是**cv.minAreaRect**()。 import cv2 import numpy as npimgcv2.imread(rD:\PythonProject\thunder.jpg) img1cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) print(img.dtype) ret,threshcv2.threshold(img1,1…

BUUCTF—[网鼎杯 2020 朱雀组]phpweb

题解 打开题目是这样子的。 啥也不管抓个包看看&#xff0c;从它返回的信息判断出func后面的是要调用的函数&#xff0c;p后面的是要执行的内容。 那我们直接执行个系统命令看看&#xff0c;可以看到返回了hack&#xff0c;估计是做了过滤。 funcsystem&pls 直接读取源码…

python多进程

文章目录 1、前言2、示例3、参考 1、前言 python中使用多进程&#xff0c;可以加快代码的运行速度&#xff0c;更高效地进行相关工作。 2、示例 使用蒙特卡洛方法计算 π \pi π来进行使用多进程前后代码运行速率的对比&#xff1b; import random import multiprocessing as…

白盒测试和黑盒测试详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 对于很多刚开始学习软件测试的小伙伴来说&#xff0c;如果能尽早将黑盒、白盒测试弄明白&#xff0c;掌握两种测试的结论和基本原理&#xff0c;将对自己后期的学习…