说说双调排序

一、简介

    双调排序(Bitonic Sort)属于排序网络(Sorting Network)的一种,它是一种可以并行计算的排序算法。

    要理解双调排序,首先需要理解双调序列,双调序列定义如下:

    如果序列<a0, a1, …, an-1>满足以下两个条件之一,则称之为双调序列:™

    存在一个0≤k≤n-1,使得<a0, a1, …, ak-1>为升序序列,<ak, ak+1, …, an-1>为降序序列;或存在一个标号的循环移位,使得条件1)满足。

    如果n为偶数,且<a0, a1, …, an/2-1>为升序序列,<an/2, an/2+1, …, an-1>为降序序列,则以下两个序列都是双调序列

    S1=<min(a0, an/2), min(a1, an/2+1), …, min(an/2-1, an-1)>

    S2=<max(a0, an/2), max(a1, an/2+1), …, max(an/2-1, an-1)>

    双调排序主要思想:

    1、首先不断的二分,直到每组只剩下一个元素,然后开始归并。

    2、双调排序归并时以不大于n的最大2的幂次方2^k为界限,把2^k~n的元素分别与0~(n-2^k)的元素比较,然后再分别在0~2^k和2^k~n这两段上应用比较网络。

    3、双调排序难以理解的地方就在于这个归并的过程,假设我们要把长度为n的序列a升序排列,由于二分时是把前n/2的序列降序排列后n/2的序列升序排列的,而n-2^k < n/2,所以前n-2^k 和后n-2^k个元素都大于中间的元素,当前n-2^k个元素和后n-2^k个元素比较时,会把序列中最大的n-2^k个元素放到最后n-2^k个位置上,也就是说比较后,2^k~n的元素都比0~2^k的元素大,这样在分别对这两段用同样的方法归并,最终得到完整的升序序列。

    以6个元素的序列为例,当前3个元素已经降序排好,后3个元素已经升序排好(递归到底时是从1个元素开始返回的,所以对6个元素归并时前后3个元素已经排好序),这个以4(不大于6的最大2的幂次方)为界限,分别让第1个和第5个、第2个和第6个元素比较,使得这6个元素中最大的两个处于第5、6个位置上,然后再分别对前4个和后2个元素按此方法归并,最终递归完成排序。

二、算法实现

//双调归并过程
template <typename T>
void BitonicMerge(T* pFirst,T* pLast,bool bDirection)
{
	T* pTemp = pFirst;
	if(pFirst < pLast)
	{
		int nLength = pLast - pFirst + 1;                   //计算数组长度
		int nMid = 1;
		while(nMid < nLength)                               //计算小于数组长度的2的最大幂次方值k
			nMid = nMid << 1;
		nMid = nMid >> 1;
		for(int i=0;i< nLength - nMid;i++)                  //对元素0~n-k和元素k~n进行比较,根据升序降序标志bDirection对元素进行交换
		{
			if((*(pTemp+i) > *(pTemp+i+nMid)) == bDirection)
			{
				Swap(*(pTemp+i),*(pTemp+i+nMid));
			}
		}
		BitonicMerge(pFirst,pFirst+nMid-1,bDirection);      //递归对数组前后两部分元素进行双调递归
		BitonicMerge(pFirst+nMid,pLast,bDirection);
	}
}


//Bitonic排序(双调排序):属于排序网络(Sorting Network)的一种,它是一种可以并行计算的排序算法。
//首先,双调序列是指序列要么先单调递增然后再单调递减,要么先单调递减然后又单调递增。
//通过对要排序的数组构造双调序列,然后递归进行双调归并即可完成对数组的排序
template <typename T>
bool BitonicSort(T* pFirst,T* pLast,bool bDirection,Compare pFun)
{
	bool bIsReverse = false;
	T* pTemp = NULL;
	if((pFirst == NULL) || (pLast == NULL))
	{
		cout<<"Input parameters error!"<<endl;
		return false;
	}
	if(pFirst > pLast)
	{
		bIsReverse = true;
		pTemp = pFirst;
		pFirst = pLast;
		pLast = pTemp;
	}
	if(pFirst < pLast)
	{
		int nNum = pLast - pFirst + 1;                         //计算数组长度
		int nMid = nNum / 2;                                   //计算中间元素索引值
		BitonicSort(pFirst,pFirst+nMid-1,!bDirection);         //对数组前半部分递归进行分裂
		BitonicSort(pFirst+nMid,pLast,bDirection);             //对数组后半部分递归进行分裂
		BitonicMerge(pFirst,pLast,bDirection);                 //双调归并过程
	}
	if(bIsReverse)
	{
		while(pFirst < pLast)
		{
			Swap(*pFirst,*pLast);
			++pFirst;
			--pLast;
		}
	}
	return true;
}

    其他 排序算法及数据结构的具体实现详见GitHub:https://github.com/daiyl0320/IntroductionToAlgorithms

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值