快速排序有很多版本,這裡給出一種基礎版本和一種典型加強版本,即三數取中版本.
public
class
quicksort
private
static
void
quicksort(int a, int left, int right)
int cutoff = partition(a, left, right,right);
quicksort(a, left, cutoff - 1);
quicksort(a, cutoff + 1, right);
}private
static
intpartition(int a, int left,int right,int pivot)
if (leftptr >= rightptr) else
}exchange(a,leftptr,right);
return leftptr;
}private
static
void
exchange(int a ,int x, int y)
}
public
class
quicksort_median3
private
static
void
quicksort(int a, int left, int right)
int median=median3(a,left,right);
int cutoff = partition(a, left, right, median);
quicksort(a, left, cutoff - 1);
quicksort(a, cutoff + 1, right);
}private
static
void
manualsort(int a,int left, int right)
if (size == 2)
} else
if ((a[left] > right))
if (a[right - 1] > right) }}
private
static
intpartition(int a, int left, int right, int pivot)
if (leftptr >= rightptr) else
}exchange(a,leftptr,right-1);
return leftptr;
}private
static
intmedian3(int a,int left, int right)
if (a[left] > a[right])
if (a[center] > a[right])
exchange(a,center,right-1);
return right-1;
}private
static
void
exchange(int a ,int x, int y)
}
快速排序的難點不在於理解,而在於**實現.
核心步驟是:
1. 指定某個值,
2. 把陣列中所有小於這個數的數放在左邊
3. 把陣列中所有大於這個數的數放在右邊
4. 對於左邊的陣列重複步驟12345
5. 對於右邊的陣列重複步驟12345
而在**中有很多細節需要注意.
基礎版快排
首先要有乙個驅動程式,穿入一左一右兩個指標
public
static
void
quicksort(int a)
直接選取最右的位置的值作為樞紐,寫出快排框架:
private
static
void
quicksort(int a, int left, int right)
int cutoff = partition(a, left, right,right);//以最右位為樞紐.
quicksort(a, left, cutoff - 1);
quicksort(a, cutoff + 1, right);
}
注意,此段程式為遞迴程式,所以引數必須為可變的.不能再內部指定left,right.
合格的遞迴應有恰當的跳出條件.左指標大於右指標的時候需要結束遞迴.
事實上partition方法承擔了大部分任務.它負責內部的跳躍交換,最後返回歸位後的樞紐位置.最後乙個引數是初始樞紐,直接給為right.
partition(a, left, right,right)
左遞迴,右遞迴.
quicksort(a, left, cutoff - 1);
quicksort(a, cutoff + 1, right);
接下來是分割程式.分割承擔了內部的跳躍任務,細節不太容易準確寫對.
private
static
intpartition(int a, int left,int right,int pivot)//右指標與樞紐比較,盡可能左移.由於先左移後比較,故只要right>0即可保證right-1>=0,不會左越界.最後落在小於等於pivot的位置.
if (leftptr >= rightptr) else
}exchange(a,leftptr,right);//樞紐歸位.
return leftptr;
}
三數取中版快排
三數分割法在選取樞紐的環節做了優化,使平均效率更高.雖然**量有所增加,但是反而使分割環節的細節好記了一些.
在基礎版中,選取樞紐的方法是直接任命right.而如果right並非約等於中值而是約等於最大值或最小值,將會有最差o(n^2)的時間複雜度.而三數分割法大大降低了這樣的可能性.
三數取中過程:
private
static
intmedian3(int a,int left, int right)
if (a[left] > a[right])
if (a[center] > a[right])
exchange(a,center,right-1);//最後把樞紐值置於倒數第二個位置.
return right-1;//返回樞紐位置.
}
分割過程:
private
static
intpartition(int a, int left, int right, int pivot)
if (leftptr >= rightptr) else
}exchange(a,leftptr,right-1);
return leftptr;
}
與基礎版類似,但是由於最左,最右,右倒2都已經被佔據且排好序,故在指定比較指標的時候要稍稍改變.另外,由於左右兩端都已經left<=pivotval<=right,所以內部while迴圈時無需再判斷邊界,一定不會越界.
當數值小於等於3的時候,為了效率要求,我們單獨為3個數寫出排序.
private
static
void
manualsort(int a,int left, int right)
if (size == 2)
} else
if ((a[left] > right))
if (a[right - 1] > right)
}}
簡單的快速排序
1 定義int left start,right end 再定義乙個標誌位 boolen flag true。2 在迴圈體中比較,只要left right,就進行比較。3 剛開始將最左邊數最為基準數basenumber arr left 將基準數basenumber逐一與右邊倒序比較,直到basen...
快速排序分析
1.開篇 終於還是忍不住要學習一下演算法啦,該面對的還是要面對,不能逃避,不能把已經會的技能忘掉,那是一種對生命的摧殘和不仁。不要怕,只要每天都在進步,水滴石穿,終有破雲見天日的時刻。感慨寫完了,回到正題,分析快速排序。2.原理 假設要排序的陣列是a 0 a n 1 首先任意選取乙個資料 通常選用陣...
快速排序分析
首先簡單描述一下快速排序 1.快速排序樹不穩定的 由於關鍵字的比較與交換是跳躍進行的 2.時間複雜度為o n logn 最好情況為n logn 若陣列基本有序為n n 3.空間複雜度為logn 主要是遞迴造成的棧空間的使用,最好情況,遞迴樹的深度為log2n,其空間複雜度也就為o logn 最壞情況...