【发布时间】:2015-06-25 17:56:53
【问题描述】:
我目前正在进行实证研究,以评估快速排序和归并排序算法的运行时复杂性。为此,我运行了一个随机数生成器,它将我指定的任意数量的数字存储在二进制文件中。这些数字的范围是 1-1,000,000。然后我从 100,000 个数字开始对每个算法进行测试,每次递增 50,000,直到最后一次运行时对 1,000,000 个数字进行排序。所以每个测试 20 次。我已经成功地完成了每个算法,但我的结果有点令人费解。这是显示我的结果的图表。
我知道快速排序的最坏情况是 O(n2) 时间,但通常是 O(n·lg(n)) 时间。合并排序有 Θ(n·lg(n)) 时间。
我还想指出,当我启动计时器时,我只是使用了 time.h 中的 clock(),并计算了经过的时间。在调用排序函数之前,我启动了我的计时器一行代码。
我不明白的是,与快速排序相比,我的图表如何显示合并排序的时间总是加倍,而对数字进行排序的时间却是三倍。
我唯一的想法是,对于我的合并排序算法,每次我将数组分成两半时,我都会使用 malloc 为每一半创建一个新的整数数组。当然,这意味着考虑到我正在排序的数字大小,会对 malloc 进行大量调用。
int* mergeSort(int* nums, int size){
int* left;
int* right;
int middle = size/2;
if(size <= 1)
return nums;
split(nums, size, &left, &right, middle);
//I dont understand why the code below wouldnt work in place of the split()
//when i run it, in main, nothing gets printed out. I guess i lose my pointer to the beginning of my array.
//left = nums;
//right = nums+middle;
left = mergeSort(left, middle);
right = mergeSort(right, size - middle);
merge(nums,left,right,middle,size - middle);
free(left);
free(right);
return nums;
}
void split(int* nums, int size, int** left, int** right, int middle){
int *lft = (int*) malloc ((sizeof(int) * middle));
int *rght = (int*) malloc ((sizeof(int) * size - middle));
int mid = middle;
int upMid = size - middle;
int i;
for(i=0; i < mid; i++)
lft[i] = nums[i];
for(i=0; i < upMid; i++)
rght[i] = nums[i+middle];
*left = lft;
*right = rght;
}
void merge(int* num, int* left, int* right, int sizeLeft, int sizeRight){
int i,j,k,n;
i=j=k=0;
n=sizeLeft + sizeRight;
while(k < n){
if(i< sizeLeft){
if(j<sizeRight){
insert(num,left,right,&i,&j,&k);
}
else{
append(num, left, sizeLeft, &i, &k);
}
}
else{
append(num,right,sizeRight,&j,&k);
}
}
}
void insert(int* num, int* left, int* right, int* i, int* j, int* k){
/*int i,j,k,n;*/
if(left[*i]<right[*j]){
num[*k] = left[*i];
(*i)++;
}
else{
num[*k] = right[*j];
(*j)++;
}
(*k)++;
}
void append(int* num, int* half, int sizeHalf, int* i, int* k){
while(*i < sizeHalf){
num[*k]= half[*i];
(*i)++; (*k)++;
}
}
对于我的这个问题的任何反馈,以及关于可能使我的归并排序功能更高效的任何建议,我将不胜感激。谢谢!!
【问题讨论】:
-
查看有关合并排序的维基百科文章的Variants 部分,以获取有关减少空间量或复制的方法的建议。如果空间不是问题,一种解决方案是预先分配一个与 ORIGINAL 长度相同的 NEW 数组,然后交替合并(并附加)来自 ORIGINAL->NEW 或 NEW->ORIGINAL 的子列表。
-
啊,谢谢。我想我可能会改变的是,而不是每次都分配新的数组。我将把我的 *left 和 *right 分配给 nums 数组中每个期望值的地址。并且只需处理缩短数组视图的数字即可。希望我能让它正常工作
标签: objective-c time-complexity quicksort mergesort