快排及其优化(C语言)

快排的普通写法(递归)

时间复杂度(平均情况):nlog2(n)

int PartSort(int*arr,int first,int end)     //分步排序函数
{
	int tmp=arr[first]; //取第一个数作为基准值
	while(first!=end)
	{                                      //取左边作为基准值从右面开始判断
		while(first=tmp)  //判断end指向的值是否大于基准值
			end--;                         //如果大于,end向左移动
		arr[first]=arr[end];               //否则将值放到左边
		while(first

基于普通情况下的快排,选取首元素或者尾元素作为基准数,如果数组有序,此时就为最坏情况的快排,这时的数组会被划分为一个最长子数组和一个空数组,这样快排的时间复杂度就变为了O(n^2)

优化1:三分取中法。对基准数的选取进行优化,取首元素,中间元素和尾元素进行比较,取三个中中间值作为基准值。这样分割数组时就可以有效的分为等长数组。

//和上面代码相比,加入两个函数进行优化。同时改变Quick函数的内容
//三分取中法,两次比较以后将最小的值放在中间,最后一次比较将小的值(此值为三个数中第二大的值)放在首位置作为基准数

void FindSecondMax(int arr[], int first, int end, int mid)
{
	if (arr[end] < arr[mid])         
	{
		swap(arr, mid, end);
	}
	if (arr[first] < arr[mid])
	{
		swap(arr, mid, first);
	}
	if (arr[first] < arr[end])      
	{
		swap(arr, end, first);
	}
}

void swap(int arr[], int firstIndex, int secondIndex)
{
	int tmp = arr[firstIndex];
	arr[firstIndex] = arr[secondIndex];
	arr[secondIndex] = tmp;
}
void Quick(int*arr,int first,int end)
{
	if(first

优化2:数据量较小时使用直接插入排序时间复杂度会小一些为O(n).

void selectSort(int arr[],int len)
{
	int i,j;
	int min;
	int tmp;
	for(i=0;iarr[j])
			{
				min=j;
			}
		}
			tmp=arr[min];
			arr[min]=arr[i];
			arr[i]=tmp;
	}
}

优化3:当重复数值较多时,把与基准点相同的数据聚合在一起 ,不进行下一趟排序

void gather(int arr[], int first, int end, int mid, int *left, int *right)
{
	if (first < end)
	{
		int count = mid - 1;
		for (int i = mid - 1; i >= first; --i)
		{
			if (arr[i] == arr[mid])
			{
				swap(arr, i, count);
				count--;
			}
		}
		*left = count;
		count = mid + 1;
		for (int i = mid + 1; i <= end; ++i)
		{
			if (arr[i] == arr[mid])
			{
				swap(arr, i, count);
				count++;
			}
		}
		*right = count;
	}
}

 

你可能感兴趣的:(数据结构顺序)