簡單的幾個排序演算法
1.首先介紹最簡答的氣泡排序演算法,顧名思義就是像水中冒泡一樣,每次把當前混亂集合中的第一個資料依次和後面的資料進行比較,然後依次往後面行進。那麼每次排一個資料,則需要n-1次排序,每次要和n-1個資料比較
void Sort(int *number,int numberSize)
{
int i,j,temp;
for(i = 0;i < numberSize-1;i++) //需要n-1趟排序(最後一個資料自然就會有順序了)
{
for(j = 0;j < numberSize-i-1;j++) //因為前面的資料和n-1個資料比較了,那麼當前資料一定和後面的有序集合的資料
{ //已經有大小關係了,那麼只需要比較混亂集合即可
if(number[j] > number[j+1]) //從小到大的排序
{
temp = number[j];
number[j] = number[j+1];
number[j+1] = temp;
}
}
}
}
顯然這段程式碼的複雜度是O(n^2)時間複雜度。該冒泡演算法還可以進行一些小的優化,但是時間複雜度級別還是接近O(n^2)。
2.直接插入排序,該演算法是基於這麼一個思想。我給定一串有序的資料,我現在要插入一個資料並且我還想保持資料的順序。那麼我採取的做法就是從前往後或者從後往前挨個比較,然後插入就行。這樣對於一串無序的數,我們可以假設第一個資料是有序的,其餘的資料屬於(n-1)次輸入的資料,也就是呼叫了n-1次插入排序。最後混亂集合就變成了有序集合。
void Sort(int *number,int numberSize)
{
int i =0,j,Soldier; //這個是存放當前的比較數,為了方便後面減少交換次數的小技巧
for(i = 1;i < numberSize;i++)
{
Soldier = number[i];
for(j = i-1;j >= 0;j--)
{
if(Soldier < number[j])
{
number[j+1] = number[j]; //減少交換次數
}
else
{
number[j+1] = Soldier;
break;
}
}
if(j < 0)
number[0] = Soldier;
}
}
該演算法雖然時間複雜度還是在O(n^2)但是卻是進行了很多的優化,我們不妨來計算一下,假設輸入(n+1)個資料,那麼最壞的情況就是初始順序和我們要排列的順序相反,完全逆序。那麼第一次需要排列1次,第二次2次,。。。。依次類推。那麼最後是
(1+2+3+4+。。。。+n) = O(n^2);但是實際上是O(n*(n+1)/2),還是比冒泡的直接O(n^2)要快上不少的。
3.希爾排序,其實希爾排序就是上面直接插入排序的優化版本。但是希爾演算法非常好的利用了直接插入演算法的長處,對於儘可能有序的數列進行插入排序的時候可以達到O(n)時間複雜度這個特性,所以希爾演算法就是先將資料進行分組,具體怎麼分組這個大家可以網上百度,有非常多的分組方法,因為並沒有一個定論怎麼樣分組是最優的。我們這裡採用分組數是原始資料個數不停的二分。
void FUZHU_Sort(int *number,int numberSize,int step)
{
int i,j,k,Soldier;
for(k = 0;k < step;k++)
{
for(i = k+step;i < numberSize;i+=step) //這裡和直接插入排序是有區別的,因為並不是0,1,2這樣連著排序的,而是
{ //0,0+step,0+step+step這樣排序的
Soldier = number[i];
for(j = i-step;j >= 0;j-=step)
{
if(Soldier < number[j])
{
number[j+step] = number[j];
}
else
{
number[j+step] = Soldier;
break;
}
}
if(j < 0)
number[k] = Soldier; //多組的起始位置
}
}
}
void Shell_Sort(int *number,int numberSize)
{
int step = numberSize/2;
while(step > 0)
{
FUZHU_Sort(number,numberSize,step);
step = step/2;
}
}
4.歸併排序,歸併排序的思想是,把帶排序的資料不停的折半,最後折半到每一半都只有一個資料,那麼這個資料肯定是有序的,然後再把左右的歸併,歸併就是用一個迴圈來挨個比較兩邊的資料,小(大)的進入一個臨時陣列,最後比較完畢再把臨時陣列放回去。
void Merge_Sort(int *number,int numberSize,int low,int high)
{
if(low == high)
return;
int mid = (low+high)/2;
//分治
Merge_Sort(number,numberSize,low,mid);
Merge_Sort(number,numberSize,mid+1,high);
//歸併
int i = low,j = mid+1;
int *temp = (int *)malloc(sizeof(int)*(high-low+1));
int count = 0;
while(i <= mid && j <= high)
{
if(number[i] < number[j])
temp[count++] = number[i++];
else
temp[count++] = number[j++];
}
//還有沒做完的:
while(i <= mid)
temp[count++] = number[i++];
while(j <= high)
temp[count++] = number[j++];
for(i = low;i <= high;i++)
number[i] = temp[i-low];
}
歸併排序的分治歸併的狀態方程:T(n) = 2 * T(n/2)+O(n)很容易推出其時間複雜度是O(nlogn)(主定理法是可以直接看出來的,詳細見前面的時間複雜度的分析。)
5.快速排序,思想是每次選取一個基值,然後將每個數和這個數比較,大於它的放後面,小於它的放前面。然後從這個點斷開分成兩邊繼續重複這個操作,直到最後一個數。其實也是分治法。
void quick_Sort(int *number,int numberSize,int low,int high)
{
if(low == high)
return;
//先排序後分治
int i = low,j = high; //首尾計數器
int mid = (low+high)/2;
int base_number = number[low]; //每次以第一個作為基準
int temp;
while(i < j)
{
while(number[j] >= base_number && j > i)
j--;
if(j <= i)
break;
else
{
temp = number[j];
number[j] = number[i];
number[i] =temp;
}
while(number[i] < base_number && i < j)
i++;
if(i >= j)
break;
else
{
temp = number[j];
number[j] = number[i];
number[i] =temp;
}
}
for(int k = low;k < numberSize;k++)
{
if(number[k] == base_number)
break;
}
quick_Sort(number,numberSize,low,k);
quick_Sort(number,numberSize,k+1,high);
}
本段程式碼是設定了一個首位計數器,先從尾部開始,大於基數不管,一旦小於基數就和首指標指向的數交換,然後首指標開始運作,一旦首指標指向的數大於基數,那麼就和尾指標指向的數交換,然後尾指標開始運作,最後到首尾指標重合結束一次。快速排序的時間複雜度不難看出是O(nlogn)因為分治分方程基本是一樣的和前面的。
以上都是一些簡單的常用的排序,當然都是有很大優化空間的,這些可以自己思考,然後一些稍微複雜的排序將會在後序更新。
相關文章
- 簡單排序演算法排序演算法
- 簡述幾種常用的排序演算法排序演算法
- 菜鳥必看的排序演算法(簡單通俗)及程式碼實現,幾張圖帶你吃透排序演算法排序演算法
- 幾種常用的排序演算法排序演算法
- 簡單的排序方法排序
- 幾種經典的排序演算法排序演算法
- Java常見排序演算法之插入排序-簡單的效能優化技巧Java排序演算法優化
- PHP 簡單的幾個設計模式(個人理解)PHP設計模式
- 快速排序的簡單理解排序
- 【演算法】排序04——程式碼簡約而不簡單的希爾排序(含程式碼實現)演算法排序
- 簡單快速排序排序
- 7.1簡單排序排序
- 簡單選擇排序就是簡單~~~排序
- 幾個簡單又實用的PHP函式PHP函式
- C#中的幾個簡單技術點C#
- 最簡單易懂的三種排序演算法:冒泡、選擇、插入排序演算法
- 史上最簡單的排序演算法?看起來卻滿是bug排序演算法
- 【小小前端】前端排序演算法第三期(不簡單選擇排序-堆排序)前端排序演算法
- 基數排序的簡單理解排序
- 歸併排序的簡單理解排序
- 氣泡排序的簡單理解排序
- 選擇排序的簡單理解排序
- 簡單選擇排序排序
- 字串-簡單字串排序字串排序
- 幾種常見的排序演算法總結排序演算法
- 35.幾種常見的排序演算法排序演算法
- js數值排序中冒泡演算法的4種簡單實現JS排序演算法
- 淺解前端必須掌握的演算法(二):簡單選擇排序前端演算法排序
- 配置簡單的linux 的幾個操作步驟(Cent OS)Linux
- 郵箱 郵政編碼 等幾個簡單的 正則 表示式的幾個例子?
- 面試常問的幾個排序和查詢演算法,PHP 實現面試排序演算法PHP
- 經常提及的幾個js排序方法(氣泡排序、選擇排序、計數排序)JS排序
- 實現一個簡單的DOM diff演算法演算法
- 實現一個簡單的輪詢演算法演算法
- 幾種常用的排序演算法之JavaScript實現排序演算法JavaScript
- 幾種排序演算法的原理以及 Java 實現排序演算法Java
- 簡單說幾個MySQL高頻面試題MySql面試題
- 幾種常見排序演算法總結排序演算法