快速排序讲解及代码实现

基本思想

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

代码实现

第一种方法:左右指针法
1.begin从最左边开始,end从最右边开始,用三数取中法设置key
2.begin向右找大于key的数据,end向右找小于key的数据,找到之后进行交换
3.相遇之后,因为begin先走,所以相遇点一定比key大,key跟相遇点交换。
在这里插入图片描述

int GetMid(int* array, int left, int right)                //三数取中法
{
	int mid = left + ((right - left) >> 1);
	if (array[left] < array[mid])//左比中小
	{
		if (array[mid] < array[right])
			return mid;//mid是中位数 
		else if (array[left] > array[right])
			return right;
		else
			return left;
	}
	else
	{
		if (array[mid] > array[right])
			return mid;
		else if (array[left] > array[right])
			return right;
		else
			return left;
	}
}
int PartSort1(int* array, int left, int right) //左右指针法
{
    assert(array);
    int begin = left;
    int end = right;
    int mid = GetMid(array, left, right);
    Swap(&array[mid], &array[right]);
    int key = array[right];
    while (begin < end)
    {
        while (array[begin] <= key && begin < end)//begin找大
        {
        begin++;
        }
        while (array[end] >= key && begin < end)//end找小
        {
        end--;
        }
        if (begin < end)
        {
        Swap(&array[begin], &array[end]);
        } //begin end 相遇后,把key放在相遇位置上
    }
    Swap(&array[begin], &array[right]);//begin end 相遇后,把key放在相遇位置上
    return begin;
}

在这里插入图片描述
第二种方法:挖坑法
1.三数取中法选取适中大小的数作为key,跟最右边数据进行交换。
2.key作为坑,最左数据为begin,最右数据为end,begin找大,end找小。
3.begin,end,找到数据之后跟坑key交换,相遇之后停止。
这种方法原理上类似于左右指针法,参考上面的图解。

int PartSort2(int* array, int left, int right) //挖坑法
{
    assert(array);
    int begin = left;
    int end = right;
    int key = array[right];
    while (begin < end)
    {
        while (array[begin] <= key && begin < end)
        {
        begin++;
        }
        array[end] = array[begin]; //坑变为begin
        while (array[end] >= key && begin < end)
        {
        end--;
        }
        array[begin] = array[end]; // 坑变为end
    }
    array[begin] = key; //填坑
    return begin;
}

在这里插入图片描述
第三种方法:前后指针法
1.定义变量cur指向序列的开头,定义变量pre指向cur的前一个位置。
2.当array[cur] < key时,cur和pre同时往后走,如果array[cur]>key,cur往后走,pre留在大于key的数值前一个位置。
3.当array[cur]再次 < key时,交换array[cur]和array[pre]。
在没找到大于key值前,prev永远紧跟cur,遇到大的两者之间机会拉开差距,中间差的肯定是连续的大于key的值,当再次遇到小于key的值时,交换两个下标对应的值就好了。
在这里插入图片描述

int PartSort3(int* array, int left, int right)    //前后指针
{
	assert(array);
	int prev = left - 1;
	int cur = left;
	int key = array[right];
	while (cur < right)
	{
		if (array[cur] < key && ++prev != cur)
		{
			Swap(&array[cur], &array[prev]);
		}
		++cur;
	}
	Swap(&array[++prev], &array[right]);
	return prev;
}

在这里插入图片描述
以下为测试代码:

void QuickSort(int* array, int left, int right)	       //快速排序
{
	assert(array);
	if (left >= right)
		return;
	//int div = PartSort1(array, left, right);
	//int div = PartSort2(array, left, right);
	int div = PartSort3(array, left, right);
	printf("div:%d\n", div);
	//left div-1
	QuickSort(array, left, div - 1);
	//div+1  right
	QuickSort(array, div + 1, right);
}

时间复杂度及稳定性

平均时间复杂度: O(nlogn)
最坏时间复杂度:O(n2) (有序的情况)
稳定性:不稳定

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值