日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

双调排序

發布時間:2024/9/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 双调排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

主要參考?http://www.cs.rutgers.edu/~venugopa/parallel_summer2012/bitonic_overview.html

雙調排序的時間復雜度是?O(n (logn)^2),這是說的串行的時間復雜度。這個算法的好處是可以很容易的實現并行,用多個核的并行運算提速,會比串行排序(快排等)要加速很多。


首先要清楚什么是雙調序列。是指一個序列前段是升序或者降序,后段是降序或者升序。那么對于任意兩個數,都是雙調序列。


基本的雙調排序只能處理2^n個數的序列。



首先我們定義一個操作是sortSeq, 輸出是一個雙調序列,其中前半段s1是升序,后半段s2是降序,設這個序列的長度是n,那么s1的元素是<a0,a1,..,an/2-1>,s2的元素是<an/2,an/2+1,..,an>

對s1和s2按照元素的對應位置進行如下操作:

如果a0 <= an/2, 那么不進行操作,否則交換兩個元素

用形式化的表示就是:


交換之后,s1中的序列就是兩兩比較較小的值,s2的序列就是兩兩比較較大的值

本來s1是升序,s2是降序的,經過如此操作之后,s1也是雙調的,s2也是雙調的


大家可以看出在構建s1和s2時,可以用n/2個線程對兩兩元素進行比較交換,從而實現并行運算


再對s1進行sortSeq操作,對s2進行sortSeq操作

就這樣遞歸操作,知道傳入sortSeq的序列長度為2

最終s就是升序排列的


那么如何構建最初的雙調序列?

算法采用從低向上的方法逐步構建雙調序列


對于無序數組,A,相鄰的兩個數肯定是雙調序列,比如(a0,a1), (a2,a3)等等

首先對a0,a1傳入sortSeq,變成升序序列,a2,a3傳入sortSeq,變成降序序列,a4,a5變成升序序列.....

接下來步長變為4,a0,a1,a2,a3是雙調序列,傳入sortSeq變成升序序列,a4,a5,a6,a7也是雙調的,傳入sortSeq變成降序序列

.....

最后步長是n,前n/2元素是升序,后n/2是降序,傳入sortSeq變成升序序列

至此算法完成



算法如上圖所示,左邊是無序的輸入序列,右邊是輸出序列,中間的是排序網絡,兩個圈連接的是比較器,

圖上所示還差最后一步的sortSeq,將其變成升序序列


#include <stdlib.h> #include <stdio.h> #include <iostream> #include <math.h> #include <time.h> #include <functional> #include <algorithm>using namespace std;// void sortSeq(int *arr, int len, bool ascend) {int step = len/2;for (;step >0 ;step /= 2) {for (int i = 0; i < len; i += 2*step) {for (int k = 0; k < step; ++k) {if (ascend) {if (arr[i + k] > arr[i + step +k]) swap(arr[i +k], arr[i+ step + k]);}else {if (arr[i + k] < arr[i + step +k]) swap(arr[i +k], arr[i+ step + k]);}}}} }void printvec(int *arr, int len) {for (int i = 0; i < len;++i) {cout << arr[i] <<"\t";}cout << endl; }int main(int argc, char *argv[]) {if (argc != 3) {cout << "len a|d\n";return 1;}int len = atoi(argv[1]);bool asd = argv[2][0] == 'a' ? true : false;int *arr = (int*)malloc(sizeof(int)*len);srand((unsigned)time(NULL));for (int i = 0; i < len; ++i) arr[i] = rand()%len;printvec(arr, len);for (int step = 2; step <= len; step *= 2) {for (int i = 0; i < len; i += 2*step) {sortSeq(arr + i, step, asd);//升序if (i + step < len) {sortSeq(arr + i + step, step, !asd);//逆序}}}printvec(arr, len);free(arr);return 1; }


如果元素個數不滿足2^n次方呢?


http://blog.csdn.net/ljiabin/article/details/8630627

排序網絡

n!=2^k的雙調排序網絡

經典的雙調排序網絡的設計是用來解決輸入長度n=2^k的情況。下面提出了一種對于任意n的雙調排序網絡算法,它的正確性來自于0-1原理。

問題:

對于長度為n=2^k的雙調排序網絡包含如表1所示的三塊。左邊兩塊是雙調排序網絡,把原序列均分為兩半,分別按升序和降序排列;右邊一塊是雙調合并網絡,歸并兩半有序序列,得到整個有序序列。

圖1:雙調排序(2^k)的結構

基礎定義:

定義:a = a0,…,a(n-1)是一個0-1序列。

??? 當序列只包含0時,我們稱a為清潔的0序列,即a0,…,a(n-1) = 0.

??? 當序列只包含1時,我們稱a為清潔的1序列,即a0,…,a(n-1) = 1.

??? 如果a序列是由一個清潔的0序列后接一個清潔的1序列構成的,那么我們稱a單調遞增,即a0,…,a(k-1) = 0, ak,…,a(n-1) = 1.

??? 如果a序列是由一個清潔的1序列后接一個清潔的0序列構成的,那么我們稱a單調遞減,即a0,…,a(k-1) = 1, ak,…,a(n-1) = 0.

如果a序列依次由一個清潔的0序列、一個清潔的1序列和一個清潔的0序列構成,那么我們稱a序列雙調遞增,即a0,…,a(k-1)= 0, ak,…,a(m-1) = 1, am,…,a(n-1) = 0.

如果a序列依次由一個清潔的1序列、一個清潔的0序列和一個清潔的1序列構成,那么我們稱a序列雙調遞減,即a0,…,a(k-1)= 1, ak,…,a(m-1) = 0, am,…,a(n-1) = 1.

根據這個定義,一個清潔的序列既可以被稱作單調遞增,也可以被稱作單調遞減。相似的,一個單調序列既可以被稱作雙調遞增,也可以被稱作雙調遞減。圖2展示了雙調序列的一些例子,其中,白色部分代表0,灰色部分代表1,箭頭代表特殊情況關系(如清潔的0序列是雙調遞增序列的一種特殊情況)。

圖2:雙調序列的例子

定理:設定a是一個0-1序列,如果a是一個清潔的0/1序列或單調遞增/減序列或雙調遞增/減序列,那么a的子序列a’也是。

想法:

標準的雙調排序使用了比較網絡Bp(p=2^k),我們根據比較網絡Bp推導出對于任意n的網絡Bn,p是大于的第一個2的冪次方,然后僅僅對n-p/2的元素使用比較網絡。圖3展示了n=6時的比較網絡Bn,把它嵌入到p=8的比較網絡Bp,僅僅使用了前兩個比較器。

圖3:比較網絡Bp應用于長度為n的雙調遞減0-1序列a

定理:n!=2^k,p是大于n的最小的2的冪次方,對雙調遞減0-1序列a應用比較網絡Bn,產生序列b和c具有以下特性(圖3中):

|b| = p/2, b =2^k,

對任意I,j有bi <= cj,

b是雙調序列,c是雙調遞減序列。

證明:如果輸入的長度為n的雙調遞減a被用1填充為長度為p的序列a’,那么這個序列仍保持雙調遞減。應用比較網絡Bp將產生兩個雙調序列b和c’,|b| = p/2,對于任意i和j,bi <= cj(見標準雙調排序)。由于填充的1保持在末尾不變,所以c’雙調遞減。如果不考慮后面填充的1,序列c’的子序列c也是雙調遞減。后面屬于Bp卻不屬于Bn的比較是多余的,因此網路Bn應用于序列a會得到同樣的結果。

根據這個定理,應用于雙調序列b的比較網絡Bp(p=2^n)和應用于雙調遞減序列c的網絡Bn(n任意)的遞歸程序將產生一個有序序列。

如果排序的方向是遞減而非遞增,這個定理同樣適用于“雙調遞增”而非“雙調遞減”。證明時,原序列a用0而非1來填充。

最開始,一個序列通過對前一半遞減排序對后一半遞增排序得到一個雙調遞減序列。圖4展示了對任意輸入長度n的雙調排序網絡的結構圖,由于這個網絡對每一個0-1序列排序,根據0-1原理它對任意長度的0-1序列排序。

圖4:對任意輸入長度n的雙調排序結構圖

程序:

下面的程序實現了對于任意輸入長度n的雙調排序

[java]?view plaincopy
  • Sorter?s=new?BitonicSorterForArbitraryN();??
  • s.sort(b);??
  • 數組b通過雙調排序排序。

    [java] view plaincopy
  • public?class?BitonicSorterForArbitraryN?implements?Sorter??
  • {??
  • ????private?int[]?a;??
  • ????private?final?static?boolean?ASCENDING=true;????//?sorting?direction??
  • ???
  • ????public?void?sort(int[]?a)??
  • ????{??
  • ????????this.a=a;??
  • ????????bitonicSort(0,?a.length,?ASCENDING);??
  • ????}??
  • ???
  • ????private?void?bitonicSort(int?lo,?int?n,?boolean?dir)??
  • ????{??
  • ????????if?(n>1)??
  • ????????{??
  • ????????????int?m=n/2;??
  • ????????????bitonicSort(lo,?m,?!dir);??
  • ????????????bitonicSort(lo+m,?n-m,?dir);??
  • ????????????bitonicMerge(lo,?n,?dir);??
  • ????????}??
  • ????}??
  • ???
  • ????private?void?bitonicMerge(int?lo,?int?n,?boolean?dir)??
  • ????{??
  • ????????if?(n>1)??
  • ????????{??
  • ????????????int?m=greatestPowerOfTwoLessThan(n);??
  • ????????????for?(int?i=lo;?i<lo+n-m;?i++)??
  • ????????????????compare(i,?i+m,?dir);??
  • ????????????bitonicMerge(lo,?m,?dir);??
  • ????????????bitonicMerge(lo+m,?n-m,?dir);??
  • ????????}??
  • ????}??
  • ???
  • ????private?void?compare(int?i,?int?j,?boolean?dir)??
  • ????{??
  • ????????if?(dir==(a[i]>a[j]))??
  • ????????????exchange(i,?j);??
  • ????}??
  • ???
  • ????private?void?exchange(int?i,?int?j)??
  • ????{??
  • ????????int?t=a[i];??
  • ????????a[i]=a[j];??
  • ????????a[j]=t;??
  • ????}??
  • ???
  • ????private?int?greatestPowerOfTwoLessThan(int?n)??
  • ????{??
  • ????????int?k=1;??
  • ????????while?(k<n)??
  • ????????????k=k<<1;??
  • ????????return?k>>1;??
  • ????}??
  • ???
  • }??
  • 網絡:

    例如,圖5展示了輸入長度為6的雙調排序網絡。

    圖5:輸入長度為6的雙調排序網絡

    分析:

    這個對于任意n的新排序網絡可以嵌入原始的對于2^k的雙調排序網絡。因此,它仍有?log(n)?· (log(n)?+?1)?/?2 層,每層最多比較n/2次,結果是一個復雜度為O(nlog(n)^2)的比較器,跟原始的雙調排序網絡一樣。


    總結

    以上是生活随笔為你收集整理的双调排序的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。