Java实现堆排序问题(变治法)
问题描述
用基于变治法的堆排序算法对任意一组给定的数据进行排序
2.1 堆排序原理简介
堆可以定义为一颗二叉树,树的节点中包含键(每个节点是一个键),并且满足下面两个条件:
(1)树的形状要求——这颗二叉树是基本完备的(或者简称为完成二叉树),这意味着,树的每一层都是满的,除了最后一层最右边的元素有可能缺位。
(2)父母优势要求,又称为堆特性——每一个节点的键都要大于或等于它子女的键(对于任何孩子节点也要自动满足父母优势要求)。
2.2 变治法原理简介
变治法:首先,在“变”的阶段,出于这一或者那样的原因,把问题的实例变得更容易求解(PS:类似本文求解问题,在排序前先把数组中数进行成堆处理);然后,在第二阶段或者说“治”的阶段,对实例进行求解。
根据我们对问题实例的变换方式,变治思想有3种主要的类型:
(1)变换为同样问题的一个更简单或者更方便的实例——我们称之为实例化简;
(2)变换为同样实例的不同表现——我们称之为改变表现;
(3)变换为另一个问题的实例,这种问题的算法是已知的——我们称之为问题的化简。
package com.liuzhen.heapsort;
public class HeapSort {
/*将array[a]和array[b]、array[c]中最大值进行比较,如果较小则将array[a]与array[b]、array[c]中最大值
进行交换,否则直接返回数组array*/
public static int[] getMaxA(int[] array,int a,int b ,int c){
int temp = 0;
if(array[b] >= array[c]){
if(array[a] < array[b]){
temp = array[a];
array[a] = array[b];
array[b] = temp;
}
}
else{
if(array[a] < array[c]){
temp = array[a];
array[a] = array[c];
array[c] = temp;
}
}
return array;
}
//根据堆排序父母优势规则,返回一个给定长度的数组的成堆结果
public static int[] getHeapSort(int[] array , int len){
boolean judge = true;
while(judge){
//根据堆排序父母优先规则,对数组array进行排序
for(int i = 1;i <= len/2;i++){
if((2*i+1) < len)
array = getMaxA(array,i,(2*i),(2*i+1));
if((2*i) == len-1){ //当2*i == len-1时,说明array[i]只有一个左孩子节点a[2*i]
int temp = 0;
if(array[i] < array[2*i]){
temp = array[i];
array[i] = array[2*i];
array[2*i] = temp;
}
}
}
//遍历数组array,一旦出现根节点小于其叶子节点时,跳出for循环
int j;
for(j = 1;j < len/2;j++){
if((2*j+1) < len){
if(array[j] < array[2*j])
break;
if(array[j] < array[2*j+1])
break;
}
if((2*j) == len-1){
if(array[j] < array[2*j])
break;
}
}
if(j == len/2) //如果j==len/2,说明遍历结果符合堆排序规则,直接结束while循环
judge = false;
}
return array;
}
//使用数组成堆,对一个数组元素进行从小到大排序,并返回排序后的结果
public static int[] getResultSort(int[] array , int len){
array = getHeapSort(array , len); //首先对数组进行堆排序处理
int temp = 0; //数组值交换中间变量
int sortLen = len; //排序过程中,需要重新进行堆排序的数组长度,并初始化为array的总长度
while(sortLen > 2){
// for(int i = 1;i < len;i++)
// System.out.print(array[i]+"\t");
// System.out.println();
temp = array[1]; //交换array[0]和array[sortLen-1]的值,即把最大的值放在未排序的数组最后一位
array[1] = array[sortLen-1];
array[sortLen-1] = temp;
sortLen = sortLen - 1; //交换成功后,未排序的数组长度自动减1
array = getHeapSort(array,sortLen); //对未排序的数组,重新进行堆排序
}
return array;
}
//初始化一个长度为n的随机数组
public static int[] initArray(int n){
int[] result = new int[n];
result[0] = 0;
for(int i = 1;i < n;i++)
result[i] = (int)(Math.random()*1000); //采用随机函数随机生成0~1000之间的数
return result;
}
public static void main(String args[]){
int[] array = {0,1,4,5,3,5,23,45,12,23,34,56,78,23,24,25}; //此处定义数组,对array[1]到array[len-1]进行排序
int len = array.length;
int[] result = getResultSort(array,len);
System.out.println("手动输入数组,使用堆排序,最终排序结果:");
for(int i = 1;i < len;i++){
System.out.print(result[i]+"\t");
}
System.out.println();
System.out.println();
int[] oneArray = initArray(1000);
int len1 = 1000;
int[] result1 = getResultSort(oneArray,len1);
System.out.println("系统随机生成的长度为1000的数组(其值均在0~1000之间),使用堆排序,最终排序结果:");
for(int j = 1;j < len1;j++){
System.out.print(result1[j]+"\t");
if(j%15 == 0)
System.out.println();
}
}
}

Java实现堆排序问题(变治法)的更多相关文章
- Java中的逆变与协变
看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...
- Java中的逆变与协变(转)
看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...
- Java泛型的逆变
在上篇<Java泛型的协变>这篇文章中遗留以下问题——协变不能解决将子类型添加到父类型的泛型列表中.本篇将用逆变来解决这个问题. 实验准备 我们首先增加以下方法,见代码清单1所示. 代码清 ...
- Java中的逆变与协变 专题
结论先行: PECS总结: 要从泛型类取数据时,用extends: 协变 要往泛型类写数据时,用super: 逆变 既要取又要写,就不用通配符(即extends与super都不用) 不变 List&l ...
- [改善Java代码]覆写变长方法也循规蹈矩
建议6:覆写变长方法也循规蹈矩 在Java中,子类覆写父类中的方法很常见,这样做既可以修正Bug也可以提供扩展的业务功能支持,同时还符合开闭原则(Open-Closed Principle),我们来看 ...
- Java实现堆排序
import java.util.Scanner; /*堆是一种数据结构,类似于一棵完整的二叉树. * 思想:堆的根节点值最大(最小),将无序序列调整成一个堆,就能找出这个序列的最大值(最小值),将找 ...
- 蓝桥杯比赛java 练习《立方变自身》
立方变自身 观察下面的现象,某个数字的立方,按位累加仍然等于自身.1^3 = 1 8^3 = 512 5+1+2=817^3 = 4913 4+9+1+3=17... 请你计算包括1,8, ...
- Java实现堆排序和计数排序
堆排序代码: 思想:每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最小堆,依次类推,最终得到排序的序列. import java.util.Arrays; /** * 思路:首先要 ...
- Java中的逆变与协变 很直接不饶弯的讲出来了
```java 协变 extends只能new 辈分比自己低的家伙 List<? extends Number> list001 = new ArrayList<Integer> ...
随机推荐
- aop面向切面编程的实现
aop主要用于日志记录,跟踪,优化和监控 下面是来自慕课网学习的一些案例,复制黏贴就完事了,注意类和方法的位置 pom添加依赖: <dependency> <groupId>o ...
- SDK,JDK,API的区别
[基础概念] 先留一波传送门: SDK:软件开发工具包(外语全称:Software Development Kit)一般都是一些软件工程师为特定的软件包.软件框架.硬件平台.操作系统等建立应用软件时的 ...
- WriteUp_easy_sql_堆叠注入_强网杯2019
题目描述 随便注 解题过程 查看源码,发现应该不适合sqlmap自动化注入,该题应该是让你手工注入: <!-- sqlmap是没有灵魂的 --> <form method=" ...
- 轻松扩展机器学习能力:如何在Rancher上安装Kubeflow
随着机器学习领域不断发展,对于处理机器学习的团队来说,在1台机器上训练1个模型已经有些难以为继,并且现在业界的共识是机器学习已经不仅仅是简单的模型训练. 在模型训练之前.过程中和之后,需要进行许多活动 ...
- MySQL常见面试题索引、表设计
正确使用索引的条件 1.建立索引的列的重复度不能太高 2.条件列不能参与计算 3.不能使用函数 4.条件中不能使用范围 5.不要使用like '%c' 6.条件中用or a=0 or b=1 or c ...
- java web基础
WEB基础 C/S:即服务器-客服机(Client-Server)结构.C/S结构通常采用两层结构,服务器负责数据的管理,客户机负责完成与用户的交互任务.客户通过局域网与服务器相连,接受用户的请求,并 ...
- Selenium RemoteWebDriver 利用CDP修改User-Agent
地球人都知道,如果使用selenium时要修改user-agent可以在启动浏览器时添加配置项,如chromeOptions.addArguments("user-agent=xxx&quo ...
- Python 图像处理 OpenCV (4):图像算数运算以及修改颜色空间
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- 【常用工具】vagrant的box哪里下?镜像在哪儿找?教你在vagrant官网下载各种最新.box资源
进入vagrant官网 : https://www.vagrantup.com/ 点击findbox[寻找box],进入有很多box的列表 : https://app.vagrantup.com/bo ...
- docker 日志查看与清洗
Linux下查看磁盘与目录的容量——df.du df:列出文件系统的整体磁盘使用量: du:评估文件系统的磁盘使用量(常用于评估目录所占容量) df参数: -a:列出所有的文件系统,包括系统特有的/p ...