快速排序

                         快速排序算法学习总结

我们是在大三下半学期开始上算法课的,大一下学期学了数据结构,对几大排序算法都有过学习,但长时间不去写这些东西,贸然动手还是不适应,说白了就是忘了。今年刚开算法课,我又把以前的排序算法重新拿出来复习一下顺便做个总结。
快速排序是由C.R.Hoare提出的一种划分交换排序,采用的是分治的策略。
这个排序算法的基本思想是:
首先,从一个数组中取出一个数作为基数。(什么样的数组类型?取哪个数作为基数?如何取?)
然后,分区,将数组中比这个数大的放到基数的右边,比基数小的放到左边。(怎么放?基数是不是中间数啊?)
最后,对左右区间继续分区,直到各个区间只有一个数的时候不能再分为止。(是递归吗?)
在理解快速排序算法的时候,我看到csdn上有篇博客提出的一种“挖坑填数+分治法”思想,理解起来非常简单。下面我就来描述一下这种思想是怎么实现的。
算法流:
step1:在一个整数数组(int a[ ])中,取第一个元素作为基数。    
012345
121233456
       我们定义X=a[0]=12为基数,同时定义i 和 j 来分别指向数组的左右两端,这样初始的i为0,那么可以得到X=a[i]=12。这时候我们可以理解为a[0]中的12已经被挖了                          出来,里面只有一个空坑。
step2:从数组的最右边,我们借助变量j开始找比12小的数,发现a[5]上的数值为6,满足条件,将6放到a[0]的位子上,i变量+1,i指到a[1]的位置上,这样a[5]上就形成了                          新 坑,我们让他从a[i](刚才i+1,现在是a[1])开始往右遍历找比X(值为12)大的数,当i=2的时候,值为23,比12大,所以我们把他放到刚才空出来的a[5]的位       子       上,j--移动到前(左)一个位子上(到达a[4]),这样新空出来的坑是a[2].
012345
61 34523
step3:接着,我们开始借助j(现在指向a[4])往左遍历搜索比x小的数,刚到a[3]就发现满足了条件,所以我们要把a[3]放到新坑a[2]的位子上,i++,现在指向的是a[3]。
012345
613 4523
step4:现在,我们开始从a[3]往右搜索寻找比X大的数,当搜索到a[4]的时候i==j,不在挖坑交换,45呆在原地不动,将12放到a[3]的位置。这样,第一次递归的结果就出来      了:
012345
613124523
step5:现在,经过第一次排序,可得大致的结果,左边小于右边。然后,我们再依次分别对a[3]左面和右面的数递归调用快速排序方法。


我的思考:
        首先,挖坑思想可以很形象的解决快速排序中的++和--问题,很有意思的把问题消化理解。但是数组中数据存储的方式理解的话却又不是很正确。为什么?数据被挖走了吗?x在这段时间去哪里了?似乎还是呆在他的地方参与了数据的交换。这里的赋值问题并没有把存储地址复制,也就是说他的存储地址没有改变。不过这种思想又是相当的巧妙,看完后不仅拍案叫绝。
下是自己敲的代码,开始调试的时候出现过栈溢出错误,原因找到了,祥见代码中注释。


#include<iostream>
#include<string>
using namespace std;
int Partation(int a[],int left,int right){//left和right分别代表数组的开始和结束下标
	int x=a[left];//确定基础
	int i=left;//左变量,用来往右移动
	int j=right;//右变量,用来往左移动
	while(i<j){
		while(i<j&&a[j]>=x){//从右往左找
			j--;
		}
		if(i<j){
			a[i++]=a[j];//等价于a[i]=a[j]
		}				//i++
		while(i<j&&a[i]<x){//从左往右找
			i++;
		}
		if(i<j){
			a[j--]=a[i];//等价于a[j]=a[i]
		}				//j--
	}
	a[i]=x;
	return i;
}
int hebing(int a[],int left,int right){
	int i=Partation(a,left,right);//定义变量i标记中间值下标
	if(left<right)//判断条件不能少,否则会栈溢出
	{
		return Partation(a,left,i-1);//必须要有返回值
		return Partation(a,i+1,right);//如果没有返回值,子数组无法确定待分割的下标
	}
}


int main(){
	
	int a[6]={12,34,6,2,4,8};
	hebing(a,0,5);//函数调用
	for(int i=0;i<6;i++){//输出排序后的结果
		cout<<a[i]<<" ";
	}
	return 0;
}

运行结果:




注:本文中提到的挖坑思想来源于网络: http://www.cnblogs.com/morewindows/archive/2011/08/13/2137415.html
另,本文中提到的说法或代码有问题,欢迎各位批评指正。多谢!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值