Heapsort排序思路

将整个数组看作一个二叉树heap, 下标0为堆顶层, 下标1, 2为次顶层, 然后每层就是"3,4,5,6", "7, 8, 9, 10, 11, 12, 13, 14", ..., 对于其中的每一个非叶子节点, 其子节点的下标为 2 * pos + 1 和 2 * pos + 2

循环进行以下工作:

  1. 标记当前堆的右边界
  2. 将堆初始化为大顶堆
  3. 将堆顶置换到右边界, 同时将右边界左移一位(即将堆缩小一格)

将堆初始化为大顶堆的处理

  1. 从最后一个非叶子节点开始, 其下标为  length / 2 - 1, length为当前的堆大小, 往前挨个处理
  2. 检查节点值, 对节点与其子节点的值大小i进行比较, 如果子节点值比当前节点大, 将最大值的那个子节点换上来
  3. 如果发生了交换, 那么要对发生交换的这个子节点位置也进行检查, 如果还有交换, 则继续往下查, 直到达到叶子节点
public class DemoHeapSort {
// 待排序的数组
private int[] ints;
// 当前堆的右边界(下标)
private int limit; public DemoHeapSort(int ... ints) {
this.ints = ints;
this.limit = ints.length - 1;
} public void sortAll() {
while (limit > 0) {
resort();
swap(0, limit);
limit--;
}
} public void resort() {
// 起点pos为当前堆length / 2 - 1
for (int i = (limit + 1) / 2 - 1; i >= 0; i--) {
int pos = i;
while (true) {
pos = check(pos);
if (pos == 0) {
break;
}
}
}
} /**
* 检查pos位置, 自上而下判断是否都满足大顶堆的要求
* 其左右子节点的下标为 2*pos+1 和 2*pos+2
*
* @param pos 当前要检查的下标
* @return 如果无调整, 则返回0, 如果有调整, 则返回被调整的子节点下标
*/
private int check(int pos) {
int posLeft = 2 * pos + 1;
int posRight = 2 * pos + 2;
if (posLeft > limit) { // 没有子节点
return 0;
}
if (posRight > limit) { // 仅有左节点
if (ints[pos] < ints[posLeft]) {
swap(pos, posLeft);
return posLeft;
} else {
return 0;
}
}
// 左右节点都有
if (ints[posLeft] > ints[posRight]) {
if (ints[pos] < ints[posLeft]) {
swap(pos, posLeft);
return posLeft;
} else {
return 0;
}
} else {
if (ints[pos] < ints[posRight]) {
swap(pos, posRight);
return posRight;
} else {
return 0;
}
}
} public void print() {
for (int a : ints) {
System.out.printf("%3d", a);
}
System.out.print("\n");
} private void swap(int a, int b) {
int tmp = ints[a];
ints[a] = ints[b];
ints[b] = tmp;
} public static void main(String[] args) {
DemoHeapSort hs = new DemoHeapSort(10, 97, 9, 1,63, 64, 8, 17, 33, 7, 21, 0, 7, 75, 13, 18, 2, 99, 87);
hs.sortAll();
hs.print();
}
}

C代码, 在原数组上排序

void heap_sort(int *nums, int size) {
for (int i = 0; i < size; i++) {
int num = *(nums + i);
printf("%d ", num);
}
printf("\n");
for (int i = 0; i < size; i++) {
int length = size - i;
for (int pos = length / 2 - 1; pos >= 0; pos-- ) {
int p = pos;
do {
p = check(nums + i, length - 1, p);
} while (p != 0);
}
for (int j = 0; j < size; j++) {
int num = *(nums + j);
printf("%d ", num);
}
printf(" %d\n", i);
}
} int check(int *nums, int limit, int pos) {
int ls = pos * 2 + 1;
int rs = pos * 2 + 2;
if (ls > limit) {
return 0;
}
int p = *(nums + pos);
if (rs > limit) {
int l = *(nums + ls);
if (l > p) {
swap(nums + ls, nums + pos);
return ls;
} else {
return 0;
}
} else {
int l = *(nums + ls);
int r = *(nums + rs);
if (l > r) {
if (l > p) {
swap(nums + ls, nums + pos);
return ls;
} else {
return 0;
}
} else {
if (r > p) {
swap(nums + rs, nums + pos);
return rs;
} else {
return 0;
}
}
}
} void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}

堆排序Heapsort的Java和C代码的更多相关文章

  1. 数据结构 - 堆排序(heap sort) 具体解释 及 代码(C++)

    堆排序(heap sort) 具体解释 及 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 堆排序包括两个步骤: 第一步: 是建立大顶堆(从大到小排 ...

  2. 正则表达式学习笔记(附:Java版示例代码)

    具体学习推荐:正则表达式30分钟入门教程 .         除换行符以外的任意字符\w      word,正常字符,可以当做变量名的,字母.数字.下划线.汉字\s        space,空白符 ...

  3. java俄罗斯方块游戏代码

    java俄罗斯方块游戏代码: package com; import java.awt.Color; import java.awt.Graphics; import java.awt.event.K ...

  4. java常用用代码

    /** *Java获取IP代码 */ import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.ev ...

  5. java学用代码

    /** *Java获取IP代码 */ import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.ev ...

  6. 分享非常有用的Java程序(关键代码)(七)---抓屏程序

    原文:分享非常有用的Java程序(关键代码)(七)---抓屏程序 import java.awt.Dimension; import java.awt.Rectangle; import java.a ...

  7. 分享非常有用的Java程序 (关键代码)(六)---解析/读取XML 文件(重要)

    原文:分享非常有用的Java程序 (关键代码)(六)---解析/读取XML 文件(重要) XML文件 <?xml version="1.0"?> <student ...

  8. 分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map

    原文:分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map import java.util.Map; import org.apache.commons.lang.Ar ...

  9. 分享非常有用的Java程序 (关键代码)(四)---动态改变数组的大小

    原文:分享非常有用的Java程序 (关键代码)(四)---动态改变数组的大小 /** * Reallocates an array with a new size, and copies the co ...

随机推荐

  1. js 获取 对象 属性名称(转载)

    来源:https://www.cnblogs.com/YuyuanNo1/p/9257634.html dataObj = {name : su,age : 26,height : 18cm }; f ...

  2. Istio1.1.8部署

    istio安装 整体步骤: 下载 Istio 发行版. 完成必要的 Kubernetes 平台设置 检查对 Pod 和服务的要求. 安装高于 2.10 版本的 Helm 客户端. 安装之前的下载和准备 ...

  3. 【转】Jperf2.0下载及使用方法介绍

    iPerf图形化工具Jperf图文使用教程   在前文介绍iPerf时,我们就提到了Jperf这款软件,因为iPerf没有图形界面,操作起来不是太方便,而Jperf则是将iPerf命令行图形化的JAV ...

  4. Python的正则表达式re模块

    Python的正则表达式(re模块) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Python使用re模块提供了正则表达式处理的能力.如果对正则表达式忘记的一干二净的话,可以花费 ...

  5. RedHat7.4 yum配置

    RedHat7.4 yum配置 linux 1. yum配置 1.1 本地yum源配置 1.2 配置网络yum源为CentOS源 1. yum配置 1.1 本地yum源配置 设置使用ISO镜像软件:虚 ...

  6. jquery 表单对象属性筛选选择器

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content ...

  7. 摘:JAVA JXL API的详细使用

    转自:http://www.cr173.com/html/10377_1.html 1 开发调研1.1 需求描述MS的电子表格(Excel)是Office的重要成员,是保存统计数据的一种常用格式.作为 ...

  8. Hive UDF函数构建

    1. 概述 UDF函数其实就是一个简单的函数,执行过程就是在Hive转换成MapReduce程序后,执行java方法,类似于像MapReduce执行过程中加入一个插件,方便扩展.UDF只能实现一进一出 ...

  9. 记录一次编译安装Pg_rman缺少依赖包的问题

    系统版本:CentOS版本6.10(最终版) pg_rman:https://github.com/ossc-db/pg_rman -bash-4.1$ makegcc -Wall -Wmissing ...

  10. [Debug] How to Debug a NestJs Backend using the Chrome Dev Tools

    TO debug NestJS code with Chrome dev tool, we can run: node --inspect-brk dist/rest-api/src/main.js ...