问题描述

用基于变治法的堆排序算法对任意一组给定的数据进行排序

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实现堆排序问题(变治法)的更多相关文章

  1. Java中的逆变与协变

    看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...

  2. Java中的逆变与协变(转)

    看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); ...

  3. Java泛型的逆变

    在上篇<Java泛型的协变>这篇文章中遗留以下问题——协变不能解决将子类型添加到父类型的泛型列表中.本篇将用逆变来解决这个问题. 实验准备 我们首先增加以下方法,见代码清单1所示. 代码清 ...

  4. Java中的逆变与协变 专题

    结论先行: PECS总结: 要从泛型类取数据时,用extends: 协变 要往泛型类写数据时,用super: 逆变 既要取又要写,就不用通配符(即extends与super都不用) 不变 List&l ...

  5. [改善Java代码]覆写变长方法也循规蹈矩

    建议6:覆写变长方法也循规蹈矩 在Java中,子类覆写父类中的方法很常见,这样做既可以修正Bug也可以提供扩展的业务功能支持,同时还符合开闭原则(Open-Closed Principle),我们来看 ...

  6. Java实现堆排序

    import java.util.Scanner; /*堆是一种数据结构,类似于一棵完整的二叉树. * 思想:堆的根节点值最大(最小),将无序序列调整成一个堆,就能找出这个序列的最大值(最小值),将找 ...

  7. 蓝桥杯比赛java 练习《立方变自身》

    立方变自身 观察下面的现象,某个数字的立方,按位累加仍然等于自身.1^3 = 1 8^3  = 512    5+1+2=817^3 = 4913   4+9+1+3=17... 请你计算包括1,8, ...

  8. Java实现堆排序和计数排序

    堆排序代码: 思想:每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最小堆,依次类推,最终得到排序的序列. import java.util.Arrays; /** * 思路:首先要 ...

  9. Java中的逆变与协变 很直接不饶弯的讲出来了

    ```java 协变 extends只能new 辈分比自己低的家伙 List<? extends Number> list001 = new ArrayList<Integer> ...

随机推荐

  1. 盘点6个Kubernetes监视工具

    导读:监控可帮助您确保Kubernetes应用程序平稳运行并排除可能出现的任何问题.Prometheus是一种流行的开源监视工具,许多公司都使用它来监视其IT基础结构.但是,还有许多其他监视工具可用. ...

  2. POI 导入excel数据自动封装成model对象--介绍

    1.项目开发中,导入输入应该是常用的基本功能.我们经常会使用excel将数据导入到数据库,在导入之前必须得将excel数据转换成javaBean对象 2.由于此功能经常使用,所以开发此工具类方便日后轻 ...

  3. java ->基本数据类型与包装类的概述和转化

    基本类型 包装类概述 在实际程序使用中,程序界面上用户输入的数据都是以字符串类型进行存储的.而程序开发中,我们需要把字符串数据,根据需求转换成指定的基本数据类型,如年龄需要转换成int类型,考试成绩需 ...

  4. RocketMQ 入门

    一.rocketMQ是什么 rocketmq是一款低延迟.高可靠.可伸缩.已使用的消息中间件.具有以下特性: 1.支持发布/订阅.点对点(p2p)消息模型 2.同一个队列中支持先进先出(FIFO)和严 ...

  5. Kafka面试你不得不知道的基础知识

    Java内存管理面试指南一 Java基础面试指南一 Java基础面试指南二 Java基础面试指南三 Java基础面试指南四 Java线程面试指南一 Java线程面试指南二 Redis面试指南一 Kaf ...

  6. git pull 部分文件无法获取

    今天发现git pull origin master 的时候部分文件无法获取,然后学到了一个新方法: git fetch git checkout origin/master -- path/to/f ...

  7. env虚拟环境配置(两种)

    virtualenv(依赖关系难以解决) windows项目虚拟环境创建 # WINDOWS 环境使用虚拟环境# 在当前项目下# 安装 pip3 install virtualenv# 创建虚拟环境 ...

  8. mysql小白系列_08 zabbix3.2.6概念及部署

    一 zabbix功能简介 1.zabbix三大监控组件 zabbix server web gui database zabbix_server zabbix proxy agent client 2 ...

  9. kudu_单master集群安装

    1.配置JDK1.7/1.8,免密设置,ntp时间同步配置. 2. 将下载下来的文件放到/etc/yum.repos.d/ 目录下后,进行下一步 3.使用yum管理器安装 (集群搭建) sudo yu ...

  10. git rebase 还是 merge的使用场景最通俗的解释

    什么是 rebase? git rebase 你其实可以把它理解成是“重新设置基线”,将你的当前分支重新设置开始点.这个时候才能知道你当前分支于你需要比较的分支之间的差异. 原理很简单:rebase需 ...