二叉堆与堆排序

news/2024/5/20 8:37:26 标签:

二叉的定义
二叉是完全二叉树或者是近似完全二叉树。

二叉满足二个特性:

1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

2.每个结点的左子树和右子树都是一个二叉(都是最大或最小)。

当父结点的键值总是大于或等于任何一个子节点的键值时为最大。当父结点的键值总是小于或等于任何一个子节点的键值时为最小。下图展示一个最小
在这里插入图片描述
由于其它几种(二项式,斐波纳契等)用的较少,一般将二叉就简称为
的存储
一般都用数组来表示,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。
在这里插入图片描述
的插入
每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中——这就类似于直接插入排序中将一个数据并入到有序区间中

//  新加入i结点  其父结点为(i - 1) / 2
void MinHeapFixup(int a[], int i)
{
    int j, temp;
	
	temp = a[i];
	j = (i - 1) / 2;      //父结点
	while (j >= 0 && i != 0)
	{
		if (a[j] <= temp)
			break;
		
		a[i] = a[j];     //把较大的子结点往下移动,替换它的子结点
		i = j;
		j = (i - 1) / 2;
	}
	a[i] = temp;
}

更简短的表达为:

void MinHeapFixup(int a[], int i)
{
	for (int j = (i - 1) / 2; (j >= 0 && i != 0)&& a[i] > a[j]; i = j, j = (i - 1) / 2)
		Swap(a[i], a[j]);
}

插入时:

//在最小中加入新的数据nNum
void MinHeapAddNumber(int a[], int n, int nNum)
{
	a[n] = nNum;
	MinHeapFixup(a, n);
}

的删除(自上而下调整,自下而上更简单一些)
按定义,中每次都只能删除第0个数据。为了便于重建,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。相当于从根结点将一个数据的“下沉”过程。下面给出代码:

//  从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
// 自上而下调整推,以下方法没有验证,不一定正确。
void MinHeapFixdown(int a[], int i, int n)
{
    int j, temp;
 
	temp = a[i];
	j = 2 * i + 1;
	while (j < n)   //下沉过程
	{
		if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
			j++;
 
		if (a[j] >= temp)
			break;
 
		a[i] = a[j];     //把较小的子结点往上移动,替换它的父结点
		i = j;
		j = 2 * i + 1;
	}
	a[i] = temp;
}
//在最小中删除数
void MinHeapDeleteNumber(int a[], int n)
{
	Swap(a[0], a[n - 1]);
	MinHeapFixdown(a, 0, n - 1);
}

化数组
在这里插入图片描述
在这里插入图片描述
排序
首先可以看到建好之后中第0个数据是中最小的数据。取出这个数据再执行下化(调整)操作。这样中第0个数据又是中最小的数据,重复上述步骤直至中只有一个数据时就直接取出这个数据。


http://www.niftyadmin.cn/n/830742.html

相关文章

BL602 GPIO的使用

参考3. GLB — BL602/604 参考手册(Confidential) 文档 一、使用函数操作IO口 1、IO口的操作&#xff0c;常用以下几个函数 //设管脚为输出模式 int bl_gpio_enable_output(uint8_t pin, uint8_t pullup, uint8_t pulldown)//设置管脚为输入模式 int bl_gpio_enable_input(ui…

位移操作

在java中&#xff0c;算数右移一位代表除以2&#xff0c;算数右移两位代表除以4&#xff0c;以此类推 在java中&#xff0c;算数左移一位代表乘以2&#xff0c;算数左移两位代表乘以4&#xff0c;以此类推 位操作&#xff1a; 符号运算规则&与两个位都为1时&#xff0c;…

BL602 ADC的使用

1、我们直接调用官方的库即可&#xff0c;主要以下两个函数 //ADC初始化函数//mode: 采样模式(0正常ADC模式,1麦克风模式)//freq: 采样频率//data_num: 采样个数//gpio_num: 采样管脚int hal_adc_init(int mode, int freq, int data_num, int gpio_num)//获取AD转换结果…

BL602 PWM的使用

1、我们直接调用官方的库即可&#xff0c;主要以下几个函数 //PWM恢复默认值//id: PWM的id,一共支持5组PWM&#xff0c;范围0~4int hal_pwm_deinit(uint8_t id)//PWM初始化//id: PWM的id,一共支持5组PWM&#xff0c;范围0~4//pin: PWM的管脚int hal_pwm_init(uint8_t id, int…

BL602 I2C的使用

1、我们直接调用官方的库即可&#xff0c;主要以下几个函数 //I2C初始化//i2cx&#xff1a;I2C编号,只有一个I2C所以为0//freq: I2C频率,单位HZint hal_i2c_init(int i2cx, int freq)//I2C写数据//address&#xff1a; 从机地址//data&#xff1a; 读缓存//length&a…

BL602 WIFI的使用

1、打开工程目录下的proj_config.mk文件&#xff0c;配置CONFIG_WIFI:1 CONFIG_WIFI:1 2、打开工程目录下的Makefile文件&#xff0c;添加WIFI依赖的配置&#xff0c;如下面的COMPONENTS_WIFI COMPONENTS_BLSYS : bltime blfdt blmtd bloop loopadc looprt loopset COMPONE…

VSCode SSH 免密登录

前提 VSCode 已经安装 Remote - SSH 插件&#xff0c;并且可以通过密码登录远程主机 步骤 假设 VSCode 运行在 Windows&#xff0c;SSH 远程登录 Linux 1、在 Windows 端生成公钥/私钥对 例如在 git bash 中运行 ssh-keygen&#xff0c;然后一路回车&#xff0c;直到出现下面…

BL602 RTC的使用

1、我们直接调用官方的库即可&#xff0c;主要以下几个函数 //RTC初始化int32_t hal_rtc_init(rtc_dev_t *rtc)//获取RTC时间int32_t hal_rtc_get_time(rtc_dev_t *rtc, rtc_time_t *time)//设置RTC时间int32_t hal_rtc_set_time(rtc_dev_t *rtc, const rtc_time_t *time) 2、这…