常见排序算法整理
2017-05-01 21:23
197 查看
常见排序算法整理
我们常见的排序算法主要有以下几种:名称 | 平均 | 最好 | 最坏 | 空间 | 稳定性 |
---|---|---|---|---|---|
插入排序 | n | n2 | n2 | 1 | 稳定 |
希尔排序 | n | nlog2n | nlog2n | 1 | 不稳定 |
快速排序 | nlogn | nlogn | n2 | logn | 不稳定 |
冒泡排序 | n | n2 | n2 | 1 | 稳定 |
选择排序 | n2 | n2 | n2 | 1 | 不稳定 |
堆排序 | nlogn | nlogn | nlogn | 1 | 不稳定 |
归并排序 | n | nlogn | nlogn | n | 稳定 |
/*比较两个元素大小*/ private static boolean less(Comparable v, Comparable w){ return v.compareTo(w) < 0; }
/*交换两个元素*/ private static void exch(Comparable[] a, int i, int j){ Comparable t = a[i]; a[i] = a[j]; a[j] = t; }
插入排序 |
---|
原数据:[9] [8] [7] [1] [3] [5]
第一步:选择9,只有一个元素已经排序好
[9] [8] [7] [1] [3] [5]
第二步:选择8,插入到前面已排序的元素当中
[9] [8] [7] [1] [3] [5]
[8] [9] [7] [1] [3] [5]
第三步:选择7,插入到前面已排序的元素当中
[8] [9] [7] [1] [3] [5]
[7] [8] [9] [1] [3] [5]
同理:依次从剩余的元素选取一个插入到前面已排序的元素中
/*插入排序*/ public static void Insertion(Comparable[] c){ int N = c.length; for(int i = 1; i < N; i++){ for(int j = i; j > 0 && less(c[j], c[j-1]); j--){ exch(c, j, j-1); } } }
希尔排序 |
---|
原数据:[9] [8] [7] [1] [3] [5]
第一步:设定步长为3,设 h = 3 * h + 1; // 1, 4, 13,… 步长公式有自己设定,因此第一次步长为4,每组进行的都是插入排序
输入 [9] [8] [7] [1] [3] [5]
4-sort [3] [5] [7] [1] [9] [8]
第二步:步长为1,相当于进行一次插入排序
4-sort [3] [5] [7] [1] [9] [8]
1-sort [1] [3] [5] [7] [8] [9]
/*希尔排序*/ public static void Shell(Comparable[] c){ int N = c.length; int h = 1; while(h < N / 3){ h = 3 * h + 1; } while (h >= 1){ for(int i = h; i < N; i++){ for(int j = i; j >= h && less(c[j], c[j-h]); j -= h){ exch(c, j, j-h); } } h = h / 3; } }
快速排序 |
---|
原数据:[9] [8] [7] [1] [3] [5]
第一步:选择哨兵9存放到临时变量tmp中,定义两个索引start, end。 start指向数组的第二个元素,end指向数组的最后一个元素。分别从前往后扫描找比tmp大的,从后往前找比tmp小的,然后交换两个元素,循环这个步骤,直到两个索引相遇,则第一次扫描结束。
[9] [8] [7] [1] [3] [5]
[5] [8] [7] [1] [3] [9]
第二步:对上一步以哨兵为分界线的两个数组分别进行上面的操作。
[5] [8] [7] [1] [3] [9]
[1] [3] [5] [7] [8] [9]
同理:直到数组有序
/*希尔排序*/ public static void Quick(Comparable[] c){ sort(c, 0, c.length-1); } private static void sort(Comparable[] c, int start, int end) { if (end <= start) { return; } int j = partition(c, start, end); sort(c, start, j - 1); sort(c, j+1, end); }
/*切分程序*/ private static int partition(Comparable[] c, int start, int end){ int i = start, j = end + 1; Comparable v = c[start]; while (true){ while (less(c[++i], v)){ if(i == end){ break; } } while (less(v, c[--j])){ if(j == start){ break; } } if(i >= j){ break; } exch(c, i, j); } exch(c, start, j); return j; }
冒泡排序 |
---|
原数据:[9] [8] [7] [1] [3] [5]
第一步:依次比较,交换
[9] [8] [7] [1] [3] [5]
[8] [7] [1] [3] [5] [9]
第二步:同上
[8] [7] [1] [3] [5] [9]
[7] [1] [3] [5] [8] [9]
同理,直到数组有序
/*冒泡排序*/ public static void Bubble(Comparable[] c){ int N = c.length; for(int i = 0; i < N-1; i++){ for(int j = 0; j < N-i-1; j++){ if(less(c[j+1], c[j])){ exch(c, j, j+1); } } } }
选择排序 |
---|
原数据:[9] [8] [7] [1] [3] [5]
第一步:找到最小值1与最前面的9进行交换
[9] [8] [7] [1] [3] [5]
[1] [8] [7] [9] [3] [5]
第二步:在剩下的元素里面找到最小的瞳前面的8进行交换
[1] [8] [7] [9] [3] [5]
[1] [3] [7] [9] [8] [5]
同理:在剩余的元素中依次找最小的与前面的元素进行交换
/*选择排序*/ public static void Selection(Comparable[] c){ int N = c.length; for(int i = 0; i != N; i++){ int min = i; for(int j = i+1; j != N; j++){ if(!less(c[min], c[j])){ min = j; } } exch(c, i, min); } }
堆排序 |
---|
原数据:[9] [8] [7] [1] [3] [5]
第一步:建立初始堆:
[9] [8] [7] [1] [3] [5]
[1] [3] [5] [8] [9] [7]
第二步:交换第一个元素与堆的最后一个元素,从新调整使之为小根堆
[1] [3] [5] [8] [9] [7]
[7] [3] [5] [8] [9] [1]
[3] [7] [5] [8] [9] [1]
第三步:同上
[3] [7] [5] [8] [9] [1]
[9] [7] [5] [8] [3] [1]
[5] [7] [9] [8] [3] [1]
原理同上
/*堆排序*/ public static void HeapSort(Comparable[] c){ int i; for(i = c.length / 2 - 1; i >= 0; i--){ HeadAdjust(c, i, c.length); } for(i = c.length-1; i > 0; i--){ exch(c, 0, i); HeadAdjust(c, 0, i); } }
/*自下而上的调整堆*/ private static void HeadAdjust(Comparable[] c, int i, int N){ int nChild; for( ;2 * i + 1 < N; i = nChild){ nChild = 2 * i + 1; if(nChild < N-1 && less(c[nChild], c[nChild+1])){ nChild++; } if(less(c[i], c[nChild])){ exch(c, i, nChild); }else { break; } } }
归并排序 |
---|
/*合并两个子数组*/ public static void merge(Comparable[] c, Comparable[] cc, int start, int mid, int end){ int i = start; int j = mid + 1; for(int k = start; k <= end; k++){ cc[k] = c[k]; } for(int k =start; k <= end; k++){ if(i > mid){ c[k] = cc[j++]; }else if(j > end){ c[k] = cc[i++]; }else if(less(cc[j], cc[i])){ c[k] = cc[j++]; }else{ c[k] = cc[i++]; } } }
/*归并排序*/ public static void MergeSort(Comparable[] c){ Comparable[] cc = new Comparable[c.length]; sort(c, cc, 0, c.length-1); }
/*递归归并*/ private static void sort(Comparable[] c, Comparable[] cc, int start, int end){ if(end <= start){ return; } int mid = start + (end - start) / 2; sort(c, cc, start, mid); sort(c, cc, mid+1, end); merge(c, cc, start, mid, end); }
相关文章推荐
- 常见排序算法整理(三)----归并排序、快速排序
- 自己整理的几种常见排序算法,及时间复杂度空间复杂度。c++编程
- 整理的常见排序算法
- 常见排序算法整理-
- 常见排序算法整理(二)----希尔排序,选择排序
- 常见排序算法整理
- IT求职整理Ⅲ---常见排序算法小结
- 数据结构常见的八大排序算法(详细整理)
- 常见排序算法:插入排序 <整理>
- 常见排序算法整理
- 常见排序算法整理
- 常见排序算法整理
- Java_常见排序算法整理
- 几种常见的排序算法整理
- 常见排序算法代码整理
- 常见排序算法整理(一)----冒泡排序、直接插入排序
- Python常见数据结构整理
- 4种常见的排序算法(Java版)
- 几种常见排序算法和数据结构
- 常见Crash问题整理