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> ...
随机推荐
- spring MVC--WebApplicationContext做了什么
在WebApplicationContext中默认内置了DispatcherServlet依赖的bean!我们可以根据实际的项目需要对这些bean进行自定义参数设置.因为如果在配置文件中存在我们自定义 ...
- java ->多线程_线程同步、死锁、等待唤醒机制
线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. l 我们通过一个案例,演示线 ...
- 开源电影项目源码案例重磅分析,一套代码发布小程序、APP平台多个平台
uni-app-Video GitHub地址:https://github.com/Tzlibai/uni-app-video 一个优秀的uni-app案例,旨在帮助大家更快的上手uni-app,共同 ...
- 【C#】CsvHelper 使用手册
目录 简介 模块 读取 读取所有记录 逐条读取 读取单个字段 写入 写入所有记录 逐条写入 逐字段写入 特性 Index Name NameIndex Ignore Optional Default ...
- css概述三
五.盒子模型 4.box-sizing 定义盒子模型的计算方式 box-sizing:content-box; 默认值,我们定义的width/height是内容区域 元素占地宽度=左外边距+左边框+左 ...
- HTML5新特性--svg-echarts(重点)-拖动API-WebWorker
一.html5新特性--svg--(折线/渐变特效对象/滤镜) #折线:多个坐标点组件一条折线 <polyline points="50,50 70,55 60,66 " s ...
- 破坏之王DDoS攻击与防范深度剖析【学习笔记】
一.DDoS初步印象 1.什么是分布式拒绝服务攻击? 1)首先它是一种拒绝服务攻击 我们可以这么认为,凡是导致合法用户不能访问服务的行为,就是拒绝服务攻击. 注:早期的拒绝服务主要基于系统和应用程序的 ...
- RenderBox使用说明书&原理浅析
本文基于1.12.13+hotfix.8版本源码分析. 0.目录 一.RenderBox的用法 1.RenderBox的使用基本流程 2.RenderObjectWidget 3.非容器控件的hitT ...
- jsp 判断时间大小
jsp 判断时间大小 <% SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date ...
- 前端知识点也可以当做面试题含vue
一.webpack3.x打包工具 三大组成结构.package.json.webpack.config.js.serve.js 1.Package.json:下载目录需要的依赖包 2.Webpack. ...