演算法導論-迴圈不變式、插入排序、歸併排序
阿新 • • 發佈:2019-01-01
迴圈不變式
演算法導論第二章中的原文是:We state these properties of A[1 ‥ j -1] formally as a loop invariant。其中舉的例子是插入排序,每次迴圈從陣列A中取出第j個元素插入有序區A[1 .. j-1],然後遞增j。這樣A[1 .. j-1]的有序性始終得到保持,這就是所謂的“迴圈不變”了。
這個概念主要用來檢驗演算法的正確性
1. 初始化(迴圈第一次迭代之前)的時候,A[1 ‥ j -1]的“有序性”是成立的;
2. 在迴圈的每次迭代過程中,A[1 ‥ j -1]的“有序性”仍然保持;
3. 迴圈結束的時候,A[1 ‥ j -1]的“有序性”仍然成立。
我的理解就是:解集合中的解一定正確。每次迴圈之後將新的解歸入解集合,直至全部數都歸入解集合。
插入排序
思路:假設最前面的第一個數已排好序,迴圈新增後面的數,新增的時候如果被新增的數滿足條件就和前面的數交換位置,最終每一個數都到達自己的位置,排序結束。T(n)=O(n^2).
歸併排序
思路:歸併排序屬於分治法的一種:把待排序的序列分為若干自序列,每個子序列都是有序的,然後把有序子序列合併為整體有序序列。T(n)=O(nlgn).
演算法導論第二章中的原文是:We state these properties of A[1 ‥ j -1] formally as a loop invariant。其中舉的例子是插入排序,每次迴圈從陣列A中取出第j個元素插入有序區A[1 .. j-1],然後遞增j。這樣A[1 .. j-1]的有序性始終得到保持,這就是所謂的“迴圈不變”了。
這個概念主要用來檢驗演算法的正確性
1. 初始化(迴圈第一次迭代之前)的時候,A[1 ‥ j -1]的“有序性”是成立的;
2. 在迴圈的每次迭代過程中,A[1 ‥ j -1]的“有序性”仍然保持;
3. 迴圈結束的時候,A[1 ‥ j -1]的“有序性”仍然成立。
我的理解就是:解集合中的解一定正確。每次迴圈之後將新的解歸入解集合,直至全部數都歸入解集合。
插入排序
思路:假設最前面的第一個數已排好序,迴圈新增後面的數,新增的時候如果被新增的數滿足條件就和前面的數交換位置,最終每一個數都到達自己的位置,排序結束。T(n)=O(n^2).
#include<stdio.h> void insertSort(int *a,int n) { int i,j; for(i=1;i<=n;i++) { int tmp=a[i]; j=i; while(j>0&&a[j-1]>tmp) { a[j]=a[j-1]; j--; } a[j]=tmp; } printf("After insert-sort:\n"); for(i=1;i<n;i++) printf("%6d",a[i]); printf("\n"); } int main() { int a[]={1,9,3,5,23,15,8}; insertSort(a,7);; return 0; }
歸併排序
思路:歸併排序屬於分治法的一種:把待排序的序列分為若干自序列,每個子序列都是有序的,然後把有序子序列合併為整體有序序列。T(n)=O(nlgn).
#include<stdio.h> const int maxSize=100; void merge(int a[],int n) { int i,j,k=0; //將a中資料暫存在b中 int b[10]; for(i=0;i<n;i++) b[i]=a[i]; i=0,j=n/2; while(i<n/2&&j<n) { if(b[i]<=b[j])a[k++]=b[i++]; else a[k++]=b[j++]; } if(i<n/2) for(;i<n/2;i++) a[k++]=b[i]; if(j<n) for(;j<n;j++) a[k++]=b[j]; printf("After merge-sort:\n"); for(i=0;i<n;i++) printf("%6d",a[i]); printf("\n"); } void mergeSort(int *a,int n) { if(n>=2) { mergeSort(a,n/2); mergeSort(a+n/2,n-n/2); merge(a,n); } } int main() { int a[]={27,22,18,20,15,19,12}; mergeSort(a,7); //printf("Hello!"); return 0; }