码迷,mamicode.com
首页 > 编程语言 > 详细

快速排序

时间:2016-07-30 22:44:18      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:快速排序

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!