选择排序:通过每次选择出待排序列中的最大值或最小值,并将其移除队列,输出到新的已排序列。逐步执行,直到选出待排序列中最后一个元素,则输出结果即为排好序的最终结果。
直接选择排序
直接选择排序,通过每次遍历待排序列中的元素,选择出其中最大或最小元素值,将它与其应在位置的元素进行交换,因此确定了该元素对应的位置。外层循环从序列某端开始,遍历要确定的位置,嵌套执行后
动态演示图如下:
代码实现如下:
import java.util.Arrays;
/**
* @description: select sort method
* @author: liyaguang
* @create: 2018-12-03 13:26
**/
public class SelectSort {
public static void main(String[] args){
int[] arrOriginal = new int[]{5, 9, 7, 4, 22, 2, 65, 1, 45};
System.out.println("before select sort, the array is: ");
System.out.println(Arrays.toString(arrOriginal));
// 最小元素下标存放临时变量
int smallestIdx;
// 每次待确定值的索引位置
for (int i = 0; i < arrOriginal.length - 1; i++) {
smallestIdx = i;
// 遍历待排序序列,选出其中最小元素
for (int j = i+1; j < arrOriginal.length; j++) {
if (arrOriginal[j] < arrOriginal[smallestIdx]) {
smallestIdx = j;
}
}
// 将最小值移动到它对应的索引位置
Utils.switchVal(arrOriginal, i, smallestIdx);
}
System.out.println("\nend select sort, the array is: ");
System.out.println(Arrays.toString(arrOriginal));
}
}
直接插入排序的时间复杂度为O(n2)。
堆排序
堆排序:在直接选择排序的思想上,利用堆这种数据结构的特点,可以直接选择得出最大或最小元素。堆是一种特殊的完全二叉树,分为最大堆或最小堆,最大堆的父节点值>=两个子节点值,最小堆的父节点值<=两个子节点值。后来堆的含义被引申为程序设计语言中的垃圾收集区域。
算法主要的关键是构建出堆这种数据结构,下文演示了通过使用最大堆进行堆排序的代码。其中最大堆数据结构通过数组来实现,最大堆的元素个数要小于等于数组元素个数,用Heap类对象中的heapSize属性表示
动态演示图如下:
代码实现如下:
- 最大堆数据结构的实现
/**
* max heap data structure
*
* @author liyaguang
*/
public class Heap {
private int heapSize;
public int getHeapSize() {
return heapSize;
}
public void setHeapSize(int size) {
this.heapSize = size;
}
public int getParentIdx(int i) {
return i / 2;
}
public int getLeftIdx(int i) {
return 2 * i;
}
public int getRightIdx(int i) {
return 2 * i + 1;
}
/**
* 调整最大堆,使其符合数据结构要求
*
* @param arr 源数组
* @param i 待调整元素在数组中的元素下标
*/
public void maxHeapify(int[] arr, int i) {
int left = getLeftIdx(i);
int right = getRightIdx(i);
int largest = i;
if (left < heapSize && arr[left] > arr[largest]) {
largest = left;
}
if (right < heapSize && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
Utils.switchVal(arr, i, largest);
maxHeapify(arr, largest);
}
}
/**
* 构建最大堆
*
* @param arr 源数组
*/
public void buildMaxHeap(int[] arr) {
this.setHeapSize(arr.length);
for (int i = (arr.length / 2); i >= 0; i--) {
maxHeapify(arr, i);
}
}
}
- 基于最大堆数据结构实现的堆排序主要算法
import java.util.Arrays;
/**
* heap sort algorithm
*
* @author liyaguang
*/
public class HeapSort {
public static void main(String[] args) {
int[] arr = new int[]{5, 9, 7, 4, 22, 2, 65, 1, 45};
System.out.println("before select sort, the array is: ");
System.out.println(Arrays.toString(arr));
// 建最大堆
Heap heap = new Heap();
heap.buildMaxHeap(arr);
// 选取堆顶最大元素,放置到数组对应位置后,调整最大堆
for (int i = arr.length - 1; i > 0; i--) {
Utils.switchVal(arr, i, 0);
heap.setHeapSize(heap.getHeapSize() - 1);
heap.maxHeapify(arr, 0);
}
System.out.println("\nend heap sort, the array is: ");
System.out.println(Arrays.toString(arr));
}
}
堆排序时间复杂度为:O(nlogn)
小结
通过每次选出最值的方式,直接选择排序采用的办法——遍历,而堆排序建立在已经有序的一种数据结构之上,而且,每次的选最值后,调整堆结构是建立在已经部分有序的基础上,少做了很多比较,提升了运行效率。
参考资料:
《算法导论》
Selection sort - wikiwand
Heapsort - wikiwand
该系列示例代码下载:欢迎关注我的github