堆排序:大堆排序就是将最大的数先进行排序,然后对剩下依次排序,自到堆里无未排序数据为止,
小堆排序,恰好相反, 用二叉树进行实现,
具体代码如下:
、
package com.qdcz.breadth.demo;
/**
*
* <p>Title: HeapA</p>
* <p>Description:堆排序实现类
* 堆积排序(Heapsort)是指利用堆积树(堆)这种资料结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。堆排序是不稳定的排序方法,辅助空间为O(1), 最坏时间复杂度为O(nlog2n) ,堆排序的堆序的平均性能较接近于最坏性能。 </br>
* 堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单 </br>
* 用大根堆排序的基本思想:
* 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区 </br>
* 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key </br>
* 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆 </br>
* 直到无序区只有一个元素为止。 </br>
* 大根堆排序算法的基本操作:
* 初始化操作:将R[1..n]构造为初始堆; </br>
* 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。 </br>
* 注意:
* 只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。 </br>
* 用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。 </br>
* <a href="http://blog.csdn.net/apei830/article/details/6584645">借鉴的资料</a>
* </p>
* <p>Company:奇点创智 </p>
* <p>Version:1.0 </p>
* @author Administrator
* @date 2017年6月6日 下午4:05:26
*/
public class HeapA {
public static void main(String[] args) {
int[] data={13,2,12,42,4,43,34,1};
print(data);
heapSort(data);
System.out.println("排序后的数组:");
print(data);
}
private static void heapSort(int[] data) {
for (int i = 0; i < data.length; i++) {
createMaxHeap(data,data.length-1-i);
swap(data,0,data.length-1-i);
print(data);
}
}
/**
*
*<p>Title: swap</p>
*<p>Description: </p>
*@param data
*@param i
*@param j
*@return void
*@author Administrator
*@date 2017年6月6日 下午4:33:10
*/
private static void swap(int[] data, int i, int j) {
if(i==j)return;
data[i]=data[i]+data[j];
data[j]=data[i]-data[j];
data[i]=data[i]-data[j];
}
/**
*
*<p>Title: createMaxHeap</p>
*<p>Description:堆排序核心算法方法 </p>
*@param data
*@param lastIndex
*@return void
*@author Administrator
*@date 2017年6月6日 下午4:32:29
*/
private static void createMaxHeap(int[] data, int lastIndex) {
for (int i = (lastIndex-1)/2; i >=0; i--) {//保存当前正在判断的节点
int k=i;
//若当前节点的子节点存在,
while(2*k+1<=lastIndex){
//bigger总是记录较大节点的值,先赋值为当前判断节点的左子节点
int bigger=2*k+1;
if(bigger<lastIndex){
//若子节点存在,否则此时bigger应该等于lastIndex
if(data[bigger]<data[bigger+1])bigger++; // 若右子节点值比左子节点值大,则bigger记录的是右子节点的值
}
if(data[k]<data[bigger]){ // 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k
swap(data,k,bigger);
k=bigger;
}else break;
}
}
}
private static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+"\t");
}
System.out.println();
}
}