1、快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
2、排序的过程
3、代码实现
三数取中法代码:
//优化一:三数取中法,避免出现最坏的情况
int GetMidIndex(int* a,int left,int right)
{
	assert(a);
	int mid = left + (right- left)/2;
	if(a[left] > a[right])
	{
		if(a[mid] > a[left])
		{
			return left;
		}
		else
		{
			if(a[mid] > a[right])
				return mid;
			else
				return right;
		}
	}
	else//right大
	{
		if(a[mid] > a[right])
			return right;
		else//right 大
		{
			if(a[mid] > a[left])
				return mid;
			else
				return left;
		}
	}
}快速排序的代码:
int PartSort1(int* a,int left,int right)
{
	int mid = GetMidIndex(a,left,right);
	int key = a[mid];
    int begin = left;
    int end = right-1;
	swap(a[mid],a[right]);
    while(begin <end)
    { 
        while(begin <end && a[end] >=key)
            end--;
		 while(begin <end && a[begin] <key)
            begin++;
		 if(begin < end)
		swap(a[begin],a[end]);
    }
	if(a[begin] > a[right])
	{
		swap(a[begin],a[right]);
		return begin;
	}
	else
		return begin;
}
void QuickSort(int* a,int left,int right)
{
	//快速排序的第二种优化,将插入排序与快速排序结合
	assert(a);
	if(left >= right)
		return;
	if(right -left < 16)
	{
		InsertSort(a+left,right-left+1);
		return;
	}
	else
	{
	    int ret = PartSort1(a,left,right);
	    QuickSort(a,left,ret-1);
	    QuickSort(a,ret+1,right);
	}
}另外两种快速排序的方法:
//挖坑法
int PartSort2(int* a,int left,int right)
{
	int mid = GetMidIndex(a,left,right);
	int key = a[mid];
    int begin = left;
    int end = right;//初始时的坑
	swap(a[mid],a[right]);
	while(begin < end)
	{
		while(begin < end && a[begin] <= key)
			begin++;
		if(begin < end)
		{
			a[end] = a[begin];//begin的位置变为坑
		}
		while(begin < end && a[end] >= key)
			end--;
		if(begin < end)
		{
			a[begin] = a[end];
		}
	}
	//跳出循环后,begin的位置为坑,将key放入
	a[begin] = key;
	return begin;
}
//双指针法
int PartSort3(int* a,int left,int right)
{
	int mid = GetMidIndex(a,left,right);
	int key = a[mid];
	swap(a[mid],a[right]);
	int cur = 0;
	int prev = -1;
	while(cur < right)
	{
		if(a[cur] < key && (++prev != cur))
			swap(a[cur],a[prev]);
		cur++;			
	}
	prev++;
	swap(a[prev],a[cur]);
	return prev;
}4、时间复杂度
1)最好:O(N*logN)
在最好情况下,每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数:O(NlogN)。
2)最坏:O(N*N)(key取得的值接近最大或最小)
最坏情况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。时间复杂度为O(N*N)。
本文出自 “LOVEMERIGHT” 博客,请务必保留此出处http://lovemeright.blog.51cto.com/10808587/1832176
原文:http://lovemeright.blog.51cto.com/10808587/1832176