目录
1.选择排序
2.冒泡排序
3.插入排序
排序的稳定性
1.选择排序
每次选出最小的元素,与当前元素进行交换;保持前面的元素不变
简单选择排序是最简单直观的一种算法,基本思想为每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为首元素,直到所有元素排完为止,简单选择排序是不稳定排序。
//简单选择排序public static void selectSort(int[] arr) {for (int i = 0; i < arr.length - 1; i++) {int min = i;//每一趟循环比较时,min用于存放较小元素的数组下标,这样当前批次比较完毕最终存放的就是此趟内最小的元素的下标,避免每次遇到较小元素都要进行交换。for (int j = i + 1; j < arr.length; j++) {if (arr[j] < arr[min]) {min = j;}}//进行交换,如果min发生变化,则进行交换if (min != i) {swap(arr,min,i);}}}
2.冒泡排序
对相邻的元素进行两两比较,顺序相反则进行交换,这样,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序。
/*** 冒泡排序*/public static void bubbleSort(int[] arr) {for (int i = 0; i < arr.length - 1; i++) {boolean flag = true;//设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已然完成。for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {swap(arr,j,j+1);flag = false;}}if (flag) {break;}}}
3.插入排序
直接插入排序基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。
/*** 插入排序*/public static void insertionSort(int[] arr) {for (int i = 1; i < arr.length; i++) {int j = i;//将下标为j的元素插到前面排好序的序列中while (j > 0 && arr[j] < arr[j - 1]) {swap(arr,j,j-1);j--;}}}
排序的稳定性
排序算法的稳定性可以通过以下方法判断:
在待排序的记录序列中,如果存在两个或两个以上关键字相等的记录,经过排序后,这些记录的相对次序保持不变,则称这种排序算法是稳定的。反之,如果排序后这些记录的相对次序发生变化,则称为不稳定的排序算法。
常见排序算法的稳定性如下:
- 冒泡排序:稳定的,因为比较相邻元素并交换时,只有当前元素比相邻元素大才会交换。34
- 插入排序:稳定的,因为插入时只有当前元素比前面的元素小才会插入,并且插入位置是有序区的最后一个位置。
- 归并排序:稳定的,因为在合并两个有序子数组时,相等元素会先放入左侧子数组,保持相对顺序不变。
- 堆排序:不稳定的,因为堆化过程中会交换不相邻的元素。
- 快速排序:不稳定的,因为在分区过程中,相等元素可能会被交换到不同的位置。
- 选择排序:不稳定的,因为在一趟选择中,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。
- 基数排序:稳定的,因为它按照数字的每一位来进行排序。
排序算法稳定性的意义和应用场景:
排序算法的稳定性在实际应用中具有重要意义。例如,如果一个排序算法是稳定的,那么在进行多关键字排序时,可以先按第一个关键字排序,然后再按第二个关键字排序,第一个关键字排序的结果可以直接用于第二个关键字的排序,而不需要重新调整记录的相对顺序。这样可以减少数据交换的次数,提高排序效率。