算法学习-归并排序和二分查找
一:归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
算法步骤:
1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4. 重复步骤3直到某一指针达到序列尾
5. 将另一序列剩下的所有元素直接复制到合并序列尾
根据对数据结构书上此算法的理解,编写了以下归并算法的递归实现:
#include "iostream.h"
void merge(int a[],int b[],int i,int m,int n)
{
for(int j=m+1,k=i;i<=m&&j<=n;++k)
{
if(a[i]<=a[j])b[k]=a[i++]; //a中按顺序归并
else b[k]=a[j++];
}
if(i<=m)
{for(;i<=m;++k) //前半区多余的部分直接赋值
{
b[k]=a[i++];
}
}
if(j<=n)
{for(;j<=n;++k) //后半区多余的部分直接赋值
{
b[k]=a[j++];
}
}
}
void msort(int a[],int b[],int s,int t)
{
int tr[8]; //中间变量,存储有序序列
if(s==t)b[s]=a[s];
else
{
int m=(s+t)/2; //均分
msort(a,tr,s,m); //前半区归并为有序存储到tr中
msort(a,tr,m+1,t); //后半区归并为有序存储到tr中
merge(tr,b,s,m,t); //两个有序序列归并到b中
//注意此处的tr位置,以及数据是如何传递和修改的
//调试此处花费了大量时间,还需仔细理解
}
}
void main()
{
int a[]={49,38,65,97,76,13,27};
int b[8];
msort(a,b,0,7);
for(int q=0;q<7;q++)
{
cout<<b[q]<<endl;
}
}
二分查找是在一个有序的数组中查找的算法,通过二分查找可以快速的缩小范围;
算法步骤:
1. 申明三个变量,指示待查找区域的起点,中点,末点
2. 将数组的中间项与T进行比较,如果T比数组的中间项要小,则到数组的前半部分继续查找,反之,则到数组的后半部分继续查找。
3.如果找到则返回,否则重复2的操作,最终就会在数组中找到T,或者确定原以为T所在的范围实际为空。
以下是自己实现的二分查找算法:
#include "iostream.h"
int binarysearch(int a[],int n,int value)
{
int left=0;
int right=n-1;
while(left<=right) //注意等号,当查询为最后一个元素时需要用到等号
{
int middle=left+((right-left)>>1); //位移运算防溢出(借鉴)
//理解是(left+right)/2,会超过int型范围
if(value<a[middle])
right=middle-1; //在前半区
else if(value>a[middle])
left=middle+1; //在后半区
else
return middle;
}
return -1; //没有找到
}
void main()
{
int a[10]={3,12,24,37,45,53,61,78,90,100};
int m=binarysearch(a,10,100);
cout<<m<<endl;
}