快速排序(C语言)

思想

分治法

过程

从数列中取出一个数作为基准数,一般取第一个数
将大于等于这个数的数全放在他的右边,小于等于它的数全放在他的左边
再对左右区间重复第二步,直到各区间只有一个数。

代码实现(C语言)

快排的核心思想是partition,对于实现partition有两种方法:交换法和“挖坑填数法”(后者执行的次数少)
快速排序可以用递归和非递归的形式实现。

递归实现

#include<stdio.h>
#define DEBUG

/* //交换法实现的quicksort
void swap(int *a, int *b)
{
	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
}

void quicksort(int arr[], int left, int right)
{
	if (left >= right)//注意要写这个递归跳出的条件
		return;
	int i = left;
	int j = right;
	int key = arr[left];
	while (i < j){
		while(i < j && arr[j] >= key)
			j--;
		while(i < j && arr[i] <= key)
			i++;
		if (i < j)
			swap(&arr[i], &arr[j]);
	}
	swap(&arr[left], &arr[i]);
	quicksort(arr, left, i-1);
	quicksort(arr, i+1, right);
}
 */

//挖坑填数法实现的quicksort
void quicksort(int arr[], int left, int right)
{
	if (left >= right)//注意递归跳出的条件
		return;
	int i = left;
	int j = right;
	int key = arr[left];
	while (i < j){
		while (arr[j] >= key && i < j)
			j--;
		arr[i] = arr[j];
		while (arr[i] <= key && i < j)
			i++;
		arr[j] = arr[i];
	}
	arr[i] = key;
	#ifdef DEBUG
	int k;
	for (k = left; k <=right; k++)
		printf("arr[%d]=%d ", k, arr[k]);
	printf("\n");
	#endif
	quicksort(arr, left, i-1);
	quicksort(arr, i+1, right);
	
} 

int main()
{
	int arr[100]; //输入序列所存放的数组
	int len = 0;
	char c;//用于对回车键进行检测
	printf("请输入任意个数,按回车键结束\n");
	printf("Input:\n");
	while(1) {
		scanf("%d", &arr[len++]);
		c = getchar();
		if (c == '\n')
			break;		
	}
	quicksort(arr, 0, len-1);
	printf("quicksort:\n");
	int i;
	for (i=0; i<len; i++)
		printf("%d ", arr[i]);
	printf("\n");
	return 0;	
}

非递归实现

#include<stdio.h>

//分隔 用"挖坑填数法"实现
int partition(int arr[], int left, int right)
{
	int i = left;
	int j = right;
	int key = arr[left];
	while (i < j){
		while (arr[j] >= key && i < j)
			j--;
		arr[i] = arr[j];
		while (arr[i] <= key && i < j)
			i++;
		arr[j] = arr[i];
	}
	arr[i] = key;
	int k;
	for (k = left; k <=right; k++)
		printf("arr[%d]=%d ", k, arr[k]);
	printf("\n");
	return i;
}

//非递归实现快排
void quicksort(int arr[], int len)
{
	int left = 0;//左指针
	int right = len - 1;//右指针
	int b[1000] = {0};//用于存放左右索引
	int n = 0;//记录当前b中的索引数目
	int index;
	b[n++] = left;//该思路来自于用C++用栈来实现非递归快排,c语言中没有栈这种数据结构
	b[n++] = right;
	while(n != 0){
		right = b[--n];
		left = b[--n];
		index = partition(arr, left, right);
		printf("index = %d\n", index);
		if (index - 1 > left){
			b[n++] = left;
			b[n++] = index -1;
		}
		if (index + 1 < right){
			b[n++] = index + 1;
			b[n++] = right;
		}
	}
}

int main()
{
	int arr[100]; //输入序列所存放的数组
	int len = 0;
	char c;//用于对回车键进行检测
	printf("请输入任意个数,按回车键结束\n");
	printf("Input:\n");
	while(1) {
		scanf("%d", &arr[len++]);
		c = getchar();
		if (c == '\n')
			break;		
	}
	quicksort(arr, len);
	printf("quicksort:\n");
	int i;
	for (i=0; i<len; i++)
		printf("%d ", arr[i]);
	printf("\n");
	return 0;	
}

性能分析

时间复杂度

快排的时间性能取决于递归的深度
最优情况,排序n个关键字,递归树深度为 l o g 2 n log_2n log2n

空间复杂度

稳定性

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值