堆排序(C)

2023-11-03

堆排序

堆排序的基本思想:

  1. 对于一组待排序数据,首先按堆的定义建立初始堆(大根堆或小根堆);
  2. 取出堆顶元素(最大或最小),将剩余的元素继续调整成新堆,就得到次大或次小元素;
  3. 反复执行 1、2 ,直到全部元素排序成顺序或逆序,堆排序结束
堆的定义

对于 n 个元素的序列 {K1, K2, …, Kn},当且仅当满足下列关系时称为堆,其中 2i 和 2i +1应不大于 n
堆
其中,1 <= i <= n/2
当任意 K[i] 都小于 K[2i] 和 K[2i + 1] 时,为小根堆
当任意 K[i] 都大于 K[2i] 和 K[2i + 1] 时,为大根堆

堆排序

  堆排序是一种树形选择排序,可以将待排序数组看成是一个完全二叉树,则由堆的定义表明,该完全二叉树中,所有非叶子节点的值都不大于(或不小于)其左、右孩子节点的值。
  因此,在一个堆中,堆顶元素(二叉树根节点)必定为该序列中的最大(或最小)元素。
  所以堆排序就是,先构造堆,取堆顶元素,再构造新堆,重复这一过程,直到排序完成
假设待排序数组为:N = {55, 60, 40, 10, 80, 65, 15, 5, 75}; 结构如下:
排序数组

构造大根堆

构造大根堆,要使得该二叉树中所有非叶子节点的值都大于其左右节点,及使节点 1、2、3、4 的值都大于左右孩子节点。
初始化大根堆过程示意图:
构造大根堆

/*
	N 为待排序数组, target 为需要调整的非叶子节点
	n 为节点个数
*/
void AdjustMaxHeap(int N[], int target, int n) {
	int i = target;
	int j = 2 * i + 1;
	int temp = N[i];
	while(j <= n) {
		if(j < n && N[j] < N[j + 1]) {	// 找出左右孩子的最大值
			j++;
		}
		if(temp < N[j]) {	// 不满足大根堆则交换元素值
			N[i] = N[j];
			i = j;
			j = 2 * j + 1;
		}
		else {
			break;
		}
	}
	N[i] = temp;
}
构造小根堆

构造小根堆,要使得该二叉树中所有非叶子节点的值都小于其左右节点,及使节点 1、2、3、4 的值都小于左右孩子节点。

void AdjustMinHeap(int N[], int target, int n) {
	int i = target;
	int j = 2 * i + 1;
	int temp = N[i];
	while(j <= n) {
		if(j < n && N[j] > N[j + 1]) {	// 找出左右孩子的最小值
			j++;
		}
		if(temp > N[j]) {	// 不满足小根堆则交换元素值
			N[i] = N[j];
			i = j;
			j = 2 * j + 1;
		}
		else {
			break;
		}
	}
	N[i] = temp;
}
实现堆排序

取堆顶元素,调整新堆过程示意图:
调整新堆

void HeapSort(int N[], int n) {
	int i;
	// 构造大根堆,元素从 0 开始
	for(i = n/2 - 1; i >=0; i--) {
		AdjustMaxHeap(N, i, n - 1);
	}
	int temp;
	// 取堆顶元素,重新构造新堆
	for(i = n - 1; i > 0; i--) {
		temp = N[0];
		N[0] = N[i];
		N[i] = temp;
		AdjustMaxHeap(N, 0, i - 1);
	}
}
测试代码
void test() {
    int N[] = {55, 60, 40, 10, 80, 65, 15, 5, 75};
    HeapSort(N, 9);
    int i;
    for(i = 0; i < len; i++) {
        printf("%d ", N[i]);
    }
    printf("\n");
}

测试结果:

E:\C_demo>heapsort.exe
5 10 15 40 55 60 65 75 80

算法复杂度
  • 空间复杂度:堆排序只需一个记录大小的辅助空间,为 O(1)
  • 时间复杂度:堆排序的算法时间由建立初始化堆和不断调整堆这两部分时间构成,为O(nlogn)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

堆排序(C) 的相关文章

随机推荐

  • element ui + vue项目,修改el-divider默认样式

    修改el divider 垂直分割线的样式 以修改margin为例 其他样式改变同理
  • 实验2-动态规划编程题4. 01背包问题

    问题描述 给定一个容量为C的背包 现有n个物品 每个物品的体积分别为s1 s2 sn 价值分别为v1 v2 vn 每个物品只能放入一次 背包最多能装入价值为多少的物品 输入形式 输入的第1行包含2个整数C和n 分别表示背包容量和物品个数 接
  • gdb--设置断点的方法

    package utils import fmt github com gin gonic gin net http type Album struct ID string json id Title string json title A
  • 一个赛马算法

    原题 25匹马 5条跑道 怎样能用最快方式 得到最快的三匹马 假设每匹马的体力保持不变 速度固定 解法 堆排序 如下 package org algorithm search import java util ArrayList impor
  • 【vue】vue2 获取本地IP地址

    具体代码
  • 如何挖掘关键词

    挖掘关键词是SEO的基本功 借助的工具有 百度下拉框 百度相关搜索 搜搜问问 百度知道 百度推广助手 百度指数等 1 百度下拉框和相关搜索 通过下拉框和相关搜索搜集长尾词的方法是一级一级搜集 比如搜索SEO 然后再搜索SEO的下拉框里面的S
  • STM32F4 RTC-Alarm 的使用(RT-Thread操作系统)

    文章目录 1 工程的创建和配置 1 1 CubeMX 的配置 1 1 1 时钟源的选择 1 1 2 Debug 引脚配置 1 1 3 控制台串口的配置 1 1 4 RTC的配置 1 1 5 时钟树配置 1 1 6 代码生成 1 2 RT T
  • 合并多个文件到一个文件内

    package com caini psaer test import java io import java nio charset StandardCharsets import java util ArrayList import j
  • 快速排序实现(递归+非递归)

    快速排序代码 首先是划分算法 假设每次都以第一个元素作为枢轴值 进行一趟划分 int Partition int A int low int high int pivot A low while low lt high while low
  • java将office文件转换为pdf文件的三种方法

    方法1 poi读取doc itext生成pdf 实现最方便 效果最差 跨平台 方法2 jodconverter openOffice 一般格式实现效果还行 复杂格式容易有错位 跨平台 方法3 jacob msOfficeWord SaveA
  • win10 vmware虚拟机蓝屏怎么办 win10 vmware虚拟机蓝屏解决方法【详解】

    最近有朋友出现win10 vmware虚拟机蓝屏的情况应该怎么办 小伙伴们在使用vmware虚拟机出现了蓝屏现象的小伙伴们不用担心 小编翻阅各种资料后给大家带来两种虚拟机蓝屏的解决方法 想要解决此问题的小伙伴们快跟着小编往下看吧 win10
  • 总线(BUS)和总线操作

    1 什么是总线 答 总线是运算部件之间数据流通的公共通道 2 总线的作用 答 提高专用信号处理逻辑电路的运算能力和速度 3 总线与部件之间是怎么连接的 答 各运算部件和数据寄存器组是通过带控制端的三态门与总线相连接的 通过控制端口电平的高低
  • netlab在线助手(基于鼠标移动事件+窗体设计)

    随着老板每天查岗的频率越来越高 奈何自己是个十足的夜猫子 早晨的被窝就像一块磁铁牢牢的吸着我 俗话说 懒人也有勤劳的时候 那一定是在想怎么可以偷懒 哈哈哈哈 偷偷制作了一款在线助手 再也不用担心早上迟到了 还可以挂时长 美滋滋 废话不多说
  • JAVA中的四种JSON解析方式详解

    我们在日常开发中少不了和JSON数据打交道 那么我们来看看JAVA中常用的JSON解析方式 1 JSON官方 2 GSON 3 FastJSON 4 jackson JSON操作涉及到的类 public class Student priv
  • C语言的printf函数以从右到左的顺序输出,每个数据项可以进行算术但各自互不影响

    今天在一个网站上看到有个冒泡排序算法 最后的输出prinf输出函数如 printf c a i a i 突然记得在什么地方看过一种说法 C语言的输出是从右到左的 但具体却很模糊 下班回来之后就试了一下 代码如下 include
  • 指令大全(win+r)

    1 appwiz cpl 程序和功能 2 calc 启动计算器 3 certmgr msc 证书管理实 程序 4 charmap 启动字符映射表 5 chkdsk exe Chkdsk磁盘检查 管理员 份运 命令提 符 6 cleanmgr
  • 近期必读的7篇【医学图像分割】相关论文和代码(CVPR、AAAI)

    导读 最近小编推出CVPR2019图卷积网络相关论文 CVPR2019生成对抗网络相关视觉论文 可解释性 相关论文和代码 CVPR视觉目标跟踪相关论文 CVPR视觉问答相关论文 反响热烈 最近 医学图像分割这一新分割应用领域也广泛受关注 出
  • WKWebView 使用和坑

    iOS8以后 苹果推出了新框架Wekkit 提供了替换UIWebView的组件WKWebView 各种UIWebView的问题没有了 速度更快了 占用内存少了 一句话 WKWebView是App内部加载网页的最佳选择 先看下 WKWebVi
  • docker 安装 mongodb

    1 拉取最新的镜像 docker pull mongo latest 2 运行容器 docker run itd name mongo p 27017 27017 mongo auth 参数说明 p 27017 27017 映射容器服务的
  • 堆排序(C)

    文章目录 堆排序 堆的定义 堆排序 构造大根堆 构造小根堆 实现堆排序 测试代码 算法复杂度 堆排序 堆排序的基本思想 对于一组待排序数据 首先按堆的定义建立初始堆 大根堆或小根堆 取出堆顶元素 最大或最小 将剩余的元素继续调整成新堆 就得