八大排序---快速排序

一.快速排序的步骤

第一步:将待排序数组的第一个位置标为基准数;
第二步:将待排序数组的第一个位置和最后一个位置放入left和right两个指针;
第三步:让right指针先移动,去找比基准数小的数,找到之后停止
第四步:让left指针往后移动,去找比当前基准数大的数,找到后停止
第五步:让当前left和right指针所指向的值进行交换,之后重复第3.4.5步
第六步:left和right相遇以后,让相遇位置的值和基准数进行交换
执行完这六步之后,基准数前面的都比基准数小,后面的都比基准数大
第七步:从相遇位置将数组拆分成左右两部分,重复1-6步,直到所有元素都变成单个之后,就排好了

二.图解

假设我们要对这样一组数进行快速排序:
我们第一步是将第一个数字:8设置为基准数;
第二步是将待排序数组的第一个位置和最后一个位置放入left指针和right指针;
第三步是让right指针向左移动,去寻找比基准数小的数字,明显,这里数字1比8小,因此在1处停止;
第四步让left指针向右移动,去寻找比基准数大的数字,找到数字9是第一个比8大的数字;
第五步:交换左右指针所指向的值;
交换之后重复第三,第四,第五步,直到两指针指向同一位置
right指针继续向左移动找下一个比基准数小的数字,找到数字4是第一个比基准数小的数字;
left指针继续向右移动找下一个比基准数大的数字,找到数字13是第一个比基准数字大的数字;
交换左右指针的值;
左右指针继续移动:right指针下一次指向6;left指针向右移动指向6之后两指针指向同一个位置;
 第六步:两指针相遇后,让相遇位置的值和和基准数进行互换;
 这样,整个数组被分成了两部分,左边部分是比基准数小的部分,右边部分是比基准数大的部分;基准数的位置就是最后排序完成之后该数字应该在的位置。
我们对拆成的两个数组,继续进行上面的操作:
 经过上述操作之后,数字6和数字13最终应该也会出现在正确的位置,会出更多的数组,循环到出现的数组大小都为1之后。这个数组就排好序了。

三:时间复杂度

快速排序的时间复杂度最优解就是每次都能正好把数组分成平均的两份,这样第一次能排好一个数的位置(每次都能排好基准数的位置),第二轮能排好两个数的位置(第一次将数组分为两份,有两个基准数,因此可以排好两个数),第三轮可以排好四个数的位置,第n轮可以排好2^(n-1)个数的位置,n轮就可以排好2^n-1个数(n个数需要比较约log2 n次),每一轮需要进行比较的次数为左右指针移动的次数之和,也就是第一轮需要比较n次,第二轮需要比较n-1次(刨去第一轮基准数,即已经排好的数字),第三轮比较n-3次……最后log2 n轮一共需要比较的次数与nlogn成正比,因此时间复杂度为O(nlogn);
最坏的情况下就是每次分成的两个数组中都有一个数组长度为0;这样每一轮只能将一个数字排到正确的位置,一共需要排n次,第一次需要比较n次,第二次需要比较n-1次,第三次需要比较n-2次……,一共n轮总共需要比较n(n+1)/2次,时间复杂度为O(n方);
平均时间复杂度:快速排序的平均时间复杂度也是:O(nlogn);快速排序时间复杂度较低,且非常稳定,因此比较重要;

四:代码实现

1.交换左右指针所指向的值:
void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
2.上述步骤的1-6步:进行一轮排序
int PartSort1(int* a, int left, int right)
{
	int keyi = left;
	while (left < right)
	{
		//找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}

		//找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[keyi], &a[left]);
	return left;
}
3.第七步:将数组分成两份,继续进行排序
void Quicksort(int* a, int begin, int end)
{
	int key = PartSort1(a, begin, end);
	Quicksort(a, begin, key - 1);
	Quicksort(a, key + 1, end);
}
完整代码:
void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}


int PartSort1(int* a, int left, int right)
{
	int keyi = left;
	while (left < right)
	{
		//找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}

		//找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[keyi], &a[left]);
	return left;
}



void Quicksort(int* a, int begin, int end)
{
	int key = PartSort1(a, begin, end);
	Quicksort(a, begin, key - 1);
	Quicksort(a, key + 1, end);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值