按照书上的最优快速排序代码,写了两份简单的。驱动程序读取数据规模n,随机数填充一个长度为n的数组,从小到大排序,并输出排序时间。

@ Athlon 64 X2 5200+ 2.75GHz    /    2x2GB DDR2 800

@ Archlinux —- 2.6.37-pf x86-64 内核

GCC 4.5.2:gcc source.c -O3 -std=c99

FPC 2.4.2:fpc source.pas -O3

C99实现(修改COMP改变排序顺序; 用标准库qsort比较时间):

#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/time.h>

// 调试开关
//#define DEBUGPRINT

/* 交换变量的宏函数 */
#define SWAP(X,Y) {temp=(X);(X)=(Y);(Y)=temp;}
/* 获取时间差的宏函数 */
#define TIMEDIFF(X,Y) (1000000*((Y).tv_sec-(X).tv_sec)+(Y).tv_usec-(X).tv_usec)

/* 用于自编快排的比较函数 */
extern inline int COMP (const int x, const int y)
{
	return x > y ? 1 :
			(x < y ? -1 : 0);
}

/* 用于标准qsort()的比较函数 */
int COMP2 (const void *x, const void *y)
{
	return *(int*)x - *(int*)y;
}

/* 自编快排 --- 快速排序部分 */
void xquicksort (int *pL, int *pR)
{
	ptrdiff_t diff;
	int mid, temp, *pi, *pj, *pmid, ppivot;

	while (( diff = pR - pL ) >= 36 )
	//36可修改为大于3的任何数
	//越大快排作用越小,同时插排作用越大
	{
		mid = rand() % (diff-2) + 1;
		pmid = pL + mid;

		if (COMP(*pL, *pmid)>0)
			SWAP(*pL, *pmid);
		if (COMP(*pL, *pR)>0)
			SWAP(*pL, *pR);
		if (COMP(*pmid, *pR)>0)
			SWAP(*pmid, *pR);

		SWAP(*pmid, *(pR-1));

		pi = pL;
		pj = pR - 1;
		ppivot = *pj;
		while (1)
		{
			while (COMP(*++pi, ppivot) < 0)
				continue;
			while (COMP(*--pj, ppivot) > 0)
				continue;

			if (pi>=pj)
				break;
			else
				SWAP(*pi, *pj);
		}

		*(pR - 1) = *pi;
		*pi = ppivot;

		if (pi - pL > pR - pi)
		{
			xquicksort(pi+1, pR);
			pR = pi - 1;
		}
		else
		{
			xquicksort(pL, pi-1);
			pL = pi + 1;
		}
	}
}

/* 自编快排 --- 插入排序部分 */
void InsSort (int *arr, const int len)
{
	int i, j, temp;
	for (i = 1;  i < len;  i++)
	{
		temp = arr[i];
		for (j = i - 1;  j >= 0;  j--)
			if (COMP(arr[j], temp) > 0)
				arr[j+1] = arr[j];
			else
				break;

		arr[j+1] = temp;
	}
}

/* 自编快排 --- 用户接口部分 */
void QSort (int *arr, const int len)
{
	xquicksort(arr, arr+len-1);
	InsSort(arr, len);
}

int main (void)
{
	int n, *arr, *arr2, i;
	struct timeval stime, etime;

	printf("数据规模: ");
	scanf("%d", &n);

	arr = malloc(n * sizeof(int));
	arr2 = malloc(n * sizeof(int));
	srand((int)arr);

	puts("数组填充中...");
	for (i = 0;  i < n;  i++)
	{
		arr2[i] = arr[i] = rand();
#ifdef DEBUGPRINT
		printf("%d ", arr[i]);
#endif
	}

	puts("\n开始使用自编函数排序...");
	gettimeofday(&stime, NULL);
	QSort(arr, n);
	gettimeofday(&etime, NULL);
	printf("排序用时: %.3f ms\n", (float)TIMEDIFF(stime, etime) / 1000.0);

	puts("\n开始使用标准库函数排序...");
	gettimeofday(&stime, NULL);
	qsort(arr2, n, sizeof(int), COMP2);
	gettimeofday(&etime, NULL);
	printf("排序用时: %.3f ms\n", (float)TIMEDIFF(stime, etime) / 1000.0);

#ifdef DEBUGPRINT
	bool wrong = false;
	puts("排序后数组:");
	for (i = 0;  i < n-1;  i++)
	{
		if (arr[i] != arr2[i])
			wrong = true;
		printf("%d ", arr[i]);
	}
	puts(wrong ? "\n算法错误" : "\n正常结束");
#endif

	return 0;
}

Pascal实现(修改所有comp注释行,反转不等号,即可调整排序顺序; 用FP示例快排比对时间):

program QuickSort_im;

uses
	dos;

var
	n, i, stime, etime : longint;
	wrong : boolean;
	arr, arr2 : array of longint;

(*
 * < gettimeofday_hs: 获取时间 >
 * 返回值: 以0.01秒为单位的当日时间
 * 本程序中用于统计排序用时。
 *)
function gettimeofday_hs : longint;
	var
		hour, minute, second, sec100 : word;
	begin
		gettime(hour, minute, second, sec100);
		exit( hour*360000 + minute*6000 + second*100 + sec100 );
	end;

// ------------ 快速排序所需函数 BEGIN ------------ //
(*
 * < swap: 交换变量 >
 * swap (变量a, 变量b)
 *)
procedure swap (var a, b: longint);
	var
		temp: longint;
	begin
		temp := a;
		a := b;
		b := temp;
	end;

(*
 * < inssort: 插入排序 >
 * inssort (待排序数组, 排序区域下界, 排序区域上界)
 * 本程序中用于快排后期处理。
 *)
procedure inssort (var a: array of longint; const down, up: longint);
	var
		i, j, add, temp : longint;
	begin
		for i := down+1 to up do
		begin
			temp := a[i];

			add := down;
			for j := i-1 downto down do
				if a[j] > temp then //COMP
					arr[j+1] := arr[j]
				else
				begin
					add := j+1;
					break;
				end;

			arr[add] := temp;
		end;
	end; // inssort END

(*
 * < qsort: 自己写的快速排序 >
 * qsort (待排序数组, 排序区域下界, 排序区域上界)
 * 按照书上的方法,优化过的快排,从C代码移植。
 *)
procedure qsort (var a: array of longint;  const down, up: longint);

	procedure xquicksort (l, r: longint);
		var
			diff, i, j, pivot: longint;
		begin
			diff := r - l;

			while diff >= 24 do
			//24可修改为大于3的任何数
			//越大快排作用越小,同时插排作用越大
			begin
				i := random(diff-2) + 1 + l;
				if a[l] > a[i] then //COMP
					swap(a[l], a[i]);
				if a[l] > a[r] then //COMP
					swap(a[l], a[r]);
				if a[i] > a[r] then //COMP
					swap(a[i], a[r]);
				swap(a[i], a[r-1]);

				i := l;
				j := r-1;
				pivot := a[j];
				repeat
					repeat inc(i); until a[i] >= pivot; //COMP
					repeat dec(j); until a[j] <= pivot; //COMP

					if i>=j then
						break
					else
						swap(a[i], a[j]);
				until false;

				a[r-1] := a[i];
				a[i] := pivot;

				if i-l > r-i then
				begin
					xquicksort(i+1, r);
					r := i-1;
				end
				else
				begin
					xquicksort(l, i-1);
					l := i + 1;
				end;

				diff := r - l;
			end;
		end; // qsort->xquicksort END

	begin
		xquicksort(down, up);
		inssort(arr, down, up);
	end; // qsort END

(*
 * < qsort_fp: FreePascal 快速排序示例 >
 * qsort_fp (待排序数组, 排序区域下界, 排序区域上界)
 * FP安装路径/demo/text/qsort.pp 快速排序示例。
 *)

procedure qsort_fp (var a: array of longint;  const down, up: longint);
	procedure sort(l,r: longint);
		var
			i,j,x,y: longint;
		begin
			i:=l;
			j:=r;
			x:=a[(l+r) div 2];

			repeat
				while a[i]<x do inc(i);
				while x<a[j] do dec(j);

          			if i<=j then
				begin
					y:=a[i];
					a[i]:=a[j];
					a[j]:=y;
					inc(i);
					dec(j);
				end;
			until i>j;

			if l<j then sort(l,j);
			if i<r then sort(i,r);
		end; // qsort_fp->sort END

	begin
		sort(down, up);
	end; // qsort_fp END

// ------------ 快速排序所需函数 END ------------ //

begin
	write('数据规模: ');
	readln(n);	

	randomize;
	setlength(arr, n);
	setlength(arr2, n);
	writeln('数组填充中...');
	writeln;
	for i := 0 to n-1 do
	begin
		arr[i] := random(maxlongint);
		arr2[i] := arr[i];
	end;

	writeln('开始使用自编函数排序...');
	stime := gettimeofday_hs();
	qsort(arr, 0, n-1);
	etime := gettimeofday_hs();
	writeln('排序用时: ', (etime-stime)/100.0 :0:2, ' s');

	writeln;
	writeln('开始使用FreePascal示例函数排序...');
	stime := gettimeofday_hs();
	qsort_fp(arr2, 0, n-1);
	etime := gettimeofday_hs();
	writeln('排序用时: ', (etime-stime)/100.0 :0:2, ' s');

	// 检查排序结果
	wrong := false;
	for i := 0 to n-1 do
		if arr[i] <> arr2[i] then
			wrong := true;

	writeln;
	if wrong then
		writeln('算法错误.')
	else
		writeln('正常结束.');
	// 检查 END
end.

排序20000000个数的性能比较: C 实现:2.08 s C qsort():4.03 s Pascal 实现:3.36 s Pascal 示例:4.18 s