1.冒泡(稳定)
视频演示:冒泡排序示意图1、冒泡排序示意图2
排序思路:在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序。
1.1 程序测试
public static void bubbleSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
boolean isSorted = true;
for (int j = 0; j < array.length - i - 1; j++) {
// 相等不交换,保证稳定性
if (array[j] > array[j + 1]) {
swap(array, j, j + 1);
isSorted = false;
}
}
if (isSorted) {
break;
}
}
}
性能分析:
1.2 比较:插入、选择、冒泡排序
一次使得一个数据有序 | 思想 |
---|---|
插入排序 | 在无序区间选择第一个数,在有序区间遍历 查找合适的位置插入 |
选择排序 | 遍历无序区间 查找最大数/最小数的下标,放到有序区间中 |
冒泡排序 | 遍历无序区间 通过两两比较,将最大数挤到最后 |
for(int i = 0;i < array.length-1;i++){
//插排:j遍历的是有序区间
//选择、冒泡:j遍历的是无序区间
}
2.堆排序(不稳定)
视频演示:堆排序示意图
堆排序:规模大的选择排序(减治排序,没次选择最大的数放后面),利用堆的特性选择最大的数。
排升序要建大堆;排降序要建小堆
从前向后遍历,向上调整;从后向前遍历,向下调整
2.1 建大堆步骤
1)把整个数组建一个大堆。
2)需要选出n-1个数。
i.[0]是无序区间最大的数;
ii.交换[0]和[无序区间最后一个数的位置];
iii.无序区间-1;无序区间堆的特性被破坏;
iiii.针对无序区间做向下调整,重新建一个大堆;
iiiii.重复上述步骤。
2.2 向下调整步骤
1)判断index是不是叶子(不是叶子:2*index+1<size),左孩子下标没越界,调整需继续
2)找到最大孩子下标
i.假设左孩子是最大的
ii.如果有右孩子且右孩子大,大的是右孩子
int max = 2*index+1;
if(2*index+2<size){
if(array[2*index+2]>array[2*index+1]){
max = 2*index+2;
}
}
iii.比较[max]和[index]
如果[index]大,满足堆,调整结束;否则交换,并对[max]继续调整
2.3 程序测试
public class HeapSort {
public static void heapSort(int[] array) {
// 1. 建大堆
createBigHeap(array);
// 2. 选出 array.length - 1 个数
for (int i = 0; i < array.length - 1; i++) {
// 无序 [0, array.length - i)
// 交换 array[0], array[length - i - 1]
swap(array, 0, array.length - i - 1);
//大堆第一个元素和无序区间最后一个数交换
// 无序 [0, array.length - i - 1)
// 无序长度 array.length - i - 1
shiftDown(array, array.length - i - 1, 0);
//下标为0的位置开始向下调整
}
}
private static void createBigHeap(int[] array) {
for (int i = (array.length - 2) / 2; i >= 0; i--) { //(array.length-2)/2为最后一个结点的双亲 保证i的父节点存在
shiftDown(array, array.length, i);
}
}
private static void shiftDown(int[] array, int size, int i) {
while (2 * i + 1 < size) { //index非叶子节点,确定i有左孩子
int max = 2 * i + 1; //假设最大的是左孩子
/*
if (max + 1 < size) {
if (array[max + 1] > array[max]) {
max = max + 1; //最大的是右孩子
}
}
*/
if (max + 1 < size && array[max+1] > array[max]) {
max = max + 1; //大的是右孩子
}
if (array[i] >= array[max]) {
return; //i大 不需要调整
}
swap(array, i, max); //否则 需要调整 交换[i] [max]
i = max; //[max]需要继续向下调整
}
}
private static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
public static void main(String[] args) {
int[] array = {34,45,12,33,0,1,2,3,88,100};
heapSort(array);
System.out.println(Arrays.toString(array));
}
}
测试结果:
性能分析: