快速排序详解及不排序求中位数o(n)算法

      先理解快速排序。

int partition(int L[],int low,int high)
{
	int i,num=low;
	for(i=low+1;i<=high;i++)
	{
		if(L[i]<L[low])
		{
			swap(&L[i],&L[num+1]);
			num++;
		}
	}
	swap(&L[low],&L[num]);
	return num;
}

      以上面的算法代码为例,L为要排序的数组,low和high是序列的两头元素的坐标,将序列第一个元素作为哨兵,定义变量num=low,这个变量表示哨兵的最终位置。以low=0,high=L.length-1为例,即对整个数组进行第一次排序:哨兵与数组中其他所有数字进行比较,如果比哨兵小,则将该数与num+1位置的数交换,确保num+1位置的数都比哨兵小,num++。遍历完整个数组之后,num位置之前的数都比哨兵小,则num就是哨兵的最终位置,也就是说哨兵是数组中第num小的数。

void Qsort(int L[],int low,int high)
{
	if(low<high)
	{
		int pivot=partition(L,low,high);
		Qsort(L,low,pivot-1);
		Qsort(L,pivot+1,high);
	}
}

      上面是对整个数组不断做划分,进行排序的递归算法代码。if(low<high)是保证划分的序列最少有两个数,语句中,先对整个数组进行第一次排序,得到第一个哨兵的最终位置,以此位置作为分割点,对左右两个序列进行排序,得到他们的哨兵的最终位置,再以此为分割点······最后得到有序的数组。这是快速排序的基本思路。

-------------------------------------------------------------------------------------------------------------------------

      中位数是指一段序列中,比它大的数和比它小的数的数量相等的那个数。序列经过排序后中位数在最中间。可以联想到使用快速排序的思想,找到最终位置在n/2的那个数。

      而找中位数,是要找到最终位置在中间的那个数,即mid=(low+high)/2时的那个数。找中位数并不需要像快速排序那样找到每个数的最终位置,所以并不需要划分序列。如果进行一次partition(L,low,high)排序后找到那个数的最终位置偏右,即他的最终位置大于mid,则这个数比中位数大,又因为这个数右边的数都比这个数大,则可以high=pos-1,将这个数右边的数都舍去再进行快排。同理,如果最终位置偏左,则继续进行low=pos+1,将小于中位数的数舍去再进行快排。最后当mid=(low+high)/2时,函数结束,输出结果。

void getmid(int L[],int low,int high)
{
	int mid=(low+high)/2;
	while(1)
	{
		int pos=partition(L,low,high);
		if(pos==mid)
			break;
		else if(pos>mid)
			high=pos-1;
		else low=pos+1;
	}
	printf("%d",L[mid]);
}
      还有一个小问题就是数组的长度是偶数时,要输出中间两个数的平均值。可以将mid的值返回到主函数中,输出mid位置和mid+1位置的两个数的平均值即可。

猜你喜欢

转载自blog.csdn.net/q_m_x_d_d_/article/details/80108541
今日推荐