快速排序之C++实现

1.快速排序之C++实现

快速排序本质上是一个分治算法,其重点在于数组的拆分。当我们定义一个比较基准元素后,将数组中小于该基准元素的数放到其左边,将大于基准元素的放到其右边。这样我们就将数组拆分成了左右两部分:小于比较元素的数组;大于比较元素的数组。我们再对这两个数组进行同样的拆分,直到拆分到不能再拆分,数组就自然而然地以升序排列了。

基准元素
小于比较元素的数组
大于基准元素的数组

抛开快速排序的数组划分,这个划分思想我们要注意在其他算法设计时可扩展性
下面介绍两种划分数组的方式实现,分别命名为split和partition。

1.1 split划分

split算法使用一个单向的指针来对数组进行遍历,开始之时将数组首元素设置为基准元素,然后将第二个开始的元素依次与基准元素比较,如果大于基准元素则跳过,如果小于基准元素则将其与前面较大的元素进行交换,将数组中所有元素交换完毕后,再将基准元素放到中间位置。此时基准元素左边的值均小于基准元素,基准元素右边的值均大于基准元素。

是不是很像数组处理中的快慢指针法

下面是以数组{4,7,6,3,8,2,1,5}为初始数组划分一次的示意图,可以看到一轮划分后按照基准元素4将数组划分为两个部分。
在这里插入图片描述

1.2 partition划分

partition算法使用首尾两个反向的指针进行遍历,也是先将数组第一个元素设置为基准元素,左指针i从左至右找到第一个大于基准元素的数,右指针j从右至左找到第一个小于基准元素的数,全部交换完毕后将基准元素放到中间位置。注意在最后一次指针位置更新后,此时的i和j指向了同一个元素,虽然此时出现了i=j但是进入循环之前的i<j是成立的,也就是说此时不用再进行两个元素的交换。所以我们选择在碰到这种边界条件时直接将跳出本层循环,将其与基准元素交换。
在这里插入图片描述
需要注意的是我们上面过程中的指针移动的先后次序是不能调换的,也就是必须先移动j指针,然后再移动i指针,否则就会导致不好定位与基准元素交换位置的元素。如在上面的例子中就会使得i指针走过头,此时的i和j会同时指向元素8.

2.具体代码

//快速排序实现
int split(int *a,int low,int high){
	int i =low;
	int x = a[i];
	for(int j=i+1;j<=high;j++){
        //如果当前元素小于基准元素
		if(a[j] <= x){
            //应该放在基准元素左边,根据慢指针进行填充
            //并将可能不属于左边的元素换到后面去
			i++;
			if (i != j) {
                   swap(nums[i], nums[j]);
             }
			}
	}
    //交换基准元素与最后一个小于等于基准元素的值
    swap(a[low],a[i]);
	return i;
} 

int partitiion(int *a,int low,int high){
	int x=a[low];
	int i =low,j=high;
	while(i<j){
        //从右到左找第一个小于等于基准的值
		while(i<j && a[j]>=x){
			j--;
		}
        //从左到右找第一个大于等于基准的值
		while(i<j && a[i]<=x){
			i++;
		}
        //如果不是指向同一个位置则说明还未处理完,交换元素
		if(i!=j){
			swap(a[i],a[j]);
		}
	}
    //i==j 已经遍历完
	swap(a[low],a[i]);
	return i;
	}
	
void quickSort(int *a,int low,int high){
	if(low < high){
		int par = partitiion(a,low,high);
        cout<<"这次分隔的par是"<<par<<endl;
		quickSort(a,0,par-1);
		quickSort(a,par+1,high);	
	}
}

绝了,代码还是要手写一遍,不然有些很细节的错误还是不好把握

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值