通俗的讲,算法是解决问题的方法或过程;严格的讲,算法是满足以下性质的指令序列:
1.输入:有另个或者多个外部量作为算法的输入。
2.输出:算法产生至少一个量作为输出。
3.确定性:组成算法的每条指令是清晰的,无歧义的。
4.有限性:算法中每条指令的执行次数有限,执行每条指令的时间也有限。
程序不同与算法,程序是算法用某种程序设计语言的具体实现。
对于一个明确的数学问题,设计它的算法,总是选用该问题的一个数据模型。接着弄清楚该问题是数据模型在已知条件下的初始状态和要求的结果状态,以及这连个状态之间的隐含关系。然后探索从数据模型的已知状态到达要求的结果状态所需的运算步骤。这些运算步骤就是求解该问题的算法。
抽象数据类型是算法设计的重要概念。描述算法可以有很多种,如自然语言方式,表格方式,以及程序设计语言方式等方式。
算法复杂性的高低天现在勋兴该算法所需要的计算机资源的多少上,所需要的资源越多,则算法的复杂性越高;反之,该算法的复杂性越低。
由于计算机的资源最重要的是时间和空间资源,因此算法的复杂性有时间复杂性和空间复杂性之分。
更确切的说,算法的复杂性是算法运行所需要的计算机资源的量,需要时间资源的量称为时间复杂性,需要空间资源的量称为空间复杂性。这个量应该集中反映算法的效率而从运行该算法的实际计算机中抽象出来。这个量应该只依赖于算法要解的问题的规模,算法的输入和算法本身函数。
任何可以用计算机求解的问题所需要的计算时间都与其规模有关,问题的规模越小,解题所需要的计算时间往往也越少。故此,分治法的设计思想是,将一个难以直接解决的的问题,分割成一些规模比较小的相同问题,以便各个击破,分而治之。
分治法的基本思想是讲一个规模为n的问题分解成k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归的解这些子问题,然后将各个子问题的解合并得到原问题的解。它的一般算法设计模式如下:
divide-and-conquer(P)
{
if(|P|<=n0) adhoc(P);
divide P into smaller subinstances P1,P2,P3...,Pk;
for(i=1;i<=k;i++)
yi=divide-and-conquer(Pi);
return merge(y1,...,yk);
}
|P|表示问题的规模,n0表示一个阈值,adhoc(P)表示解决小规模问题的基本算法。该代码段的含义即为:当给定问题的规模大于确定的阈值时,通过分治法将其划分为多个相同的子问题,且子问题的规模小于确定的阈值,通过给定的子问题解决算法将所有子问题一一求解,最后合并多个子问题的解,即为最初给定问题的解。
给定已排好序的n各元素a[0:n-1],现在要在这n各元素中找出一特定元素x。
二分搜索的基恩思想是将n个元素分成大致相同的两半,取a[n/2]与x进行比较。如果x=a[n/2],则找到x,算法中止。如果x
Algorithm::BinarySearching(int a[],int n,int x)
{
int left(0);
int right(n-1);
int middle;
while(left<=right)
{
middle=(left+right)/2;
if(x==a[middle]) return middle;
else if(x>a[middle]) left=middle+1;
else right=middle-1;
}
return -1;
}
合并排序算法是用分治策略实现对n个元素进行排序的算法,其基本思想是:将待排序的数组元素分割成大小大致相同的2个子集合,分别对两个子集合进行排序最终将排好序的子集合合并成为所有要求的排好序的集合。合并排序算法可以递归地描述如下:
void mergeSort(int a[],int left,int right)
{
if(left>right)
{
int middle=(left+right)/2;
mergeSort(a,left,middle-1);
mergeSort(a,middle+1,right);
meger(a,b,left,i,right);
copy(a,b,left,right);
}
}
合并排序的非递归代码如下:
void Algorithm::mergeSort(int a[],int n)
{
int *b=new int[n];
int s=1;
while(sint a[],int b[],int s,int n)
{
int i=0;
for(i=0;i2*s;i=i+s*2)
{
merge(a,b,i,i+s,i+2*s);
}
if(ielse
{
for(int j=i;jint a[],int b[],int left,int middle,int right)
{
int i=left;
int j=middle;
int k=left;
while((iright))
{
if(a[i]else
{
b[k]=a[j];
k++;
j++;
}
}
if(ifor(int p=i;pelse
{
for(int q=j;q<right;q++)
b[k++]=a[q];
}
}
快速排序算法是基于分治策略的另一种排序算法。其基本思想是,对于输入的子数组a[p:r],按以下三个步骤进行排序。
1.分解(divide):以a[p]为基准元素将a[p:r]划分为三段a[p:q-1],a[q]和a[q+1:r],使得a[p:q-1]中的任何原色小于等于a[q],a[q+1]中任何元素大于等于a[q]。下标q在划分过程中确定。
2.递归求解(conquer):通过递归调用快速排序算法,分别对a[p:q-1]和a[q+1:r]进行排序。
3.合并(merge):由于对a[p:q-1]和a[q+1:r]的排序是就地进行的,所以在a[p:q-1]和a[q+1:r]都已排好的序后不需要执行任何计算,a[p:r]就已经排好序。
基于此思想,可以实现快速排序算法如下:
void Algorithm::qSort(int a[],int left,int right)
{
if(left<right)
{
int middle=partition(a,left,right);
qSort(a,left,middle-1);
qSort(a,middle+1,right);
}
}
int Algorithm::partition(int a[],int left,int right)
{
int first=left+1;
int last=right;
int number=a[left];
int i=0;
while(true)
{
while(a[first]right)
{
first++;
}
while(a[last]>number)
{
last--;
}
if(first>=last)
{
break;
}
else
{
int temp=0;
temp=a[last];
a[last]=a[first];
a[first]=temp;
}
}
a[left]=a[last];
a[last]=number;
return last;
}
2017年12月26日21时16分Rao