分段双调排序实现

本文介绍了一种名为分段双调排序的算法,详细阐述了双调序列和Batcher定理,并提供了两种实现方式:递归实现和非递归实现。递归实现基于双调序列的概念,通过递归将序列分成递增和递减部分,然后合并。非递归实现利用Batcher定理,避免了递归和额外的函数调用,同时确保了内存效率和并行性。文章还讨论了算法的时间复杂度和在处理包含NaN值时的鲁棒性。
摘要由CSDN通过智能技术生成
最终代码
#include 
   
   
    
       
#include 
    
    
     
      
#include 
     
     
      
        
#include
      
      
       
        
using namespace std; 

void segmentedBitonicSort(float* data, int* seg_id, int* seg_start, int n, int m){  
        float MAXNUM = 3.402823E38f;
        //float Nnum[100000] = {MAXNUM}; 
        if(n <= 0 || m <= 0||m>n)  
        {  
            return;  
        }  
        if(!(seg_start[m]==n && seg_id[n-1]==(m-1)))  
        {  
            perror("input error!");  
            return;  
        }  
        int step=0;  
        for(int g=0;g
       
       
         << 1; } vector 
        
          Nnum(len); for(int i=0; i 
         
           <= len;k = k<<1) {//2,4,8,到2次幂长度 for (j = k >> 1;j>0; j = j >> 1) {//以k为单位,内部形成双调序列 for (i = 0;i 
          
            i){ //判断是否在子双调序列的升序部分 if ((i&k) == 0 && (Nnum[i] > Nnum[ixj]||Nnum[ixj]!=Nnum[ixj])){//i与k与运算,判断前部分升序 temp = Nnum[i]; Nnum[i] = Nnum[ixj]; Nnum[ixj] = temp; } if ((i&k) != 0 && (Nnum[i] < Nnum[ixj]||Nnum[i]!=Nnum[i])) {i与k与运算,判断后部分降序 temp = Nnum[i]; Nnum[i] = Nnum[ixj]; Nnum[ixj] = temp; } } } } } for(int i=0; i 
            
           
          
         
       
      
      
     
     
    
    
   
   

最终结果是:绝对鲁邦和内存管理失败,其他正确。



问题说明:


***********************

给出分成m段 的n个浮点数,输入数据已按段号有序,但每段内部 无序。用C/C++ 编写一个分段双调排序(Bitonic sort)函数,对每一段内部的浮点数进行排序,但 不要改变段间的位置。

接口方式:

***********************

void segmentedBitonicSort(float* data, int* seg_id, int* seg_start, int n, int m);

输入数据中,data包含需要分段排序的n个float值,seg_id给出data中n个元素各 自所在的 段编号。seg_start共有m+1个元素,前m个分别给 出0..m-1共m个段的起 始位置,seg_start[m]保证等于n。

seg_id中的元素保证单调不下降,即对任意的i<j,seg_id[i]<=seg_id[j]。 seg_id所有元 素均在0到m-1范围内。

输出结果覆盖data,保证每一段内排序,但不改变段间元素的顺序。

注意:

***********************

1、必须使用双调排序算法进行排序。

2、可以直接使用从网上下载的双调排序代码,但须注明出处。

样例输入:

***********************

float data[5]={0.8, 0.2, 0.4, 0.6, 0.5};

int seg_id[5]={0,   0,   1,   1,   1}

int seg_start[3]={0,2,5};

int n=5;

int m=2;

样例输出:

***********************

float data[5]={0.2, 0.8, 0.4, 0.5, 0.6};

加分挑战(非必需):

***********************

1、不递归:segmentedBitonicSort函数及其所调用的任何其他函数都不得直接或 间接地进行递归。

2、不调用函数:segmentedBitonicSort不调用除标准库函数外的任何其他函数。

3、内存高效:segmentedBitonicSort及其所调用的任何其他函数都不得进行动态 内存分配,包括malloc、new和静态定义的STL容器。

4、可并行:segmentedBitonicSort涉及到的所有时间复杂度O(n)以上的代码都写 在for循 环中,而且每个这样的for循环内部的循环顺序可 以任意改变,不影响程 序结果。注:自己测试时可以用rand()决定循环顺序。

5、不需内存:segmentedBitonicSort不调用任何函数(包括C/C++标准库函数), 不使用全局变量,所有局部变量都是int、float或指针类 型,C++程序不使用new 关键字。

6、绝对鲁棒:在输入数据中包含NaN时(例如sqrt(-1.f)),保证除NaN以外 的数 据正确排序,NaN的个数保持不变。

你的程序每满足以上的一个条件都可以获得额外的加分。

应提交的结果:

***********************

a) 算法描述;

b) 尝试过和完成了的加分挑战;

c) 可以独立运行的源代码;

d) 测试数据;

e) 性能分析;

f) 测试的起始和完成时间以及实际使用的时间。

提示:

***********************

1. 利用好网上资源。

2. 尽量利用输入中的冗余信息。

3. 利用好位操作。

***************************************************************************************************************************************************************************************

a.算法描述

双调排序主要有两个重要概念:双调序列和白扯定理>_<(Batcher定理)

1.双调序列:(Bitonic Sequence)是指由一个非严格增序列X和非严格减序列Y构成的序列,比如序列(23,10,8,3,5,7,11,78)。定义:一个序列a1,a2,…,an是双调序列(Bitonic Sequence),如果:(1)存在一个ak(1≤k≤n), 使得a1≥…≥ak≤…≤an成立;或者(2)序列能够循环移位满足条件(1)

2.Batcher定理:将任意一个长为2n的双调序列A分为等长的两半X和Y,将X中的元素与Y中的元素一一按原序比较,即a[i]与a[i+n](i<n)比较,将较大者放入MAX序列,较小者放入        MIN序列。则得到的MAX和MIN序列仍然是双调序列,并且MAX序列中的任意一个元素不小于MIN序列中的任意一个元素对于无序数组,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变成升序序列 ,至此算法完成。

//根据定理第一次实现(无附加条件的简单递归):
#include <stdlib.h>   
#include <iostream>  
using namespace std;  

 
    void SortDown(int , int);  
    void MergeUp(int, int);  
    void MergeDown(int, int);  
    void Exchange(int , int);  
    void SortUp(int, int);  
    const int MAXNUM = 99999999; //如果个数不为2的次幂个,要填充的数字  
    float *arr;
 

    void SortUp(int beg,int n)  
    {  
        if(n == 1)  
        return;  
      
        SortUp(beg,n / 2);//把前面的n/2个元素按递增排序  
        SortDown(beg + n / 2, n / 2);//把后面n/2个元素按递减排序  
        MergeUp(beg, n);//合并前面n/2个和后面n/2个数组。  
        return;  
    }  
      
    void SortDown(int beg,int n)//类似SortUp,只是按照递减排序数组从beg开始的n个元素  
    {  
        if(n == 1)  
            return;  
        SortUp(beg, n / 2); //把前面的n/2个元素按递增排序  
        SortDown(beg + n / 2, n / 2); //把后面n/2个元素按递减排序  
        MergeDown(beg, n); //合并前面n/2个和后面n/2个数组。  
    }  
      
      
    void MergeUp(int beg,int n)//按照从小到大的顺序合并  
    {  
        if(n == 1) return;  
        int halfN = n >> 1; //向右移一位等同于除以2  
      
        for(int i = beg; i < beg + halfN; i++)  
        {  
            if(arr[i] > arr[i + halfN])  
            Exchang

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值