• 双调排序算法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,这样的话就不会影响排序结果啦~

  • 相关阅读:
    Spring Boot 打包插件,真是太有用了!
    java高级应用:线程池全面解析
    漫画:HTTP 协议极简教程,傻瓜都能看懂!
    Tomcat 连接数与线程池详解
    Intellij IDEA Debug 调试技巧
    Java 程序员必须掌握的 5 个注解!
    如何优雅地终止一个线程?
    springmvc实现REST中的GET、POST、PUT和DELETE
    @Resource 和 @Autowired注解的异同
    SpringMVC的各种参数绑定方式
  • 原文地址:https://www.cnblogs.com/zmt0429/p/3649493.html
Copyright © 2020-2023  润新知