《算法设计与分析基础》学习 --- 分治法
继续实现书上的算法,现在是分治法咯。很多基础的算法都是分治思想的,而分治这个思想也符合我们平时的思维方式,将问题简化为同个类型但是规模较小的问题,化大为小,通过解决众多小问题而最终实现解决大问题。
先解决下几个比较简单的基础问题,然后再另开两篇解决“凸包问题”和“最近对问题”。
一、合并排序
// 将有序的data[i,m],data[m+1,n]合并到data[i,n]
// temp为临时空间
void merge(int data[],int temp[],int i,int m,int n)
{
int pos=i;
int j,k;
for(j=m+1,k=i;i<=m&&j<=n;k++)
{
if(data[i]<data[j])
temp[k]=data[i++];
else
temp[k]=data[j++];
}
//归并剩余之一
while(i<=m)
temp[k++]=data[i++];
while(j<=n)
temp[k++]=data[j++];
//重新复制到原数组
for(k--;k>=pos;k--)
data[k]=temp[k];
}
//归并排序data[i,j],还需提供额外空间temp[i,j]
void msort(int data[],int temp[],int i,int j)
{
if(i<j)
{
int mid = (i+j)/2;
//分治归并,temp为临时空间
msort(data,temp,i,mid);
msort(data,temp,mid+1,j);
merge(data,temp,i,mid,j);
}
}
//对数组data[n]进行归并排序
void MergeSort(int data[],int n)
{
int * temp = new int[n];
msort(data,temp,0,n-1);
delete [] temp;
}
合并排序虽然可以达到O(nlogn)的时间复杂度,但是它确需要线性的额外空间。对于内部排序来说,实在是找不到使用二路归并排序的理由;但是在外部排序,使用多路归并排序就应该能解决一下实际问题。
二、快速排序
算是非常好的内部排序算法了,首先编码够简单,效率也非常高:最好的情况是 O(nlogn);根据书上的分析,其平均效率也只需要O(1.38logn);就是最差效率为O(n*n)这个缺点,但是一般比较少遇到这种情况,也有其它的解决方案。
//快排中的分割算法
//对 data[low,high]进行分割、返回枢轴
int Partition(int data[],int low,int high)
{
int temp = data[low];
while(low < high)
{
while(low < high && data[high] >= temp)
high--;
data[low] = data[high];
while(low <high && data[low] <= temp)
low++;
data[high] = data[low];
}
data[low]=temp;
return low;
}
//快排中的递归排序
//对data[low,high]进行快排
void QSort(int data[],int low,int high)
{
if(low < high)
{
int pivotloc = Partition(data,low,high);
QSort(data,low,pivotloc-1);
QSort(data,pivotloc+1,high);
}
}
三、二分查找法
对于查找有序数组,二分查找算是非常好了。效率高:O(logn),代码实现起来又非常简单:
//二分查找算法
//在非递减数组data[low,high]查找key,返回位置
int BinarySearch(int data[],int low,int high,int key)
{
while(low < high)
{
int mid = (low+high)/2;
if(data[mid] > key)
high = mid -1;
else if(data[mid] < key)
low = mid + 1;
else
return mid;
}
return -1;
}
嗯嗯,非常简单的几个算法,分治法。接下来写一个比较复杂的算法:凸包!
By:洪庚伟