算法总结--排序(快排未写)
算法第四版的简化的笔记!给自己看的
数据,一个长度为n的无序数组
api
exch([]a,i,j) 交换数组i与j位置的元素
less(i,j) 判断大小:数组元素i<j?true:false
一 选择排序 selection
i=0;从i~n中选取最小值与i交换位置;i++ ;循环;
特点
运行时间与输入无关(无论多么乱,或者元素全部一样) 排序时间是一样的。
数据移动是最少的,每个元素只交换一次。
public static void sort(Comparable[] a) { int n = a.length; for (int i = 1; i < n; i++) { int min = i; for (int j = i; j < n; j++) { if (less(a[j], a[min])) { min = j; } } exch(a, i, min); } }
二插入排序 insertion
将i插入已排序的0~i 中合适的位置,i++;循环
插入方法:将i与i-1比较,小于则交换i与i-1;i--;循环;直到插入合适位置
特点
接近有序的数组比乱序或逆序的要快得多
适合小规模数组,或大规模数组的局部优化
改进
插入方法不总是交换位置,直接找到位置,后面元素全部右移
/** * 将a中lf-rt元素排序 不包括rt位置 * * @param a * @param lf * @param rt */ public static void sort(Comparable[] a, int lf, int rt) { for (int i = lf + 1; i < rt; i++) { for (int j = i; j > lf && less(a[j], a[j - 1]); j--) { exch(a, j, j - 1); } } }
三 希尔排序 shell
类似插入排序,插入排序可视为增量h=1的情况。
参数:增量h递减至1 (h可选,例子增量约等于n/3)
将h,2h,3h。。
h+i,2h+i,3h+i..n
...分别按插入排序
h递减(例子增量为h/=3)
循环,直至h<=1;
public static void sort(Comparable[] a) { int N = a.length; // 增量 int h = 0; while (h < N / 3) h = h * 3 + 1; while (h >= 1) { for (int i = h; i < N; i++) { for (int j = i; j >= h && less(a[j], a[j - h]); j -= h) { exch(a, i, j); } } h /= 3; } }
四归并排序 merge
对于两叠已排序的纸牌,只需依次比较两叠中最顶一张,不断取较小的就行了
归并分为两种 链表排序适合自下而上
1自上而下
将n不断二分,类似二叉树,最后一个节点一个元素
1,1合为2
2,2合为4
直至合为n
public static void sort(Comparable[] a) { int n = a.length; Comparable [] aux = new Comparable[n]; sort(a, 0, n - 1,aux); } private static void sort(Comparable[] a, int lf, int rt, Comparable[] aux) { if (lf >= rt) return; if((rt-lf)<=15){ new Insertion().sort(a,lf,rt+1); } int mid = lf + (rt - lf) / 2; sort(a, lf, mid, aux); sort(a, mid + 1, rt, aux); if (less(a[mid], a[mid + 1])) return; else merge(a, lf, mid, rt, aux); } /** * 将lf-mid 和 mid+1-rt归并 * * @param a * @param lf * @param mid * @param rt * @param aux */ private static void merge(Comparable[] a, int lf, int mid, int rt, Comparable[] aux) { for (int i = lf; i <= rt; i++) { aux[i] = a[i]; } int i = lf; int j = mid + 1; for (int k = lf; k <= rt; k++) { if (i > mid) a[k] = aux[j++]; else if (j > rt) a[k] = aux[i++]; else if (less(aux[i], aux[j])) a[k] = a[i++]; else a[k] = a[j++]; } }
2自下而上
直接将n化为1,类似n叉树
1,1合为2。。。。直至合为n
原始排序:即将已排序子序列合并,需要一个临时数组拷贝两个子序列,然后排序至原始数组对应位置
改进:1当子序列长度小于某个值时,使用插入排序 ,比如长度为15
2原始排序需要不断拷贝临时数组,可以再开始就一次性拷贝到辅助数组,直接排序到排序数组?减少复制时间 但不能减少空间
五快速排序
待续。。。。