记录几个常用排序算法(冒泡排序、快速排序、直接插入排序、选择排序)的思想 和 源码
冒泡排序
冒泡排序 (Bubble Sort),又被称为气泡排序或泡沫排序
思想:它会遍历若干次要排序的数列,每次遍历时,它都会从前往后依次的比较相邻两个数的大小;如果前者比后者大,则交换它们的位置。这样,一次遍历之后,最大的元素就在数列的末尾! 采用相同的方法再次遍历时,第二大的元素就被排列在最大元素之前。重复此操作,直到整个数列都有序为止!
时间复杂度
冒泡排序的时间复杂度是 O(N2)
假设被排序的数列中有 N 个数。遍历一趟的时间复杂度是 O(N),需要遍历多少次呢?N-1 次!因此,冒泡排序的时间复杂度是 O(N2)
Java 实现冒泡排序
// 冒泡排序public class BubbleSort {public static void bubbleSort(int[] a, int n){int i,j;int flag;for(i = n-1; i > 0; i--){flag = 0;for (j = 0; j < i; j++){if(a[j] > a[j+1]){int tmp = a[j];a[j] = a[j+1];a[j+1] = tmp;flag = 1;}}if (flag==0)break;}}public static void main(String[] args) {int i;int[] a = {20,40,30,10,60,50};System.out.printf("before sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);System.out.printf("\n");bubbleSort(a, a.length);System.out.printf("after sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);}}
快速排序
快速排序 (Quick Sort)使用分治法策略
思想:选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
快速排序流程:
- 从数列中挑出一个基准值
- 将所有比基准值小的摆放在基准前面,所有比基准值大的摆在基准的后面(相同的数可以到任一边);在这个分区退出之后,该基准就处于数列的中间位置
- 递归地把”基准值前面的子数列”和”基准值后面的子数列”进行排序
下面以数列 a={30,40,60,10,20,50}为例,演示它的快速排序过程
时间复杂度
快速排序的时间复杂度在最坏情况下是 O(N2),平均的时间复杂度是 O(N*lgN)
这句话很好理解:假设被排序的数列中有 N 个数。遍历一次的时间复杂度是 O(N),需要遍历多少次呢?至少 lg(N+1)次,最多 N 次
Java 实现快速排序
// 快速排序public class QuickSort {public static void quickSort(int[] a, int l, int r){if(l<r){int i,j,x;i = l;j = r;x = a[i];while (i<j){while (i<j && x<a[j])j--;if(i<j)a[i++] = a[j];while (i<j && x>a[i])i++;if (i<j)a[j--] = a[i];}a[i] = x;quickSort(a,l,i-1);quickSort(a,j+1,r);}}public static void main(String[] args) {int i;int a[] = {30,40,60,10,20,50};System.out.printf("before sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);System.out.printf("\n");quickSort(a, 0, a.length-1);System.out.printf("after sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);}}
直接插入排序
思想:把 n 个待排序的元素看成为一个有序表和一个无序表。开始时有序表中只包含 1 个元素,无序表中包含有 n-1个元素,排序过程中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复 n-1 次可完成排序过程
假设 {20,30,40,10,60,50} 中的前3个数已经排列过,是有序的了;接下来对10进行排列,如下:
图中将数列分为有序区和无序区。我们需要做的工作只有两个:
- 取出无序区中的第1个数,并找出它在有序区对应的位置
将无序区的数据插入到有序区;若有必要的话,则对有序区中的相关数据进行移位
Java 实现直接插入排序
// 直接插入排序public class InsertSort {public static void insertSort(int[]a,int n){int i,j,k;for (i = 1;i < n;i++){// a[i]是从无序列表中取出来的值,要找到放它的位置for (j = i-1;j>=0;j--){if (a[j] < a[i])break;}if(j != i-1){int tmp = a[i];// 将有序列表中往后挪,然后把a[i]插入列表中for(k = i-1;k > j;k--){a[k+1] = a[k];}a[k+1] = tmp;}}}public static void main(String[] args) {int i;int[] a = {20,40,30,10,60,50};System.out.printf("before sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);System.out.printf("\n");insertSort(a, a.length);System.out.printf("after sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);}}
选择排序
选择排序 (Selection sort)是一种简单直观的排序算法。
思想:首先在未排序的数列中找到最小(or最大)元素,然后将其存放到数列的起始位置;接着,再从剩余未排序的元素中继续寻找最小(or最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕
选择排序的时间复杂度是 O(N2)Java 实现选择排序
// 选择排序public class SelectSort {public static void selectSort(int[] a,int n){int i,j,min;for (i=0;i<n;i++){min = i;for (j=i+1;j<n;j++){if (a[min]>a[j])min = j;}if (i != min){int tmp = a[min];a[min] = a[i];a[i] = tmp;}}}public static void main(String[] args) {int i;int[] a = {20,40,30,10,60,50};System.out.printf("before sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);System.out.printf("\n");selectSort(a, a.length);System.out.printf("after sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);}}
