1. 选择排序 SelectionSort
概念:
- 选择排序是一种简单直观的排序算法,它的工作原理是每一次从无序区中选出最小(或最大)的一个元素,追加到有序区,直到全部无序区的数据元素排完。
- 选择排序是不稳定的排序方法,比如序列
[5, 5, 3]第一轮就将第一个5与3交换,导致第一个5挪动到第二个5后面。 - 选择排序的核心思想是抢夺:从第一个数开始,依次和后面所有的数进行比较。
流程: 以正序为例:{1, 3, 154, 2345, 1345}
- 用
arrs[0]和后面所有的元素比较,发现小的就抢过来:- 第1轮下来,
arrs[0]位置上就是整个数组中第1小的元素。 arrs[0]组成有序区,其余仍在无序区。
- 第1轮下来,
- 用
arrs[1]和后面所有的元素比较,发现小的就抢过来:- 第2轮下来,
arrs[1]位置上就是整个数组中第2小的元素。 arrs[0]和arrs[1]组成有序区,其余仍在无序区。
- 第2轮下来,
- 用
arrs[2]和后面所有的元素比较,发现小的就抢过来:- 第3轮下来,
arrs[2]位置上就是整个数组中第3小的元素。 arrs[0]、arrs[1]和arrs[2]组成有序区,其余仍在无序区。
- 第3轮下来,
- ...
- 一共比较length-1次,无序区没有任何元素了,只剩下有序区,数组就排好序了。
源码: /javase-start/
- src:
c.y.arraysort.SelectionSortTest
/**
* @author yap
*/
public class SelectionSortTest {
@Test
public void selectionSort(){
int[] arr = { 101, 2, 23, 133, 412, 23, 412, 51, 235 };
// 每轮都将确定将一个无序区中最小的元素追加到有序区,需要比较N-1次
for (int i = 0, j = arr.length - 1; i < j; i++) {
// 每一次都拿一个元素和后面所有的元素进行比较
for (int m = i + 1, n = arr.length; m < n; m++) {
// 只要比arr[x]小,arr[x]就将其抢夺,最终arr[x]一定是无序区最小的元素
if (arr[i] < arr[m]) {
int temp = arr[i];
arr[i] = arr[m];
arr[m] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
2. 冒泡排序 BubbleSort
概念:
- 冒泡排序是一种计算机科学领域的较简单的排序算法,它从头开始,不断地比较相邻的两个元素,并进行对应的交换,直到最后排序完成。
- 这个算法的名字由来是因为越大(越小)的元素会经由交换慢慢浮到数列的顶端,故名。
- 冒泡排序的核心思想是交换:相邻的两个数进行比较。
流程: 以正序为例:{3, 1, 4, 2, 5};
- 比较相邻的元素,如果前数比后数大,就交换他们两个。
- 每一轮的工作内容是:对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。
- 1轮结束后,数组倒数第1位的元素一定是数组中第1大的数,5个数需要比4次。
- 2轮结束后,数组倒数第2位的元素一定是数组中第2大的数,需要比3次。
- 3轮结束后,数组倒数第3位的元素一定是数组中第3大的数,需要比2次。
- ...
- 一共要比较4轮(n-1轮)。
源码: /javase-start/
- src:
c.y.arraysort.BubbleSortTest
/**
* @author yap
*/
public class BubbleSortTest {
@Test
public void bubbleSort(){
int[] arr = { 101, 2, 23, 133, 412, 23, 412, 51, 235 };
// 每一轮:9个数,两两相比,要比9-1轮
for (int i = 0, j = arr.length - 1; i < j; i++) {
// 相邻两个数比较,需要比较length-1-i次
for (int m = 0, n = arr.length - 1 - i; m < n; m++) {
// 前数大于后数就交换,循环一次完毕保证最大的数排最后
if (arr[m] > arr[m + 1]) {
int temp = arr[m];
arr[m] = arr[m + 1];
arr[m + 1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
3. 插入排序 InsertSort
概念:
- 有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法,插入排序法。
- 插入排序就是我们生活中按大小个排序的基本排序思想,基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,是稳定的排序方法。
- 原理就是从第二个元素开始,每次都和前一位的元素进行比较,如果小于前面的元素,则交换位置,继续向前比较,直到该元素排到第一位或者不再小于前面的元素,如果不小于前面的元素,则直接继续操作下一个元素。
- 插入排序的核心思想是插队:从第二个数开始,依次和前面的数进行比较。
流程: 我们这里以正序为例:{3, 1, 4, 2, 5};(个头小的往前站)
- 我们假定
[3]是一个排好序的队伍,从第二个元素开始每个元素看做一个新的,想要插队的元素。 - 第二个元素是
1,1要插队,跟队尾的3比较,赢了,和3交换位置,得到一个新的队伍[1, 3]。 - 第三个元素是
4,4要插队,先跟队尾的3比较,输了,不动,得到一个新的队伍[1, 3, 4]。 - 第四个元素是
2,2要插队,先跟队尾的4比较,赢了,和4交换,得到一个新的队伍[1, 3, 2, 4]- 再和
3比较,赢了,和3交换,得到新的队伍[1, 2, 3, 4] - 再和
1比较,输了,不动,最终得到数组[1, 2, 3, 4]。
- 再和
- 第五个元素是
5,5要插队,先跟队尾的4比较,输了,结束。 - 最终队伍
[1, 2, 3, 4, 5]。
源码: /javase-start/
- src:
c.y.arraysort.InsertSortTest
/**
* @author yap
*/
public class InsertSortTest {
@Test
public void insertSort() {
int[] arr = {101, 2, 23, 133, 412, 23, 412, 51, 235};
// 从第i个位置开始依次向前比较,i从1开始,因为第0个人无法和它前面的人进行比较
// 由于你的i是从1开始的,所以判断条件要改为i<arrs.length,不能使用length-1,否则会少比一次
for (int i = 1, j = arr.length; i < j; i++) {
// 角标为1的人(第二个人),最多需要向前比较1次
// 角标为2的人(第三个人),最多需要向前比较2次
// 角标为i的人(第i+1个人),最多需要向前比较i次,所以m = i ; m > 0 ; m--
for (int m = i; m > 0; m--) {
// 若后面的数小,交换,若后面的数大,直接结束循环,没有再向前比较的必要
if (arr[m] < arr[m - 1]) {
int temp = arr[m];
arr[m] = arr[m - 1];
arr[m - 1] = temp;
} else {
break;
}
}
}
System.out.println(Arrays.toString(arr));
}
}