排序算法的比較
算法 |
穩定性 |
時間複雜度 |
空間複雜度 |
備註 |
選擇排序 |
× |
N<sup>2</sup> |
1 |
|
冒泡排序 |
√ |
N<sup>2</sup> |
1 |
|
插入排序 |
√ |
N ~ N<sup>2</sup> |
1 |
時間複雜度和初始順序有關 |
希爾排序 |
× |
N 的若干倍乘於遞增序列的長度 |
1 |
改進版插入排序 |
快速排序 |
× |
NlogN |
logN |
|
三向切分快速排序 |
× |
N ~ NlogN |
logN |
適用於有大量重複主鍵 |
歸併排序 |
√ |
NlogN |
N |
|
堆排序 |
× |
NlogN |
1 |
沒法利用局部性原理 |
## 排序準備
/**
* 數字交換
*
* @param nums
* @param i
* @param j
*/
public void swapNums(T\[\] nums,int i,int j){
T temp = nums\[i\];
nums\[i\]=nums\[j\];
nums\[j\] = temp;
}
/**
* 大小比較
*
*/
public boolean lessNums(T a ,T b){
return a.compareTo(b)<0;
}
/**
* 大小比較
*/
public boolean lessOrEqualNums(T a, T b) {
return a.compareTo(b) <= 0;
}
選擇排序
選擇出數組中的最小元素,將它與數組的第一個元素交換位置。再從剩下的元素中選擇出最小的元素,將它與數組的第二個元素交換位置,不斷執行這樣的操做
public void selectSort(T[] nums) {
int n = nums.length;
for (int i=0;i<n;i++){
int min = i;
for(int j=i+1;j<n;j++){
if(lessNums(nums[j] , nums[min])){
min = j;
}
}
swapNums(nums,i,min);
}
}
冒泡排序
從左到右不斷交換相鄰逆序的元素,在一輪的循環以後,可讓未排序的最大元素上浮到右側。 在一輪循環中,若是沒有發生交換,就說明數組已是有序的,此時能夠直接退出。
public void ebullitionSort(T[] nums) {
int n = nums.length;
boolean isFinish = false;
for(int i = n-1;i>0 && !isFinish;i--){
isFinish = true;
for(int j=0;j<i;j++){
if(less(nums[j+1],nums[j])){
swapNums(nums,j+1,j);
isFinish = false;
}
}
}
}
插入排序
每次都將當前元素插入到左側已經排序的數組中,使得插入以後左側數組依然有序
public void insertSort(T[] nums) {
int n = nums.length;
for(int i=1;i<n;i++){
for(int j=i;j<n;j++){
if(lessNums(nums[j],nums[j-1])){
swapNums(nums,j,j-1);
}
}
}
}
快速排序
快速排序經過一個切分元素將數組分爲兩個子數組,左子數組小於等於切分元素,右子數組大於等於切分元素,將這兩個子數組排序也就將整個數組排序了
public void qucikSort(T[] nums, int start, int end) {
int i = start;
int j = end;
if(i>j){
return ;
}
T temp = nums[start];
while (i<j){
while(lessOrEqualNums(temp,nums[j]) && i<j){
j--;
}
while(lessOrEqualNums(nums[i],temp) && i<j){
i++;
}
if(i<j){
swapNums(nums,i,j);
}
}
swapNums(nums,start,j);
qucikSort(nums,start,j-1);
qucikSort(nums,j+1,end);
}