#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