开始学习算法导论。以前学数据结构时写过排序的算法,很长时间不用全忘了,今天重新开始学习。
看到归并排序,发现可以稍微改进一下。原算法归并时,把左右两个数组都复制一份,然后归并。而实际上,只需复制两个数组其中的一个就够了,这样可以把复制数组的时间减小一半。
对于原算法,假设复制出来的两个数组是 L 和 R ,归并时每次需要把L和R中的全部元素取出来算法才能结束。
而只复制左边数组(保存到L)时,直接使用右边数组,不另外保存,这时 ,只要L中元素全被取出了,算法就可以结束了。
在最好情况下,可以把插入元素的时间减少一半。
代码
#include <iostream>
#include <ctime>
using namespace std;
# define MAX 20//对[a,m)和[m,b)归并
void merge (int *a, int *m,int *b)
{
static int que[(MAX+1)/2];
int *p=a;
int *q=que;
//把[a,m) 之间的内容备份到que中。
while (p!=m)
*q++=*p++;
int *q_end=q;
q=que;
//对[q,q_end)和 [m,b)两段元素归并
while (m!=b && q!=q_end)
{
if (*m<*q)
*a++ = *m++;
else
*a++ = *q++;
}
while (q!=q_end) //如果que中仍有元素,则插入到原数组中。
*a++ = *q++;
}
void merge_sort (int *a, int *b)
{
if (b-a>1)
{
int *m=a+(b-a+1)/2;
merge_sort(a,m);
merge_sort(m,b);
merge(a,m,b);
}
}
int main()
{
int a[MAX];
srand((int)time(NULL));
for (int i=0;i<MAX ;i++)
{
a[i]=rand()%20;
}
cout<<"排序前:"<<endl;
for (int i=0;i<MAX ;i++)
{
cout<<a[i]<<'\t';
}
merge_sort (a, a+MAX);
cout<<"排序后:"<<endl;
for (int i=0;i<MAX ;i++)
{
cout<<a[i]<<'\t';
}
cout<<endl;
}