您的位置:首页 > 编程语言 > Java开发

基本算法_堆排序_Java实现

2015-12-22 14:14 232 查看
转载请注明出处:/article/11557480.html

本文出自:【梁敬明的博客】

1.堆排序

  堆排序就是将序列调整为指定的堆,然后调整首尾元素的位置,取出末尾元素,反复进行,直到将所有元素取出,形成一个有序的序列。假设存在n个元素的序列{R0,R1,……,Rn}\{R_0,R_1,……,R_n\},其中父节点值不大于子节点值的堆称为小根堆(Ri≤R2i+1且Ri≤R2i+2)(R_i≤R_{2i+1}且R_i≤R_{2i+2}),父节点的值不小于子节点的堆称为大根堆(Ri≥R2i+1且Ri≥R2i+2)(R_i≥R_{2i+1}且R_i≥R_{2i+2})。



  存在一个序列【7】【5】【9】【6】【8】,按照从小到大的顺序进行排序。

  ①将无序序列构造成一个堆。

  ②取出子节点中6和8较大的值,与父节点5进行比较,比父节点5大,则交换位置。

  ③取出子节点中8和9较大的值,与根节点7进行比较,比跟节点7大,则交换位置,此时序列已调整为大根堆。

  ④将节点9和5调换位置,同时取出节点9,然后按照相同的方式将序列转换为大根堆,取出序列中最大的数,重复操作直到序列中所有数取出完毕,生成一个新的有序序列。

2.示例代码

  存在一个序列N由小到大进行排序,将序列转换为大根堆,交换首尾元素的位置,再将子序列N-1转换为大根堆,交换收尾元素位置,反复进行,当子序列剩余一个元素时,此时的序列为一个有序序列。

public class HeapSort {

public static void main(String[] args) {
int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
HeapSort.sort(array);
System.out.println("排序后数组:" + Arrays.toString(array));
}

public static void sort(int[] a) {
// 循环建立初始堆,若父节点索引为i,那么左节点的索引为i*2+1,即左节点为a.length时,其父节点应当小于a.length/2
for (int i = a.length / 2; i >= 0; i--) {// 遍历存在子节点的父节点
adjustHeap(a, i, a.length - 1);
}

// 进行n-1次循环完成排序
for (int i = a.length - 1; i > 0; i--) {
// 最后一个元素和第一个元素进行交换
int temp = a[i];
a[i] = a[0];
a[0] = temp;

adjustHeap(a, 0, i);
}
}

// 将数组转换为大根堆,大根堆的根节点为数组中的最大值
public static void adjustHeap(int[] a, int parent, int length) {
int temp = a[parent]; // 父节点的值
int child = 2 * parent + 1; // 左子节点的索引

while (child < length) {// 判断左节点是否为最大索引
// 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
if (child + 1 < length && a[child] < a[child + 1]) {
child ++;// 将左子节点转换为右子节点
}
// 当父节点的值直接大于子节点的值时,直接退出
if (temp > a[child])
break;
// 将子节点的值赋值给父节点
a[parent] = a[child];
// 选取子节点的左子节点继续向下筛选
parent = child;
child = 2 * parent + 1;
}
// 若发生交换,此时parent代表子节点索引,没有发生交换,此时parent仍旧代表父节点索引
a[parent] = temp;
}

}


3.算法分析

时间复杂度:堆排序的时间复杂度为O(nlog2n)O(nlog_2n)。

算法稳定性:排序前后相同元素间的相对位置可能会发生改变,堆排序是一种不稳定的排序算法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: