快速排序

快速排序

一、快排实现

快排的核心是对split()方法的理解。

split()的作用就是:将数组中比枢纽元素小的的元素排在枢纽元素前面,比枢纽元素大的元素排在枢纽元素后面。

实现split()方法后,下面就是实现快速排序了。

首先就是对递归基础条件的处理,让递归有一个出口。然后将整个数组进行split(),这样就把整个数组分割成了两部分,前半部分比枢纽元素小,后半部分比枢纽元素大,采取分而治之的思想,对两部分数组分别进行快速排序。

最后形成整体有序。

以下是实现过程,写法上比较繁琐,没有为代码好看牺牲必要的思维步骤。

#include <stdio.h>

void my_print(char*, int*, int);
void quick_sort(int*, int, int);
int split(int*, int, int);

int main()
{
	int n = 0;
	int arr[10] = {12, 2, 45, 22, 13, 1, 3, 5, 16, 20}; 
	my_print("排序前", arr, 10);
	
	quick_sort(arr, 0, 9);
	my_print("排序后", arr, 10);
} 

/**
 * 自定义输出, 忽略这个方法 
 */
void my_print(char* msg, int* arr, int length)
{
	printf("%s\t", msg);
	for (int i = 0; i < length; i ++)
	{
		printf("%d", arr[i]);
		if (length - i - 1)
		{
			printf(", ");
		} else {
			printf("\n");
		}
	}
} 

/**
 * 快速排序
 */
void quick_sort(int* arr, int l, int r)
{
	if (l >= r)
	{
		return; 
	}
	
	// 整个数组进行split,
	int in = split(arr, l, r);
	// 分而治之 
	quick_sort(arr, l, in - 1);
	quick_sort(arr, in + 1, r);	
}

/**
 *  使key左边元素都比key小, key右边的元素都比key大 
 *	参数:	 
 *		arr : 数组
 *		l	: 左边界
 *		r	: 有边界
 *	返回值: 枢纽元素的位置
 *	----------------------------------------
 *	l      ----  左边界
 *  r      ----  右边界 
 *  i      ----  指向当前正在遍历的元素
 *  (l, k] ----  比枢纽元素小的元素
 *  (k, i) ----  比枢纽元素大的元素 
 *  [i, r] ----  还未或正在遍历的元素  
 */
int split(int* arr, int l, int r)
{
	int k = l, i = l + 1;   //初始化
	int key = arr[l];		//左边界元素作为枢纽元素	
	while (i <= r)
	{
		if (arr[i] <= key)
		{
			k ++;				// 找到一个比key小的元素, 前进一步 
			if (i == k)		   //没有遇到key < arr[i]会一直保持 i == k	
			{
				i ++;
			} else {
				int temp = arr[k];		//交换 
				arr[k] = arr[i];
				arr[i] = temp;
			}
		} else {			 // 当前元素比key大, 继续 
			i ++;
		}
	}
	// 循环过后
	//  (l, k] ----  比枢纽元素小的元素
	//  (k, i] ----  比枢纽元素大的元素 
	int temp = arr[l];
	arr[l] = arr[k];
	arr[k] = temp;
		
	return k;			// 返回枢纽元素所在的位置 
}
二、JAVA中的快排

JAVA中快排主要是在split()方法上做了文章,普通的split()是选取1个枢纽元素,然后将数组分割成两部分;JAVA中的split()是一次选取2个枢纽元素,将数组分割成了三部分,让人意外的性能竟然比原先要快很多。果然一个小小的想法带来的改变是巨大的!!!!不知道有没有一位狠人在split()上一次选取3个或4个枢纽元素,估计性能还会提升。。。。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值