排序詳細分析
前言 : 博主之前也是一直很懶 排序的時間複雜度也是都去看別人寫的 沒有測試過. 今天想想就把程式碼全部貼出來 C語言和JAVA程式碼都會貼出來 測試是在JAVA上測試的 而且之前一直沒怎麼用插入 因為懶就去寫冒泡的程式碼 因為短嘛! 我知道有人和我是一樣的哈哈. 如果是寫題或者別的幹嘛 就會 用C++的algorithm庫中的sort 或者 JAVA的 的sort方法. 其實C語言stdlib庫中也有qsort方法 有興趣的去查查. 最近學完了希爾排序 才發現 希爾排序也不是一般的好用 而且程式碼很好寫.所以今天我想把 各種排序的時間都貼出來和大家分享 注意! 我是在JAVA虛擬機器上測試出來的.
話不多說 : 先說說測試了什麼
1.簡單選擇排序
2.氣泡排序
3.插入排序
4.優化的插入排序
5.希爾排序.
6.優化的希爾排序.
7快速排序.
8.歸併排序.
9.JAVA的Arrays的sort方法(沒學JAVA可以不用管這個)
10.堆排序
先說明 我這裡的測試 用了0 - 10005 的隨機數
而且所有的排序都是用了同一個隨機數陣列 也就是9個方法 我複製了9份這樣陣列
for (int i = 0; i < N; i++) { box[i] = rm.nextInt(10005); //這裡就是獲得一個[0,10005)的隨機數 box2[i] = box[i]; box3[i] = box[i]; box4[i] = box[i]; box5[i] = box[i]; box6[i] = box[i]; box7[i] = box[i]; box8[i] = box[i]; box9[i] = box[i]; }
看不懂JAVA的不用去管 知道 這是隨機數就好
好了 宣告 N 就是我們的測試個數
開始讓N為10看一下結果
當N變為100
當N變為1000
兩張圖 1000的兩次結果 為了說明結果
接下來都是兩張圖
N = 10000
N = 100000
好了 接下來 加0的時候我準備取消幾個排序
以免太慢
有一次 我N = 1000000
我出去吃了個飯 冒泡還沒跑完
最後 跑了36分鐘....
N = 1000000
一激動 放了4張圖
N = 10000000
好了 結果已經對比出來了 冒泡 最慢 然後是 簡單選擇
然後是插入
當時剛學C語言1個多月的時候去打比賽
當時因為只掌握了冒泡和簡單選擇 快排不是太熟
怕寫不出來 有一道題要用排序 就用了冒泡
因為當時覺得 冒泡應該是插入 冒泡 和 簡單選擇
三個排序中最快的
後來發現是最慢的
結果那道題 一直執行超時 真後悔啊
總結 : 資料較少的時候都很快 N = 1000的時候建議用插入
這裡說一下 插入的優化 和希爾排序的優化是什麼
沒有優化的是交換
優化了的是 覆蓋 然後最後一次交換
N = 10000的時候 冒泡就開始吃力. 我記得C語言的比賽
時間限制好像是3000ms
插入排序在資料少 有序資料多的情況很不錯
資料少的時候不是很建議去使用快排 歸併
因為他們都有遞迴
而且 歸併雖然很快 但是有時間開銷.
其實我們現在做的無非也就是用時間去換空間
或者用空間去換時間
這裡我強烈推薦希爾排序 時間複雜度可以接受
不消耗空間 且寫法簡單
接下來就是程式碼
因為用到的語法和C語言很像就說明一下
如果想學習可以去看看別人的演算法教學
應該都很詳細,我就不講了哈哈哈...
後面都只寫核心程式碼
1.簡單選擇排序
for (int i = 0; i < N - 1; i++) {
int index = i;
for (int j = i + 1; j < N; j++) {
if (arr[index] < arr[j]) {
index = j;
}
}
int t = arr[i];
arr[i] = arr[index];
arr[index] = t;
}
2.氣泡排序
for (int i = 0; i < N - 1; i++) {
for (int j = 0; j < N - i; j++) {
if(arr[j] > arr[j+1]) {
int t = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = t;
}
}
}
3.插入排序
for (int i = 1; i < N; i++) {
int j;
for (j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
int t = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = t;
}
}
4.優化插入排序
for (int i = 1; i < N; i++) {
int temp = arr[i];
int j;
for (j = i;j> 0 && temp < arr[j - 1] ; j--) {
arr[j] = arr[j - 1];
}
arr[j] = temp;
}
5.希爾排序(個人最喜歡)
int n = 1;
while(n < N/3) n = n*3 + 1;
while (n >= 1) {
for (int i = n; i < N; i++) {
int j;
for (j = i; j >=n && arr[j] < arr[j-n]; j-=n) {
int t = arr[j];
arr[j] = arr[j - n];
arr[j - n] = t;
}
}
n/=3;
}
6.優化希爾排序(個人最喜歡)
int n = 1;
while(n < N/3) n = n*3 + 1;
while (n >= 1) {
for (int i = n; i < N; i++) {
int j;
int temp = arr[i];
for (j = i; j >=n && temp < arr[j-n]; j-=n) {
arr[j] = arr[j - n];
}
arr[j] = temp;
}
n/=3;
}
7.快速排序
因為用到函式遞迴所以函式宣告也寫
C語言把前面public static 去掉即可
public static void sort(int[] arr, int left, int right) {
if (left > right) {
return ;
}
int i = left, j = right, temp = arr[left], t;
while (i != j) {
while (arr[j] >= temp && i < j) {
j--;
}
while (arr[i] <= temp && i<j) {
i++;
}
if (i < j) {
t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[left] = arr[i];
arr[i] = temp;
sort(arr, left, i - 1);
sort(arr, i+1, right);
}
8.歸併排序
因為用到函式遞迴所以函式宣告也寫
C語言把前面public static 去掉即可
下文分配空間C語言可以在合併函式裡分配一個輔助空間
大小滿足r-l+1就行
直接定義 或者malloc(用完釋放)都可以
public static int[] temp = new int[N]; //這是分配空間的
public static void sort(int[] arr,int l, int r) {
if (l >= r) {
return;
}
int mid = (l + r)/2;
sort(arr, l, mid);
sort(arr, mid+1, r);
marge(arr,l, mid, r);
}
public static void marge(int[] arr, int l,int mid, int r) {
int i = l, j = mid+1;
for (int k = l; k <= r; k++) {
temp[k] = arr[k];
}
for (int k = l; k <= r; k++) {
if(i > mid) arr[k] = temp[j++];
else if(j > r) arr[k] = temp[i++];
else if(temp[j] < temp[i]) arr[k] = temp[j++];
else arr[k] = temp[i++];
}
}
10.歸併排序
因為用到函式遞迴所以函式宣告也寫
C語言把前面public static 去掉即可
public static void sort(int[] arr) {
for (int i = (N - 1) /2 -1; i >= 0; i--)
sink(arr,i,N-1);
int n = N - 1;
while (n > 0) {
int t = arr[0]; arr[0] = arr[n]; arr[n] = t;
n--;
sink(arr, 0, n);
}
}
public static void sink(int[] arr, int k, int n) {
while (2 * k + 1 <= n) {
int j = 2*k +1 ;
if (j+1 <= n && arr[j] < arr[j + 1]) j++;
if (arr[k] > arr[j]) break;
int t = arr[j]; arr[j] = arr[k]; arr[k] = t;
k = j;
}
}
個人認為 幾種排序的排名
理解難易度 選擇 < 冒泡 < 插入 < 歸併 < 快排 = 希爾 < 堆排
寫法難易度 選擇= 冒泡 < 插入 < 希爾 <快排 < 歸併 <= 堆排
歸併和堆排的寫法上小細節太多 容易出錯
我在寫的時候就出了幾個小錯誤 導致錯誤的排序
注意點就好了
好了就到這裡.有興趣的搜一下演算法趕快get起來吧哈哈