java实现堆排序算法_堆排序算法小顶堆

java实现堆排序算法_堆排序算法小顶堆Java实现堆排序

堆排序快速排序归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的二叉堆。

堆的定义

n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。

情形1:ki <= k2i 且ki <= k2i+1 (最小化堆小顶堆

情形2:ki >= k2i 且ki >= k2i+1 (最大化堆大顶堆

其中i=1,2,…,n/2向下取整;

若将和此序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。

由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。

堆的存储

一般用数组来表示堆,若根结点存在序号0处, i结点的父结点下标就为(i-1)/2。i结点的左右子结点下标分别为2*i+1和2*i+2。

java实现堆排序算法_堆排序算法小顶堆

堆排序的实现

实现堆排序需要解决两个问题:

1.如何由一个无序序列建成一个堆?

2.如何在输出堆顶元素之后,调整剩余元素成为一个新的堆?

先考虑第二个问题,一般在输出堆顶元素之后,视为将这个元素排除,然后用表中最后一个元素填补它的位置,自上向下进行调整:首先将堆顶元素和它的左右子树的根结点进行比较,把最小的元素交换到堆顶;然后顺着被破坏的路径一路调整下去,直至叶子结点,就得到新的堆。

我们称这个自堆顶至叶子的调整过程为“筛选”。

从无序序列建立堆的过程就是一个反复“筛选”的过程。

public class HeapSort {
 int[] arr;
 public static void main(String[] args) {
 	HeapSort heapSor = new HeapSort();
 	
 int[] arr = new int[100]; //0下标放的是数组长度,
 for(int i=arr.length-1;i>=0;i--){
 	Random r = new Random();
 	arr[i] = i*r.nextInt(10000);
 }
 Date date1 = new Date();
 System.out.println("----------开始----------"+date1);
 heapSor.arr = arr;
 heapSor.heapSort(arr);
 Date date2 = new Date();
 System.out.println("----------结束----------"+date2);
 for(int i=0;i<arr.length;i++){
 System.out.println(arr[i]);
 }
 
 System.out.println("用时:"+(date2.getTime()-date1.getTime()));
 }
 void heapAdjust(int[] arr,int s,int m){
 //已知arr[s...m]中记录的关键字除arr[s]之外均满足堆的定义,本函数调整arr[s]的关键字,使arr[s...m]成为一个最大堆
 int rc = arr[s]; //s是最后一个非叶子节点
 
 for(int j=2*s;j <= m;j = s*2){
 if(j<m && arr[j]<arr[j+1])
 j++; //j为key较大的下标
 if(rc >= arr[j]) break;
 arr[s] = arr[j]; //上移到父节点
 s=j;
 }
 arr[s]=rc; //要放入的位置
 }
 
 void heapSort(int[] arr){
 //对数组进行建堆操作,就是从最后一个非叶结点进行筛选的过程
 for(int i=(arr.length-1)/2;i > 0;i--){//因为0没有使用,所以length-1
 heapAdjust(arr,i,arr.length-1); 
 }
 System.out.println("........建堆完成.............");
 
 outputArr(1);
 for(int i=arr.length-1; i>1; i--){
 int temp = arr[1];
 arr[1] = arr[i];
 arr[i] = temp;
 heapAdjust(arr,1,i-1);
 }
 }
 void outputArr(int i){
 
 if(i <= arr[0]){
 System.out.println(arr[i]);
 outputArr(i*2); //左
 outputArr(i*2+1); //右
 }
 }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/11853.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注