排序演算法是一種基本並且常用的演算法。由於實際工作中處理的數量巨大,所以排序演算法
對演算法本身的速度要求很高。
而一般我們所謂的演算法的效能主要是指演算法的複雜度,一般用o方法來表示。在後面我將
給出詳細的說明。
對於排序的演算法我想先做一點簡單的介紹,也是給這篇文章理乙個提綱。
我將按照演算法的複雜度,從簡單到難來分析演算法。
第一部分是簡單排序演算法,後面你將看到他們的共同點是演算法複雜度為o(n*n)(因為沒有
使用word,所以無法打出上標和下標)。
第二部分是高階排序演算法,複雜度為o(log2(n))。這裡我們只介紹一種演算法。另外還有幾種
演算法因為涉及樹與堆的概念,所以這裡不於討論。
第三部分類似動腦筋。這裡的兩種演算法並不是最好的(甚至有最慢的),但是演算法本身比較
奇特,值得參考(程式設計的角度)。同時也可以讓我們從另外的角度來認識這個問題。
第四部分是我送給大家的乙個餐後的甜點——乙個基於模板的通用快速排序。由於是模板函式
可以對任何資料型別排序(抱歉,裡面使用了一些論壇專家的呢稱)。
現在,讓我們開始吧:
一、簡單排序演算法
由於程式比較簡單,所以沒有加什麼注釋。所有的程式都給出了完整的執行**,並在我的vc環境
下執行通過。因為沒有涉及mfc和windows的內容,所以在borland c++的平台上應該也不會有什麼
問題的。在**的後面給出了執行過程示意,希望對理解有幫助。
1.冒泡法:
這是最原始,也是眾所周知的最慢的演算法了。他的名字的由來因為它的工作看來象是冒泡:
#include
void bubblesort(int* pdata,int count)
pdata[w+k] = itemp;
} }
} void main()
; shellsort(data,12);
for (int i=0;i<12;i++)
cout<(cmydata& data );
private:
char* m_strdatamember;
int m_idatasize;
}; mydata.cpp檔案
cmydata::cmydata():
m_iindex(0),
m_idatasize(0),
m_strdatamember(null)
cmydata::~cmydata()
cmydata::cmydata(int index,char* strdata):
m_iindex(index),
m_idatasize(0),
m_strdatamember(null)
cmydata& cmydata::operator =(cmydata &srcdata)
bool cmydata::operator <(cmydata& data )
bool cmydata::operator >(cmydata& data )
///
// //主程式部分
#include
#include "mydata.h"
template
void run(t* pdata,int left,int right)
}while(i<=j);//如果兩邊掃瞄的下標交錯,就停止(完成一次)
//當左邊部分有值(lefti),遞迴右半邊
if(right>i)
run(pdata,i,right);
} template
void quicksort(t* pdata,int count)
void main()
; quicksort(data,8);
for (int i=0;i<8;i++)
cout<(itemp=9)10,9,8,7->(itemp=8)10,9,8,7->(itemp=7)7,9,8,10(交換1次)
第二輪:7,9,8,10->7,9,8,10(itemp=8)->(itemp=8)7,8,9,10(交換1次)
第一輪:7,8,9,10->(itemp=9)7,8,9,10(交換0次)
迴圈次數:6次
交換次數:2次
其他:
第一輪:8,10,7,9->(itemp=8)8,10,7,9->(itemp=7)8,10,7,9->(itemp=7)7,10,8,9(交換1次)
第二輪:7,10,8,9->(itemp=8)7,10,8,9->(itemp=8)7,8,10,9(交換1次)
第一輪:7,8,10,9->(itemp=9)7,8,9,10(交換1次)
迴圈次數:6次
交換次數:3次
遺憾的是演算法需要的迴圈次數依然是1/2*(n-1)*n。所以演算法複雜度為o(n*n)。
我們來看他的交換。由於每次外層迴圈只產生一次交換(只有乙個最小值)。所以f(n)<=n
所以我們有f(n)=o(n)。所以,在資料較亂的時候,可以減少一定的交換次數。
4.插入法:
插入法較為複雜,它的基本工作原理是抽出牌,在前面的牌中尋找相應的位置插入,然後繼續下一張
#include
void insertsort(int* pdata,int count)
}while(i<=j);//如果兩邊掃瞄的下標交錯,就停止(完成一次)
//當左邊部分有值(lefti),遞迴右半邊
if(right>i)
run(pdata,i,right);
} void quicksort(int* pdata,int count)
void main()
; quicksort(data,7);
for (int i=0;i<7;i++)
cout<
cout<<"/n"; } 這裡我沒有給出行為的分析,因為這個很簡單,我們直接來分析演算法:首先我們考慮最理想的情況 1.陣列的大小是2的冪,這樣分下去始終可以被2整除。假設為2的k次方,即k=log2(n)。 2.每次我們選擇的值剛好是中間值,這樣,陣列才可以被等分。 第一層遞迴,迴圈n次,第二層迴圈2*(n/2)...... 所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n 所以演算法複雜度為o(log2(n)*n) 其他的情況只會比這種情況差,最差的情況是每次選擇到的middle都是最小值或最大值,那麼他將變 成交換法(由於使用了遞迴,情況更糟)。但是你認為這種情況發生的機率有多大??呵呵,你完全 不必擔心這個問題。實踐證明,大多數的情況,快速排序總是最好的。 如果你擔心這個問題,你可以使用堆排序,這是一種穩定的o(log2(n)*n)演算法,但是通常情況下速度要慢 於快速排序(因為要重組堆)。 三、其他排序 1.雙向冒泡: 各種插入排序演算法小結 巧若拙直接插入排序是將元素vec i 插入到有序序列vec 0.i 1 依次將vec i 與vec i 1 vec i 2 進行比較,找到插入位置即將vec i 插入,原來位置上的物件向後順移。直接插入演算法 如下 voidinsertsort 1 int vec,int n... 各種排序演算法想必大家都不陌生,定義我就不多介紹了,直接寫下自己的一些小結。快速排序 可以算的上應用最廣的排序演算法。其排序思路是隨機選取乙個數字作為標誌,使得小於它的數在它左邊,大於它的數在它的右邊,然後遞迴對兩邊的資料排序。歸併排序 應用分之的思想,先將要排序的分為兩列,然後分別進行排序,然後合... 每次將乙個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子表中適當位置,直到全部記錄插入完成為止 待排序的記錄放在陣列r 0,n 1 中 排序過程中將r分成兩個子區間,有序區r 0,i 1 無序區r i,n 1 將當前無序區的第1個記錄,插入到有序區中適當的位置上 每次是有序區增加乙個記錄,知道...各種插入排序演算法小結
各種排序演算法小結和實現
排序 各種排序演算法