說說雙調排序

一、簡介

    雙調排序(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

發佈了61 篇原創文章 · 獲贊 19 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章