【发布时间】:2011-06-22 13:48:02
【问题描述】:
我将为学生实现一个玩具磁带“大型机”,展示“快速排序”类函数的快速性(递归与否,并不重要,因为硬件速度慢,以及众所周知的堆栈反转技术) 与“冒泡排序”函数类相比。所以,虽然我很清楚硬件实现和控制器,但我猜快速排序功能在序列、顺序和比较距离方面比其他功能快得多(从中间倒带比从非常最后,由于不同的倒带速度)。
不幸的是,这不是真的;与“快速排序”函数相比,这个简单的“冒泡”代码在比较距离、方向以及比较和写入的数量方面有了很大的改进。
所以我有3个问题:
- 我在实现快速排序功能时是否有错误?
- 我在实现 bubblesoft 函数时是否有错误?
- 如果不是,为什么“冒泡排序”函数(比较和写入操作)比“快速排序”函数快得多?
我已经有了“快速排序”功能:
void quicksort(float *a, long l, long r, const compare_function& compare)
{
long i=l, j=r, temp, m=(l+r)/2;
if (l == r) return;
if (l == r-1)
{
if (compare(a, l, r))
{
swap(a, l, r);
}
return;
}
if (l < r-1)
{
while (1)
{
i = l;
j = r;
while (i < m && !compare(a, i, m)) i++;
while (m < j && !compare(a, m, j)) j--;
if (i >= j)
{
break;
}
swap(a, i, j);
}
if (l < m) quicksort(a, l, m, compare);
if (m < r) quicksort(a, m, r, compare);
return;
}
}
我有自己的“冒泡排序”功能实现:
void bubblesort(float *a, long l, long r, const compare_function& compare)
{
long i, j, k;
if (l == r)
{
return;
}
if (l == r-1)
{
if (compare(a, l, r))
{
swap(a, l, r);
}
return;
}
if (l < r-1)
{
while(l < r)
{
i = l;
j = l;
while (i < r)
{
i++;
if (!compare(a, j, i))
{
continue;
}
j = i;
}
if (l < j)
{
swap(a, l, j);
}
l++;
i = r;
k = r;
while(l < i)
{
i--;
if (!compare(a, i, k))
{
continue;
}
k = i;
}
if (k < r)
{
swap(a, k, r);
}
r--;
}
return;
}
}
我在测试示例代码中使用了这些排序函数,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
long swap_count;
long compare_count;
typedef long (*compare_function)(float *, long, long );
typedef void (*sort_function)(float *, long , long , const compare_function& );
void init(float *, long );
void print(float *, long );
void sort(float *, long, const sort_function& );
void swap(float *a, long l, long r);
long less(float *a, long l, long r);
long greater(float *a, long l, long r);
void bubblesort(float *, long , long , const compare_function& );
void quicksort(float *, long , long , const compare_function& );
void main()
{
int n;
printf("n=");
scanf("%d",&n);
printf("\r\n");
long i;
float *a = (float *)malloc(n*n*sizeof(float));
sort(a, n, &bubblesort);
print(a, n);
sort(a, n, &quicksort);
print(a, n);
free(a);
}
long less(float *a, long l, long r)
{
compare_count++;
return *(a+l) < *(a+r) ? 1 : 0;
}
long greater(float *a, long l, long r)
{
compare_count++;
return *(a+l) > *(a+r) ? 1 : 0;
}
void swap(float *a, long l, long r)
{
swap_count++;
float temp;
temp = *(a+l);
*(a+l) = *(a+r);
*(a+r) = temp;
}
float tg(float x)
{
return tan(x);
}
float ctg(float x)
{
return 1.0/tan(x);
}
void init(float *m,long n)
{
long i,j;
for (i = 0; i < n; i++)
{
for (j=0; j< n; j++)
{
m[i + j*n] = tg(0.2*(i+1)) + ctg(0.3*(j+1));
}
}
}
void print(float *m, long n)
{
long i, j;
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
printf(" %5.1f", m[i + j*n]);
}
printf("\r\n");
}
printf("\r\n");
}
void sort(float *a, long n, const sort_function& sort)
{
long i, sort_compare = 0, sort_swap = 0;
init(a,n);
for(i = 0; i < n*n; i+=n)
{
if (fmod (i / n, 2) == 0)
{
compare_count = 0;
swap_count = 0;
sort(a, i, i+n-1, &less);
if (swap_count == 0)
{
compare_count = 0;
sort(a, i, i+n-1, &greater);
}
sort_compare += compare_count;
sort_swap += swap_count;
}
}
printf("compare=%ld\r\n", sort_compare);
printf("swap=%ld\r\n", sort_swap);
printf("\r\n");
}
【问题讨论】:
-
注意:所有的复杂性都被赋予了一些“成本”函数。快速排序平均为 O(n log n),其中
n确定比较次数。这不是任意选择的,在“常规”计算的情况下,这是一个很好的成本指标。但是,在处理非常规设备(此处为磁带)时,根据磁带的“移动”来计算复杂性会更准确。我认为这是让学生思考什么是“复杂性”的好方法。 -
我发现实际上我的算法与交换平均的选择排序算法非常相似。它位于这里:sorting-algorithms.com/selection-sort,如果你有兴趣,你可以找到一个非常有趣的解释,在哪里使用特定的算法以及它们的特定优缺点。
标签: c performance algorithm quicksort bubble-sort