快速排序的理解及使用

是什么?

1、是一种按顺序从左往右(或从右往左)对每一个元素精确找到他在 有序序列 对应位置 ,并进行一一安放的算法。
2、好比如冒泡排序它是找到最值放到最边缘,然后依次循环进行排序;那快速排序就是不用找最值,而是将找到的值直接放到有序序列的合理位置。
3、简单而言,快速排序算法实现的就是你给它 的任何一个值,它都能将这个值插入队列中它应该待的位置。
4、当你能将每个值都插入它应该待的位置时,那无序也就变有序了。

为什么?(原理)

那它是怎么做到的呢?
/ / 以 小->大 为例
1、一个无序的集合如何知道某值它已经放在了正确的位置上 ?
方法是这个值的左边都是小于它的值,右边都是大于它的值,那这个值自然就是已经放置在正确的位置上了。(先不用烦左右两边具体的排序,就单单这个值的位置,你自己想想是不是。。)

2、那怎么把一个值放到正确的位置?

在这里插入图片描述
方法:

–>引入 : 不知道大家有没有玩过挪方块之类的游戏?
在这里插入图片描述
快速排序的实现 有点类似这种游戏,但它比这种游戏简单的太多了。

比如你在玩这种游戏时,如果挪不过去,是不是有种想将某个方块挖出来,然后怼到它合理的位置上的念头?
快速排序就有点像是在玩这种游戏,而且还是作弊着玩的那种。。。

1、挪方块都要有一个空格,那就要在集合里产生这个空格,所有要定义一个变量temp保存某个值,然后将这个值的变量空间当成空格。(这里以“6”做空格),再定义两个指针分别指向头和尾。
在这里插入图片描述
2、那怎么挪呢?
想知道怎么挪,就要先明白我们的目的。目的是找到“6”正确的位置,就是找到空格的正确位置。也就是使空格的左边比“6”小,空格右边比“6”大。
我们是以左边的值做空格,那就要从最右边开始往左移动找比“6”小的数,找到就将小的值放到 (赋值)这个空格,再将这个小的值所在的变量当成空格。
注:这里的“空格”是一种比喻,不代表里面不放值。
如图

在这里插入图片描述
那原本由low指针指向的空格就由high指针指着,这时候就轮到low指针来向左移动找比temp “6” 要大的值, 找到就将大的值(赋值)给现在的空格,再将这个大的值所在的变量位置当成空格。
如图

在这里插入图片描述
就是这样一直循环,最终low指针和high指针一定会相遇的

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
当low指针和high指针相遇时,此时空格所在的位置就是“6”所在的集合的正确位置!再将temp保存的值赋值给两指针所指的地方。
在这里插入图片描述

怎么用

接下来就是重点了!!!
(假定这集合的数放在数组内)
我们现在已经将一个值的正确位置进行放置好的思路将明白了。如果要写一个函数,默认要处理的值都是第一个数,那我们要传的参数就是指向这个数组的首和尾元素的指针(low、high)。只要给这个函数这两个指针,这个函数就能把首元素放置到正确的位置。
那这个函数的实现功能部分代码大概是这样子:

while(1)
	{
		//high指针向左移动,找到小的值或碰到low指针就跳出
		while(*high>temp)
			if(high!=low) high--; else break;  
		//处理high指针找到的小值,交换空格,或者和low指针相遇则收尾退出
		if( high!=low ) *low =*high;
			else {  *high = temp ; break;  }
	

		//low指针向右移动,找到大的值或碰到high指针就跳出
		while(*low<=temp)
			if(high!=low) low++; else break;  
		//处理low指针找到的大值,交换空格,或者和high指针相遇则收尾退出
		if( high!=low ) *high =*low; 
			else {  *high = temp ; break;  }
		
	}
	//当循环跳出时,temp的值就已经在正常的位置了

那么!那么!那么!
当这个值处于正确的位置时,它的两边是不是又产生了两个无序的集合,如果这两个集合也分别调用这个函数呢?就这样递归的调用下去,最终的结果就是这个值的两边也变得有序,也就完成了这个快速排序!

下面是快速排序代码实现:

void ks(int * low,int * high)
{
	int *head = low;  //保存原头元素所在位置
	int *tail = high;  //保存原尾元素所在位置
	int temp=*low ;    //处理的值

	while(1)
	{
		//high指针向左移动,找到小的值或碰到low指针就跳出
		while(*high>temp)
			if(high!=low) high--; else break;  
		//处理high指针找到的小值,交换空格,或者和low指针相遇则收尾退出
		if( high!=low ) *low =*high;
			else {  *high = temp ; break;  }
	

		//low指针向右移动,找到大的值或碰到high指针就跳出
		while(*low<=temp)
			if(high!=low) low++; else break;  
		//处理low指针找到的大值,交换空格,或者和high指针相遇则收尾退出
		if( high!=low ) *high =*low; 
			else {  *high = temp ; break;  }
		
	}
	
	//递归调用函数,处理temp值左边集合数据
	if(  head !=low && low!=(head+1)  )  //左边起码有两个元素才递归
		ks(head,low-1);
	
	//递归调用函数,处理temp值右边集合数据
	if(  tail !=low && low!=(tail-1)  )  //右边起码有两个元素才递归
		ks(high+1,tail);
	
	return ;
}

可以用一段小代码测试一下

#include<stdio.h>
int main()
{
	printf("请输入10个整数\n");
	int a[10];
	int i;
	for(i=0;i<10;i++)
	scanf("%d" ,&a[i]);
	
	int* low = a;
	int* high = a+9;
	
	for(i=0;i<10;i++)
	printf("%d  " ,a[i]);
	printf("\n");
	
	ks(low,high);
	
	for(i=0;i<10;i++)
	printf("%d  " ,a[i]);
	printf("\n");

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值