##目录
##初级排序 ###一、 选择排序简述:选择排序就是遍历一遍数组把最小的和第一个数字交换。第二遍遍历数组时候选择和第二个交换,一次类推。
//注意不要在for循环中用a.length()不然每次都要获取a.length();
public voiv sort(Comparable[] a){
//for(int i=0,i<a.length;i++){
int N = a.length;
for(int i=0,i<N;i++){
int min = i;
for(int j=i+1;j<N;j++){
//if(a[min]>a[j]){
if(less(a[j],a[min])){
min = j;
}
//int tmp = a[i];
//a[i] = a[min];
//a[min] = tmp;
exch(a,j,min);
}
}
}
###二、 插入排序
简述:类似于打牌时候边抽牌边整理。第二张开始,就最大的开始对比,然后直到不大时候插入。
public void sort(Comparable[] a){
int N = a.length;
//下面是我写的,不知道书上有什么优势。有空测一下。
//for(int i=1;i<N;i++){
// if(less(a[i],a[i-1])){
/// int pos = i;
// while(less(a[pos],a[pos-1])&&pos>0){
// exch(a,pos,pos-1);
// pos--;
// }
// }
//}
for(int i=1,i<N;i++){
for(int j=i;j>0&&less(a[j],a[j-1]);j--){
exch(a,j,j-1);
}
}
}
####命题C
插入排序的比较次数 大于等于倒置的数量,小于等于倒置数量加上数组大小再减一。
最坏就是全倒置嘛,这时候每倒置一次就要多比一次,然而数组里每个数都要比较,除了第一个数时候和自身不比较,所以是 最差等于倒置数量+数组大小-1。
所以对 部分有序的数组十分高效,也适合小规模数组。
当不考虑交换和比较成本,两个差不多,但是感觉数组规模小的化插入有优势,规模大的化选择有优势。【平均而言】
###三、希尔排序
public static void sort(Comparable a){
int N = a.length;
int h = 1;
//
while(h<N3){
h = h * 3 +1
}
while(h>=1){
for(int i=h;i<N;i++){
for(int j=i;j<N&&less(a[j],a[j-h]);j-=h){
exch(a,j,j-h);
}
h=h/3;
}
}
}
平均每个比较次数增幅为N1/5 大的话才比较明显。
没什么可说的,三方比较,希尔排序一直赛高。可以把希尔排序看作套壳的插入排序。
public static void sort(Comparable[] a,int lo ,int hi){
int mid = lo + (hi - lo)/2;
if(lo>=hi) return;
sort(a,lo,mid);
sort(a,mid+1,hi);
merge(a,lo,mid,hi);
}
因为插入排序适合小数组,据说是 归并 + 插入 赛高。还没有验证。
####自底向上的归并排序
private static Compararble[] aux;
public static void sort(Comparable[] a){
int N = a.length;
//分割,1 ,2 ,4 ,6 ,8
//边界问题最头疼,首先为什么是N 不是N - 1?
//最重要的一点是 我门用sz表达的是分割的数组数字个数,如果是个数自然是按原值N过来。
for(int sz=1;sz < N ;sz = sz + sz){
//这里为什么是N
//暂时不知道,但是我用-1试过好几次也没差。反正就是为了防止过界又防止余下部分太小
for(int lo = 0;lo < N - sz;lo +=2sz){
merge(a,lo,lo + sz -1 ,Math.min(lo + 2sz - 1,N - 1));
}
}
}
最后的几个结论不是很懂,只能二刷时候再看了。
<p id = "3_1"></p>
##快速排序
快速排序也是把问题分开再分开,不同的是它并不是平均分成两组,而是产生一个分开因子。笼统而言和归并差不多吧,但是我测试速度感觉比归并快一点。时间能达到1/2甚至更多
public static void sort(Comparable[] a){
int N = a.length;
sort(a,0,N-1);
}
public static void sort(Comparable[] a,int lo,int hi){
if(lo>=hi) return;
int par = partition(a,lo,hi);
sort(a,lo,par - 1);
sort(a,par + 1 ,hi);
}
//core code
public static void partition(Comparable[] a, int lo,int hi){
Comparable v = a[lo];
i = lo;
j = hi+1;
while(true){
//while(less(a[++i],v)) if(i>=hi) break;
while(less(a[++i],v)) if(ihi) break;
//while(less(v,a[–j])) if(j<=lo) break;
//因为a[lo] = v; 所以 当j = lo时候根本进不来,所以if(jlo)是个多余的条件
while(less(v,a[–j])) {}/if(j==lo) break;/
if(i>=j) break;
exch(a,i,j);
}
exch(a,j,lo);
return j;
}
//quick3way
public static void sort3way(Comparable[] a,int lo,int hi){
if(lo>=hi) return;
int lt = lo;
int gt = hi;
int i = lo + 1;
Comparable v = a[lo];
//其实就是用 i 去遍历每一个数字,小的从 lt 插入 大的 从 gt插入。此为三向切分
while(i<=gt){
int cmp = a[i].compareTo(v);
if(cmp<0) exch(a,lt++,i++);
//换了之后i不用往下走,因为gt已经把一个陌生值换给它了。
else if(cmp>0) exch(a,i,gt--);
//和自己相等,下一个
else i++;
}
//lt-1 都是比v小的
//gt+1 都是比v大的
//剩下的都是等于v的。
sort3way(a,lo,lt-1);
sort3way(a,gt+1,hi);
}
<p id = "4_1"></p>
###优先队列
优先队列是一种思想,只能说堆排序用了这种思想。
大概就是当一个完全二叉树时候,对于一个节点k(从 1 开始的序号),
他的父节点为k/2
左子节点为 2k
右子节点为 2k + 1
下面的节点总比上面的节点大(根据实际用途,自己要求)
我们可以通过遍历某个节点的
当我们添加一个方法的时候 可以先将插入对象添加到队尾 可以使用 swim方法,让其上浮
####由下至上的对有序化(上浮)
//注意我们这里假设数组从 index 1 开始
public void swim(Comparable[] a,int k){
//k为插入元素index
while(k>=1){
if(less(a[k/2],a[k])){
exch(a,k/2,k);
k = k/2;
}
}
//这样直接上浮到适合的位置为止。
}
书上介绍优先队列用法,就是用来快速删除最大(最小【需另设队列】)元素的。
当我们删除最大节点,先使他下沉,使他子元素补位,
由上至下的堆有序化,下沉
//注意我们这里假设数组从 index 1 开始
public void sink(Comparable[] a,int k,int N){
while(k<=N){
int j = 2 * k;
//让哪个儿子重哪个儿子上
if(j<N && less(a[j],a[j+1])) j=j+1;
if(less(a[j],a[k])) break;
exch(a,k,j);
//换做最大元素,下一回合。
k = j;
}
}
####堆排序
public static void sort(Comparable[] a){
//第一步 排成优先队列
int N = a.length;
//元素先按1开始,等到使用数组的时候,再恢复实际元素
for(int k=N/2;k>=1;k–){
sink(a,k,N);
}
while(N>1){
//最前面肯定使最大的,所以将其和正确位置置换
exch(a,0,N-1);
//最先面的已经不是最轻的了,换人。
sink(a,1,--N);
}
}
public static void sink(Comparable[] a,int k,int N){
while(2*k<=N){
int j = 2 * k;
//使用时候按实际位置所以要-1.包括less 和 exch方法
if(j < N && less(a[j-1],a[j])) j = j + 1;
//如果不比儿子轻,就此结束,下一回合。
if(!less(a[k-1],a[j-1])) break;
exch(a,j-1,k-1);
k = j;
}
}
来源:CSDN
作者:Caretaker9
链接:https://blog.csdn.net/aihidao/article/details/104736112