插入排序
插入排序的思想为:从数组的第二个元素开始遍历整个数组。针对每个元素,依次将其前面的所有元素和他进行比较,大于它的元素均向后移动,最后将该元素插入。
插入排序是一种稳定的排序算法。时间复杂度T(n)=O(n^2)
最好情况下已排好序,T(n)=O(n)
private void swap(int[] a, int i, int j) {
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
插入排序的关键代码
private void insertSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int j = i - 1;
int tmp = a[i];
while (j >= 0 && a[j] > tmp) { // 稳定的排序,注意顺序
a[j + 1] = a[j];
j--;
}
a[j+1] = tmp;
}
}
冒泡排序
冒泡排序的思想为:从第一个元素开始相邻的两个元素两两比较,按照小数在上大数在下的规则交换,一趟下去大数沉底。
再从第一个元素开始两两比较相邻两个元素,直到倒数第二个元素
....
冒泡排序也是稳定的排序算法
冒泡排序的复杂度均为T(n)=O(n^2)
插入排序的关键代码
public void bubbleSorts(int[] a) {
/*boolean flag = true;*/
for (int i = 0; i < a.length - 1 /*&& flag*/; i++) {
/*flag = false;*/
for (int j = 0; j < a.length - 1 - i; j++) {
if (a[j] >= a[j + 1]) {
swap(a, j, j + 1);
/*flag = true;*/
}
}
}
}
注释是对冒泡排序的改进,当没有调用swap函数表明已经排好序了。这样可以在最好情况下达到时间复杂度为T(n)=O(n)
选择排序
从所有序列中先找到最小的,然后放到第一个位置,之后再看剩余元素中最小的,放到第二个位置……以此类推选择排序是不稳定的排序算法,比如[3,3,1]第一次交换时第一个三就会跑到第二个3后面去。
选择排序的复杂度均为T(n)=O(n^2)
选择排序的关键代码
public void selectSort(int a[]) {
for(int i = 0; i < a.length - 1; i++){
// 找到从i开始的最小数
int minIndex = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[minIndex]) {
minIndex = j;
}
}
swap(a, i, minIndex);
}
}
稳定性指具有相同值得元素在输出数组中的相对次序保持和输入数组一致。稳定性是排序算法的一个重要指标,基数排序就要用到稳定的排序算法作为其子过程。可能这样的概念解释还不是很清晰。举个例子,我们在实际应用中不会仅仅是比较数字这么简单,可能是比较一个对象,一个对象有很多属性。比如两个学生的成绩包含语文和数学,A[80,90],B[80,85],在对语文成绩排序时要保证A在B前,因为对语文成绩来说A和B是一样,但一个对象还包含数学成绩,不能再对语文成绩排序的时候打乱了数学成绩的顺序。