归并排序算法采用分治的策略:将原问题划分成n个规模较小的子问题,递归解决这些子问题,合并其结果就得到原问题的解。
将n个元素分成含n/2个元素的子序列,用递归对序列排序,当子序列的长度为1时递归结束,再和并子序列的结果。
题目:给出一个时间复杂度为nlgn的算法,使之能在给定一个由n个元素构成的集合s和一个元素x,判断出s中是否存在两个其和等于x的元素。
// merge.cpp : 定义控制台应用程序的入口点。
//
//算法思想:并归排序数组S,根据x1=x-x2二分查找确定是否存在满足条件的数x1。
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <malloc.h>
void Merge(int R[],int low,int mid,int high);
void MergePass(int R[],int length,int n);
void MergeSort(int R[],int n); //二路归并排序算法
int search(int A[],int n,int k);//二分查找,复杂度为lgn
int main()
{
int i,k,length;
int arry[10];
for (i=0;i<10;i++)
{
arry[i]=rand()%100;//产生伪随机数
}
length=sizeof(arry)/sizeof(arry[0]);
cout<<"数组归并排序前: "; //输出初始关键字序列
for (k=0;k<length;k++)
cout<<arry[k]<<" ";
printf("\n");
MergeSort(arry,length);
cout<<"数组归并排序后: "; //输出初始关键字序列
for (k=0;k<length;k++)
cout<<arry[k]<<" ";
cout<<"\n规则:输入一个数,使它是数组中两个数之和。"<<endl;
int num;
int x;
while (1)//循环输入有利于测试所有情况
{ int flag=0;
cout<<"\n输入一个整数:";
cin>>num;
for (k=0;k<length;k++)
{
x=num-arry[k];//要查找的数是x
if ((i=search(arry,length,x))!=-1)//返回i表示找到的数的位置
{
if (i!=k)//确保查找的不是自身。防止“2-1=1”这种情况呗认定为找到
{
flag=1;
break;
}
}
}
if (flag==0)
{
cout<<"没找到符合条件的数。";
}
else
{
cout<<"找到符合条件的数:"<<num<<"="<<x<<"+"<<arry[k];
}
}
getchar();
return 0;
}
void Merge(int R[],int low,int mid,int high) //将两个有序数组R[low..mid]和R[mid+1..high]归并为一个有序数组R[low..high]中
{
int *R1;
int i=low,j=mid+1,k=0; //k是R1的下标,i、j分别为第1、2段的下标
R1=(int *)malloc((high-low+1)*sizeof(int)); //动态分配空间
while (i<=mid && j<=high) //在第1段和第2段均未扫描完时循环
if (R[i]<=R[j]) //将第1段中的记录放入R1中
{
R1[k]=R[i];
i++;
k++;
}
else //将第2段中的记录放入R1中
{
R1[k]=R[j];
j++;
k++;
}
while (i<=mid) //将第1段余下部分复制到R1
{
R1[k]=R[i];
i++;
k++;
}
while (j<=high) //将第2段余下部分复制到R1
{
R1[k]=R[j];
j++;
k++;
}
for (k=0,i=low;i<=high;k++,i++) //将R1复制回R中
{ R[i]=R1[k];}
}
void MergePass(int arry[],int leng,int length) //实现一趟归并
{
int i;
for (i=0;i+2*leng-1<length;i=i+2*leng) //归并length长的两相邻子数组
Merge(arry,i,i+leng-1,i+2*leng-1);
if (i+leng-1<length) //余下两个子数组,后者长度小于length
Merge(arry,i,i+leng-1,length-1); //归并这两个子数组
}
void MergeSort(int arry[],int length) //二路归并排序算法
{
int leng;
for (leng=1;leng<length;leng=2*leng)
{
MergePass(arry,leng,length);
}
}
int search(int arry[],int length,int checkNumer)//二分查找
{
int low=0,high=length-1,mid,count=0;
while(low<=high)
{
mid=(low+high)/2;
if(arry[mid]==checkNumer)
{
return mid;
break;
}
if(checkNumer<arry[mid])
{
high=mid-1;
}
else
{
low=mid+1;
}
}
return -1;//表示没有找到
}