日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法导论学习笔记 第2章 算法基础

發布時間:2024/9/16 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法导论学习笔记 第2章 算法基础 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? 本章介紹了一個貫穿本書的框架,后續的算法設計都是在這個框架中進行的。

? 本章通過插入排序歸并排序兩種常見的算法來說明算法的過程及算法分析,在分析插入排序算法時,書中是用了循環不變式證明了算法的正確性,在介紹歸并排序時算法過程中引入了分治法的思想。

2.1 插入排序

? 這是我們的第一個算法(插入排序)用于求解第一章中引入的排序問題

? 輸入:n個數的一個序列<a1, a2, ..., an>。

? 輸出:輸入序列的一個排列<a1', a2', ..., an' >,滿足a1‘<=a2'<=...<=an'

? 插入排序的基本操作是將一個記錄插入到以排序好的有序表中,從而得到一個新的記錄數增1的有序表。一般情況下,第i趟直接插入排序的操作為:在含有i-1個記錄的有序子序列r[1..i-1]中插入一個A[i]后,編程含有i個記錄的有序子序列r[1..i],直到把第n個元素插入到n-1個元素中,最終使得n個元素有序。插入排序的為代碼如下:

INSERTION_SORT(A) 1 for j=2 to A.length 2 key = A[j] 3 //Insert A[j] into the sorted sequence A[1.. j-1] 4 i = j - 1 5 while(i>0 and A[i]>key) 6 A[i+1] = A[i] 7 i = i - 1 8 A[i+1] = key</span> ? 循環不變式主要用來幫助我們理解算法的正確性。關于循環不變式,我們必須證明三條性質:

? 初始化:循環的第一次迭代之前,它為真。

? 保持:如果循環的某次迭代之前他為真,那么下次迭代之前它仍未真。

? 終止:在循環終止時,不變式提供了一個有用的性質,該性質有助于證明算法是正確的。

? 插入排序的證明過程:

? 初始化:當j=2時,子數組A[1.. j-1]僅由單個元素A[1]組成,實際上就是A[1]原來的元素。而且該子數組是排序好的,這表明第一次循環迭代之前循環不變式成立。

? 保持:for循環的4-7行將A[j-1], A[j-2], A[j-3]等右移一個位置,直到找到A[j]的適當位置,第8行將A[j]插入該位置。這是子數組A[1.. j]由原來在A[1.. j]中的元素組成,但已經按順序排列。那么對for循環的下一次迭代增加j將保持循環不變式。

? 終止:導致for循環終止的條件式j>A.length = n。在循環不變式中將j用n+1代替,我們有:子數組A[1.. n]由原來在A[1.. n]中的元素組成,但已經按順序排序。因此算法正確。采用c語言編寫的插入排序的完整程序如下:

void insertionSort(int *arr, int length){//判斷參數是否合法if(arr == NULL || 0==length){printf("Check datas or length.\n");exit(1);}//數組下標是從0開始的,從第二個元素(對應下標1)開始向前插入for(int j=1; j<length; j++){int key = arr[j]; //記錄當前要插入的元素int i = j - 1; //前面已經有序的元素//尋找待插入元素的位置,從小到到排序,如果是從大到小改為arr[i]<keywhile(i>=0 && arr[i]>key){arr[i+1] = arr[i];i--; //向前移動}arr[i+1] = key;} }</span>

插入排序的算法分析

? 過程INSERTION-SORT需要的時間依賴于輸入:排序1000個數排序三個數需要更長的時間。此外,依據它們已經被排序的程度,INSERTION-SORT可能需要不同的數量時間來排序一個具有相同規模的輸入序列。插入排序算法中,若輸入的數組已經排好序,則出現最佳情況。這時對每個j=2, 3, ..., n,程序中的第5行,當i = j - 1時,有A[i]<=key。此時算法的復雜度為O(n)。若輸入的數組已反向排序,即按遞減序列,則導致最壞情況。此時INSERTION-SORT算法的時間復雜度為O(n^2)。

2.2 歸并排序

?分治法的思想是:將原問題分解為幾個規模較小但類似于原問題的子問題,遞歸地求解這些問題,然后在合并這些子問題的解來建立原問題的解。

歸并排序算法完全遵循分治策略。直觀上操作如下:

?分解:把具有n個元素的序列分解成具有n/2個元素的兩個子序列

?解決:使用歸并排序遞歸地排序兩個子序列

?合并:合并兩個已排序的子序列則可得到n個元素的排序序列

?歸并排序算法的關鍵操作是“合并”步驟中兩個已排序的序列。書中通過調用的一個輔助過程MERGE(A, p, q, r)來完成合并,MERGE算法的偽代碼如下(算法在實現的過程中是用來哨兵):

MERGE(A, p, q, r) 1 n1 = q - p + 1 2 n2 = r - q 3 let L[1.. n1+1] and R[1.. n2+1] 4 for i=1 to n1 5 L[i] = A[p + i -1] 6 for j=1 to n2 7 R[j] = A[q + j] 8 L[n1+1] = MAX 9 R[n2+1] = MAX 10 i = 1 11 j=1 12 for k=p to r 13 if L[i]<=R[j] 14 A[k] = L[i] 15 i = i + 1 16 else 17 A[k] = R[j] 18 j = j + 1

算法采用c++ 語言完整程序為:

void Merge(int *arr, int p, int q, int r) {int n1 = q - p + 1; //第一個有序子數組元素個數int n2 = r - q; //第二個有序子數組元素個數int *Left = (int *)malloc(sizeof(int)*(n1 + 1));int *Right = (int *)malloc(sizeof(int)*(n2 + 1));//將子數組復制到臨時輔助空間for(int i=0; i<n1; i++){Left[i] = arr[p+i];}for(int j=0; j<n2; j++){Right[j] = arr[q+j+1];}//添加哨兵Left[n1] = INT_MAX;Right[n2] = INT_MAX;//從第一個元素開始合并int i = 0;int j = 0;for(int k=p; k<=r; k++){if(Left[i] <= Right[j]){arr[k] = Left[i];++i;}else{arr[k] = Right[j];++j;}}free(Left);free(Right); }

現在我們可以把過程MERGE作為歸并排序算法中的一個子程序來用。MERGE-SORT(A, p, r)是實現歸并排序的算法:

MERGE-SORT(A, p, r) 1 if p < r 2 q = (p + r) / 2 //向下取整 3 MERGE-SORT(A, p, q) 4 MERGE-SORT(A, q + 1, r) 5 MERGE(A, p, q, r)

采用C++完整程序為:

void MergeSort(int *arr, int p, int r) {if(p < r){int q = (p + r) / 2;MergeSort(arr, p , q);MergeSort(arr, q + 1, r);Merge(arr, p, q, r);}}

merge過程的運行時間是θ(n),現將merge過程作為歸并排序中的一個子程序使用,merge_sort(A,p,r),對數組A[p...r]進行排序,實例分析如下圖所示:


歸并排序的算法分析

歸并排序算法包含對其自身的遞歸調用,我們可以用遞歸方程或遞歸式來描述其運行時間,歸并排序算法的最壞情況運行時間T(n)的遞歸式為:若n>1,T(n) = 2T(n / 2) +?Θ(n);若n=1,T(n)=?Θ(1)。該遞歸式可以由主定理求得T(n)的復雜度為Θ(nlgn)。

總結

以上是生活随笔為你收集整理的算法导论学习笔记 第2章 算法基础的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。