最经典的、最常用的:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。

对于排序算法执行效率的分析,我们一般会从这几个方面来衡量:
1.最好情况、最坏情况、平均情况时间复杂度
2.时间复杂度的系数、常数 、低阶
3.比较次数和交换(或移动)次数
针对排序算法,我们还有一个重要的度量指标,稳定性。这个概念是说,如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序不变。
冒泡排序算法
- // 冒泡排序,a表示数组,n表示数组大小
- public void bubbleSort(int[] a, int n) {
- if (n <= 1) return;
-
- for (int i = 0; i < n; ++i) {
- // 提前退出冒泡循环的标志位
- boolean flag = false;
- for (int j = 0; j < n - i - 1; ++j) {
- if (a[j] > a[j+1]) { // 交换
- int tmp = a[j];
- a[j] = a[j+1];
- a[j+1] = tmp;
- flag = true; // 表示有数据交换
- }
- }
- if (!flag) break; // 没有数据交换,提前退出
- }
- }
通过“有序度”和“逆序度”这两个概念来进行分析。
有序度是数组中具有有序关系的元素对的个数。有序元素对用数学表达式表示就是这样:
有序元素对:a[i] <= a[j], 如果i < j。
同理,对于一个倒序排列的数组,比如6,5,4,3,2,1,有序度是0;对于一个完全有序的数组,比如1,2,3,4,5,6,有序度就是n*(n-1)/2,也就是15。我们把这种完全有序的数组的有序度叫作满有序度。
逆序度的定义正好跟有序度相反(默认从小到大为有序)
逆序度=满有序度-有序度
- // 插入排序,a表示数组,n表示数组大小
- public void insertionSort(int[] a, int n) {
- if (n <= 1) return;
-
- for (int i = 1; i < n; ++i) {
- int value = a[i];
- int j = i - 1;
- // 查找插入的位置
- for (; j >= 0; --j) {
- if (a[j] > value) {
- a[j+1] = a[j]; // 数据移动
- } else {
- break;
- }
- }
- a[j+1] = value; // 插入数据
- }
- }