衡量演算法的好壞指標,顯然首先這個演算法是正確的,除此之外,通常有三個方面的考慮:
(1)演算法在執行過程中所消耗的時間;
(2)演算法在執行過程中所佔資源的大小,例如,占用記憶體空間的大小;
(3)演算法的易理解性、易實現性和易驗證性等等。我們經常討論的時間複雜度是比較常見的評價標準之一。
• 演算法的時間複雜度定義:
若有某個輔助函式f(n),當n趨向於無窮大時,如果t(n)/ f(n)的極限為不等於零的常數,則認為t(n)與f(n)是同量級的函式,記作:t(n) =o(f(n)),o(f(n))稱為演算法的漸進時間複雜度,簡稱時間複雜度。
• 漸進時間複雜度意義:
(1)在較複雜的演算法中,進行精確分析是非常複雜的;
(2)一般來說,我們並不關心t(n)的精確度量,而只是關心其量級。t (n) = o(f (n)) 表示存在乙個常數c,當n趨於正無窮大時,總有t (n) ≤ c * f(n),其意義是t(n)在n趨於正無窮大時跟f(n)基本接近,因此完全可以用f(n)來表示t(n)。
在各種不同的演算法中,若演算法語句的執行次數為常數,則演算法的時間複雜度為o(1),按數量級遞增排列,常見的時間複雜度量有:(1
)o(1)
:常量階,執行時間為常量 (
2)o(logn)
:對數階,如二分搜尋演算法 (
3)o(n)
:線性階,如
n個數內找最大值 (
4)o(nlogn)
:對數階,如快速排序演算法 (
5)o(n^2)
:平方階,如選擇排序,氣泡排序 (
6)o(n^3)
:立方階,如兩個
n階矩陣的乘法運算 (
7)o(2^n)
:指數階,如
n個元素集合的所有子集的演算法 (
8)o(n!)
:階乘階,如
n個元素全部排列的演算法
• 計算步驟
(1)找出演算法中重複執行次數最多的語句的頻度來估算演算法的時間複雜度;
(2)保留演算法的最高次冪,忽略所有低次冪和高次冪的係數;
(3)將演算法執行次數的數量級放入大ο記號中。
排序演算法的穩定性:(1)穩定:如果a原本在b前面,而a=b,排序之後a仍然在b的前面;(2)不穩定:如果a原本在b的前面,而a=b,排序之後 a 可能會出現在 b 的後面。
//變數值交換
templatevoid swap(t& a, t& b)
//一維陣列列印
templatevoid printarray(t data, int n)
std::cout<1、選擇排序及其優化版本
選擇排序
//普通選擇排序
//每次調動indexofmax(a,size)需要執行size-1次比較,因此總共的比較次數為n-1+n-2+...+1=n(n-1)/2
//取最高次,則表示為漸進記法為o(n^2)
//最差時間複雜度:o(n^2)
//最優時間複雜度:o(n^2)
//平均時間複雜度:o(n^2)
//穩定性:不穩定
templateint indexofmax(t a, int n)
return max_index;
}templatevoid selectionsort(t a, int n)
}//優化:即時終止選擇排序
templatevoid selectionsort_(t a, int n)
if(indexofmax!=size-1)
swap(a[size - 1], a[indexofmax]);}}
2、氣泡排序及其優化版本
//氣泡排序
//在要排序的一組數中,對當前還未排好序的範圍內的全部數,自上而下對相鄰的兩個數依次進行比較和調整,
//讓較大的數往下沉,較小的往上冒。即:每當兩相鄰的數比較後發現它們的排序與排序要求相反時,就將它們互換。
//對任意數k ,函式bubble(t a, int n) 比較n-1次,則n-1+n-2+...1=n(n-1)/2
//最差時間複雜度:o(n^2)
//最優時間複雜度:o(n^2)
//平均時間複雜度:o(n^2)
//穩定性:穩定
templatevoid bubble(t a, int n)
}templatevoid bubblesort(t a, int n)
}//優化:即時終止氣泡排序
templatebool bubble2(t a, int n)
}}templatevoid bubblesort2(t a, int n)
3、插入排序
//插入排序
//插入排序是一種最簡單直觀的排序演算法,它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃瞄,找到相應位置並插入。
//1)將第一待排序序列第乙個元素看做乙個有序序列,把第二個元素到最後乙個元素當成是未排序序列。
//2)從頭到尾依次掃瞄未排序序列,將掃瞄到的每個元素插入有序序列的適當位置。(如果待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的後面。)
//最差時間複雜度:o(n^2)
//最優時間複雜度:o(n)
//平均時間複雜度:o(n ^ 2)
//穩定性:穩定
templatevoid insertionsort(t a, int n)
a[j] = temp;}}
4、快速排序
/快速排序:分治法、遞迴
//1、從數列中取出乙個數作為基準數(樞軸,pivot)。
//2、將陣列進行劃分(partition),將比基準數大的元素都移至樞軸右邊,將小於等於基準數的元素都移至樞軸左邊。
//3、再對左右的子區間重複第二步的劃分操作,直至每個子區間只有乙個元素。
//平均時間複雜度: o(nlogn)
//最壞時間複雜度: o(n*n) 比如降序陣列排成公升序,反之則反之
//最好時間的複雜度: o(nlogn) 二叉樹深度logn
//穩定性:不穩定
templateint partition(t data, int left,int right)
swap(data[left], data[j]);
return j;
}templatevoid quicksort(t data, int left, int right)
5、待續…
主函式驗證:
int main() ;
printarray(data, 10);
//bublesort(data, 10);
//selectivesort(data, 10);
//selectionsort_(data, 10);
//insertionsort(data, 10);
quicksort(data, 0, 9);
std::cout << "after sort: " << std::endl;
printarray(data, 10);
system("pause");
return 0;
}
參考:
《資料結構、演算法與應用》
C 之排序演算法
這是乙個新手的總結。資料的排序方法有許多,這裡總結一下我所知道的。一 選擇排序。插入排序的時間複雜度最好的情況是已經是正序的序列,只需比較 n 1 次,時間複雜度為o n 最壞的情況是倒序的序列,要比較n n 1 2次,時間複雜度為o n 2 平均的話要比較時間複雜度為o n 2 插入排序適用於資料...
C 排序演算法之氣泡排序
氣泡排序 思想 通過一系列的 交換 動作完成。首先第乙個記錄和第二個記錄比較,如果第乙個大,則二者交換,否則不交換 然後第二個記錄和第三個記錄比較,如果第二個大,則二者交換,否則不交換.一直按這種方式進行下去,最終最大的那個記錄被交換到了最後,一趟氣泡排序完成。這個過程中,大的記錄像一塊石頭一樣 沉...
C 排序演算法之堆排序
一 基本概念 堆 這裡是指一種資料結構,而不是我們在c 中提到的用於儲存引用型別物件的地方。它可以被當成一棵完全二叉樹lnemcgqax。為了將堆用陣列www.cppcns.com來存放,這裡對每個節點標上順序。事實上,我們可以用簡單的計算公式得出父節點,左孩子,右孩子的索引 parent i le...