快速排序优化算法原理及C语言实现

经典快排

   快速排序(quicksort)的主要思想是分治,意为分而治之。其算法整体思路如下图

在这里插入图片描述
   以升序排序为例,个人认为经典的快速排序算法的主要思想为:在每次排序后,中轴数(pivot)位置前的数都小于中轴数,其位置后的数都大于中轴数。所以每轮快速排序的步骤可以分为:
   1、确认中轴数
   2、寻找中轴数应该出现的位置
   3、对中轴数前后的数分别进行快速排序

优化算法

   我们这次的优化主要针对中轴点的选取。
   我们知道,快速排序的中轴数的选取有多种方法,一般有三种选择方法:选数组的第一个数、选数组的最后一个数、选数组中间位置的数。但是由于原数组的无序性,每种选择方法的排序次数、交换次数都是不一样的,也就是说,对于不一样的数组,三种选择的表现不同,没有一种选择方法在每种数组中的表现都优于其他两种。
   因此,有人提出中轴点的选取时采取随机数的方法,随机选取数组中的任一数作为中轴点。这提高了算法的效率。
   我们介绍的这种算法在效率上比上一优化算法提高了14%。选择第一个(位置为 l)、中间(位置为 c)和最后一个元素(位置为 r)的中间值作为中轴数,并将这个数放到数组第一位。保证 l 位置的数是中轴数,c 位置的数为三者中最小的数,r 位置的数是最大的数。其他部分与经典快速排序基本相同。

例题

   您被要求编写一个程序,在升序的字符串数组(即ASCll代码)上执行快速排序。输出每步的结果,以换行符分割。您可以安全地假设所有字符串都是独立的,不包含空格,字符串的长度最多为100。
   您的程序应该从文件中读取输入,并将答案输出到另一个文件。第一个参数是输入文件名,第二个参数是输出文件名,您的程序名为“2.txt”

   Sample Input:
   4
   Apple Orange Banana Pear

   Sample Output:
   Banana Apple Orange Pear
   Apple Banana Orange Pear

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<ctype.h>

int compare(char *A, char *B) {
	return strcmp(A, B);
}

void swap(char **a, int x, int y) {
	char* temp;
	temp = a[x];
	a[x] = a[y];
	a[y] = temp;
}

/* after median3 */
/* a[l] is the pivot */
/* a[r] > a[c] */
int median3(char **a, int l, int r){
	int c = (l + r) / 2;
	if (compare(a[l],a[c])>0)
		swap(a, l, c);
	if (compare(a[l],a[r])>0)
		swap(a, l, r);
	if (compare(a[c],a[r])>0)
		swap(a, c, r);

	swap(a, c, l); // hide pivot in l
	return l; // return pivot
}



void my_qsort(char**a, int left, int right, int n, FILE *fout){
	int i, j, p; // handle simple cases
	if (left >= right) return;
	
	if (left + 1 == right){ // When there are only two numbers
		if (compare(a[left], a[right]) > 0) swap(a, left, right);
			return;
	}
	
	p = median3(a, left, right);	// When the number to be compared >= 3
	char* temp = a[p];
	i = left;
	j = right;
	while (1){
		while (i < right && compare(a[++i], temp) <= 0);
        while (j > 0 && compare(a[--j], temp) > 0);
        if (i < j)
		 swap(a, i, j);
        else
		 break;
    } // restore pivot
	swap(a, j, left);
	
	/* Output format */
	for (int i = 0; i < n-1; i++)
		fprintf(fout, "%s ", a[i]);
	fprintf(fout, "%s\n", a[n-1]);
	
	my_qsort(a, left, j - 1, n, fout);
	my_qsort(a, j + 1, right, n, fout);
}

int main(int argc, char *argv[]) {

	FILE *fin, *fout;
	int n;
	char **data;
	int i;

	fin = fopen(argv[1], "r");
	fout = fopen(argv[2], "w");

	fscanf(fin, "%d", &n);
	data = (char**) malloc(sizeof(char*)*n);
	printf("n = %d\n", n);
	for (i = 0; i < n; i++) {
		data[i] = (char*)malloc(sizeof(char)*100);
		memset(data[i], 0, sizeof(char)*100);
		fscanf(fin, "%s", data[i]);
	}

	for (i = 0; i < n-1; i++)
		printf("%s ", data[i]);
	printf("%s\n", data[n-1]);

	my_qsort(data, 0, n-1, n, fout);

	for (i = 0; i < n; i++) {
		fprintf(fout, "%s", data[i]);
		if (i != n-1) fprintf(fout, " ");
		else fprintf(fout, "\n");
		free(data[i]);
	}
	free(data);
	fclose(fin);
	fclose(fout);

	return 0;
}

   快速排序细节拉满,写程序的时候需要特别关注几个临界点。
   作为一种经典的算法,快速排序的优化还有很多。跳出选取中轴点这个优化方向,还有与插入排序结合等等优化方法,在此不一一赘述。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铖铖的花嫁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值