堆排序:
时间复杂度:O(n*log2(n))
空间复杂度:O(1)
不稳定
核心代码:
import java.util.Arrays;
/**
* 堆排序
* @author jin
*/
public class Heap {
/**
* 创建大顶堆
* @param array
* @param lastIndex
*/
public static void createMaxHeap(int[] array, int lastIndex) {
for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
int fatherIndex = i;
while (fatherIndex * 2 + 1 <= lastIndex) { // 如果当前父节点有子节点的话
int biggerIndex = fatherIndex * 2 + 1;
if (biggerIndex < lastIndex) {
if (array[biggerIndex] < array[biggerIndex + 1]) {
biggerIndex++;
}
}
if (array[biggerIndex] > array[fatherIndex]) {
swap(array, fatherIndex, biggerIndex);
} else {
break;
}
}
}
}
/**
* 数组中元素进行交换
* @param array
* @param i
* @param j
*/
public static void swap(int[] array, int i, int j) {
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
/**
* main方法
*/
public static void main(String[] args) {
int[] a = { 1, 2, 56, 3, 55, 2, 66, 9, 0, 7 };
for (int i = 0; i < a.length - 1; i++) {
createMaxHeap(a, a.length - 1 - i);
swap(a, 0, a.length - 1 - i);
}
System.out.println(Arrays.toString(a));
}
}
堆排序,有两个步骤:
(1)先建一个大顶堆,
(2)然后堆顶与堆的最后一个元素进行交换。
步骤:
(1)建大顶堆:
大顶堆:所有的父节点的数都比子节点的数大。
大顶堆是通过数组进行存储的 ,例如:
在内存中的存储方式为:
求某一子节点的父节点的索引:
(子节点索引-1)/2取整
建堆时,先从最后一个数开始,最后一个索引为lastIndex,其父节点为fatherIndex=(lastIndex-1)/2;如果该父节点有子节点的话,那么左节点为leftIndex=fatherIndex*2+1;
如果建大顶堆,也是从最后一个数开始,不过求子节点时,先假设左节点为最大的数biggerIndex=fatherIndex*2+1;如果biggerIndex
for(int i=(lastIndex-1)/2;i>=0;i--){//从后往前建立
int fatherIndex=i;
while(fatherIndex*2+1<=lastIndex){//如果当前父节点有子节点的话
int biggerIndex=fatherIndex*2+1;//为左节点
if(biggerIndex<lastIndex){
if(a[biggerIndex]<a[biggerIndex+1]){
biggerIndex++;//此时最大的数变为右节点
}
}
if(a[biggerIndex]>a[fatherIndex]){//交换这两个索引的值的位置
//这里用到了位运算,详细的以后会写
a[fatherIndex]=a[biggerIndex]^a[fatherIndex];
a[biggerIndex]=a[biggerIndex]^a[fatherIndex];
a[fatherIndex]=a[biggerIndex]^a[fatherIndex];
}else{
break;
}
}
}
(2)然后堆顶与堆的最后一个元素进行交换。
这里就开始进行排序了,交换完成后,就实现了从小到大的排列。