1. 程式人生 > >演算法導論-迴圈不變式、插入排序、歸併排序

演算法導論-迴圈不變式、插入排序、歸併排序

迴圈不變式
演算法導論第二章中的原文是: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;
}