算法排序之双路快速排序

问题:对于一个有着非常多重复数字的数组

 

因为有很多重复数字,会导致partition以v划分出来的数组,有一部分会非常大,那么还是会出现分出来的两个子数组可能一大一小,那么快速排序生成的递归树的平衡度就比归并排序差,并且不能保证深度就是logn,很有可能高于logn,最差就演变成O(n^2)

 

改进:将小于v和大于v的元素分别放在数组的两端

 

i一直往后遍历数据,直到e>=v

j一直往前遍历数据,直到e<=v

 

将遍历到的数据归并----交换i和j两个所指的元素

继续遍历,知道i和j两个数重合

这样做可以将等于v的元素分散到两个数组之中,使得不会出现两个数组长度相差过大的情况。

#include <iostream>
#include <algorithm>
#include <ctime>

using namespace std;

//双路快排 
//对arr[l,r]做partition 
int partition(int arr[], int l,int r){
	//[l+1,i-1]<v [j,r]>v
	int v = arr[l];
	int i=l+1;
	int j=r;
	while(true)
	{
		if(i<=r && arr[i]<v) i++;//从左到右,找到一个>=v的数字
		if(j>l && arr[j]>v) j--; //从右到左,找到一个<=v的数字
		if(i>j) break;
		swap(arr[i],arr[j]);
		i++;
		j--;
	}
	
	swap(arr[l],arr[i-1]);
	return i-1;
}
void quickSort(int arr[], int l,int r){
	if(l>=r)
		return;
	int p=partition(arr,l,r); //为数组的第一个数找到正确的位置并返回 
	quickSort(arr,l,p-1);//<v部分做快排 
	quickSort(arr,p+1,r);//>v部分做快排 
}


int main()
{
	int a[10]= {5,8,7,9,6,3,4,1,2,0};
	quickSort(a,0,9);
	for(int i=0; i<10; i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl;
	
	return 0;
}

 

测试有重复数值:

 

发布了86 篇原创文章 · 获赞 0 · 访问量 4084

猜你喜欢

转载自blog.csdn.net/qq_31965925/article/details/105144739