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. Linq Left Join;linq左连接 (转载)

    来源 https://www.cnblogs.com/xinjian/archive/2010/11/17/1879959.html 准备一些测试数据,如下: use Test Create tabl ...

  2. Node: 包管理机制

    Node.js 的模块机制可以很好地解决业务代码混乱的难题,但对于第三方模块包,就有些力不从心了,因为第三方模块包分散存放在各地,无法集中式管理.这就需要一个包管理机制,在 Node.js 中,Isa ...

  3. python的交互式shell-ipython体验

    ipython的python比较优秀的交互式shell,比python console功能更加强大更加的贴近开发及调试程序,也支持在linux下直接执行linux命令 00x-install 源码安装 ...

  4. 关于jupyter notebook密码设置

    对于一个jupyter编辑器使用的新手,更换浏览器或者Logout后,需要输入密码进行登陆时 按照网上的教程怎么设置都不行,那么自己整理了一个适用于初学者的操作. 1.windows下,打开命令行,重 ...

  5. 常用docker管理UI

    1. HumpBacks 特性 Web UI Supporting, Easy to use. Container Grouping and Isolation. Container Upgrades ...

  6. Windows Cmd 命令管理服务

    今天在Windows 干净环境上安装软件过程中,安装完成后,发现部署在IIS 上的网站无法使用,提示  "您提交的参数有误!,请重新提交" 纯净的windows 7 x64位环境, ...

  7. python中str和byte的相互转化

    在涉及到网络传输的时候,数据需要从str转换成btye才能进行传输. python byte 转 str , str 转 byte 其实很简单:原理图如下:在这里插入图片描述案例: a: str = ...

  8. beta版本——第一次冲刺

    第一次冲刺 (1)SCRUM部分☁️ ✨成员描述: 姓名 李星晨 完成了哪个任务 增加了个人中心返回主页按钮 花了多少时间 1h 还剩余多少时间 1h 遇到什么困难 没有遇到问题 这两天解决的进度 1 ...

  9. PAT甲级1001水题飘过

    #include<iostream> using namespace std; int main(){ int a, b; while(scanf("%d%d", &a ...

  10. Windows解决端口被占用问题

    第一种解决方法,以8080端口为例 打开命令行输入 cmd ,输入netstat -ano 会显示所有已经在运行的端口情况.PID为进程id 输入你想要查的正在占用的端口号,netstat -ano ...