双调排序算法Bitonic Sort的实现

双调排序(bitonic sort)属于排序网络(Sorting Network)的一种,是一个可并行计算的排序算法。

Bitonic Sort是一个叫Batcher的数学家在1968年提出的。基础是关于双调序列的Batcher定理。

这个排序算法其实实现起来比较简单(当然我说的是递归实现),但是隐藏在其背后的数学原理就不是那么简单就能说明白的了。在参考了维基百科(http://en.wikipedia.org/wiki/Bitonic_sorter)上面的介绍以及小例子之后,基本明白了这个算法的实现原理。

1、对于一个给定的整形数组A,我们将其均分为两个部分A1,A2;

2、对A1进行升序排序,对A2进行降序排序;

3、将A1和A2进行合并,成为一个升序的数组;

算法的重点在于合并的部分,这其中利用了所谓的Batcher定理。

废话不说了,下面上代码:

  1 #include <iostream>
  2 #include <string>
  3 using namespace std;
  4 
  5 //双调排序类
  6 class Bitonic_Sorter
  7 {
  8 private:
  9     int* array;//改造后的输入数组,是真正进行排序处理的数组
 10     int* tmp_array;//实际输入的数组
 11     int length;//改造后的输入数组的长度
 12     int tmp_length;//输入数组的实际长度
 13     int gap;//原数组长度和改造后数组长度差值(0或一个正数)
 14     bool dire;//排序方式,true为升序
 15     int ret_gap();
 16     void transfer();
 17     void bitonic_sort(int lowbundary, int len,bool direction);
 18     void bitonic_merge(int lowbundary,int len,bool direction);
 19     void compare_and_swap(int i,int j,bool direction);
 20 public:
 21     Bitonic_Sorter(int arr[],int len);
 22     void printData();
 23     void Sorter(bool dir);
 24 };
 25 
 26 //构造函数,完成属性赋值
 27 Bitonic_Sorter::Bitonic_Sorter(int arr[],int len)
 28 {
 29     tmp_array = arr;
 30     tmp_length = len;
 31     gap = ret_gap();
 32     
 33 }
 34 
 35 //根据输入数组的长度返回gap的值
 36 int Bitonic_Sorter::ret_gap()
 37 {
 38     double x = (double)log(tmp_length) / log(2);//求log2(length);
 39     int z = x + 1;
 40     int a = (int)pow(2,z);
 41     int b = a - tmp_length;//若length是2^n,则b=0;否则b为其与下一个2^n的差值;
 42     if (b == tmp_length)
 43     {
 44         return 0 ;//说明输入的数组长度满足2^n
 45     }
 46     else{
 47         return b ;//说明输入的数组长度与2^n相差b
 48     }
 49 }
 50 
 51 //改造函数,将长度不是2^n的输入数组改造成2^n数组
 52 void Bitonic_Sorter::transfer()
 53 {
 54     if(gap == 0){//输入数组长度满足2^n
 55         array = tmp_array;
 56         length = tmp_length;
 57     }
 58     else{
 59         int *temp = new int[tmp_length+gap];//tmp_length+gap即是改造后的数组长度
 60         for(int i = 0;i<tmp_length;i++)//完成原数组对新数组的赋值
 61         {
 62             temp[i] = tmp_array[i];
 63         }
 64         for (int j = tmp_length;j<tmp_length+gap;j++)//对新数组的多余部分赋值
 65         {
 66             if (dire)//升序的话,则填充整型数最大值,不会影响排序及输出,仍取排序后的前tmp_length个数
 67             {
 68                 temp[j] = INT_MAX;
 69             }
 70             else//降序的话,则填充整型数最小值。
 71             {
 72                 temp[j] = INT_MIN;
 73             }
 74         }
 75         array = temp;
 76         length = tmp_length+gap;
 77     }
 78 }
 79 
 80 //打印改造后的数组,用于排序后输出
 81 void Bitonic_Sorter::printData()
 82 {
 83     for(int i=0;i<tmp_length;i++)//tmp_length才是我们实际需要的排序结果长度
 84     {
 85         cout<<array[i]<<", ";
 86     }
 87 }
 88 
 89 //公有排序函数,调用私有函数实现
 90 void Bitonic_Sorter::Sorter(bool dir)
 91 {
 92     dire = dir;//排序方式
 93     transfer();//调用改造函数
 94     bitonic_sort(0,length,dire);
 95 }
 96 
 97 //私有排序函数,递归调用实现
 98 void Bitonic_Sorter::bitonic_sort(int lowbundary,int len,bool direction){
 99     if(len>1){
100         int m=len/2;
101         bitonic_sort(lowbundary,m,direction);//对前半部分进行排序
102         bitonic_sort(lowbundary+m,m,!direction);//后半部分
103         bitonic_merge(lowbundary,len,direction);//两部分组合
104     }
105 }
106 
107 //合并函数,递归调用实现
108 void Bitonic_Sorter::bitonic_merge(int lowbundary,int len,bool direction){
109     if(len>1){
110         int m=len/2;
111         for(int i=lowbundary;i<lowbundary+m;i++){
112             compare_and_swap(i,i+m,direction);
113         }
114         bitonic_merge(lowbundary,m,direction);//递归合并前半部分
115         bitonic_merge(lowbundary+m,m,direction);//后半部分
116     }
117 }
118 
119 //比较交换函数
120 void Bitonic_Sorter::compare_and_swap(int i, int j,bool direction){
121     if(direction==(array[i]>array[j])){
122         swap(array[i],array[j]);
123     }
124 }
125 
126 //主函数
127 void main()
128 {
129     int inputarray[1000];
130     int count = 0;
131     cout<<"Please Input Your Numbers, Each One With An Enter, Finished By Ctrl+Z!"<<endl<<"Start>>";
132     while (cin>>inputarray[count])
133     {
134         cout<<"Next>>";
135         count++;
136     }
137     //以上为输入数组
138     cout<<endl<<"INPUT: 【 ";
139 
140     for (int i=0;i<count;i++)
141     {
142         cout<<inputarray[i]<<", ";
143     }
144     cout<<""<<endl;
145     //输出输入的数组
146     Bitonic_Sorter bs = Bitonic_Sorter(inputarray,count);
147     bs.Sorter(true);
148     cout<<"OUTPUT IN ASCENDING ORDER: 【 ";
149     bs.printData();
150     cout<<""<<endl;
151     //升序排序
152     bs.Sorter(false);
153     cout<<"OUTPUT IN DESCENDING ORDER: 【 ";
154     bs.printData();
155     cout<<""<<endl;
156     //降序排序
157     system("pause");//等待结束
158 
159 }

在编码时参考了http://blog.csdn.net/here1009/article/details/7918185,但是经过实际运行发现它的代码虽然支持任意长度数组排序,但是总是有错。我的代码做了一些修改,即如果数组长度不是2^n,那么我们就将它改造成2^n长度的数组,多出来的部分填充INT_MAX或者INT_MIN,这样的话就不会影响排序结果啦~

 

posted @ 2014-04-06 23:01  zmt0429  阅读(3126)  评论(0编辑  收藏  举报