请求想法 - 如何对包含许多行和3列的2d数组进行排序,从而维护数据行

时间:2014-12-28 07:55:47

标签: c++ arrays sorting

我在按字符位置扫描MIT Meep控制文件到令牌方面取得了进展。我现在有一个nx3整数数组,其中3列标识:

  • 角色位置
  • 令牌标识符
  • 令牌长度

除非他们处于“找到”顺序,而不是输入顺序。我注意到,字符位置可以变得非常大,很容易变成数千个(即数千行),而令牌标识符和令牌长度都低于100。

我需要按字母位置按递增顺序对nx3数组进行排序,而不会丢失其他两列。我已经研究过,答案似乎是编写一些实现冒泡排序或其他类似算法的代码。

是否有一个函数是C ++可以对数组的第一列中的条目进行排序而不会丢失相关的行条目?我的一些测试控制文件导致生成一个如下所示的数组:

380  2  1
401  2  1
441  2  1
442  2  1
178  4  13
178  18  7
0  26  5
59  26  5
218  26  5
330  26  5
382  26  5
23  32  5
80  32  5
142  32  5
238  32  5
256  32  5
353  32  5
74  38  5
232  38  5
347  38  5
403  44  4

4 个答案:

答案 0 :(得分:1)

可能的做法是将您的行定义为结构{a,b,c},比较' a'字段然后使用编译器的结构分配功能来交换结构(实际上交换行)。

typedef struct ROW {
    int a, b, c;
};
struct ROW A, B;
...
if (A.a > B.a) {
    struct ROW tmp = A; A = B; B = tmp;
}

这有帮助吗?

答案 1 :(得分:1)

您应该将每个条目包装在具有三个字段的结构中,并定义基于第一个字段的值的比较:

struct Entry {
    int loc, ident, length;
    Entry(int loc, int ident, int length)
      : loc(loc), ident(ident), length(length)
    {}

    bool operator<(const Entry& other) const {
        return loc < other.loc;
    }
};

之后,您可以使用标准的sort函数

std::vector<Entry> data;
// ... fill the vector ...
std::sort(data.begin(), data.end());

如果已经将数组作为int data[][3]给出,那么事情会更烦人,我可能会手动内联shell-metzener排序:

for (int m=n>>1; m>0; m>>=1) {
    for (int j=0; j<n-m; j++) {
        for (int i=j; i>=0 && data[i][0]>data[i+m][0]; i-=m) {
            std::swap(data[i][0], data[i+m][0]);
            std::swap(data[i][1], data[i+m][1]);
            std::swap(data[i][2], data[i+m][2]);
        }
    }
}

对于一般情况,这是一个不错的排序算法,它只是三行代码。

答案 2 :(得分:0)

typedef struct row_head 
{
int char_loc;
int token_index;
};

vector<row_head> heads;
vector<int> token_id;
vector<int> token_length;

用于排序的变量头将使用相应的索引来访问数据。例如,在上述数据集中,前5个元素被认为是简单的。 排序前:

{380,0}  5 1

{401,1}  8  1

{441,2}  9  1

{442 ,3} 10  2

{178 ,4} 4  1

在头部排序后,数据看起来像这样:

{178,4}

{380,0}

{401,1}

{441,2}

{442,3}

实际令牌数据保持不变:

5  1

8  1

9  1

10  2

4  1

答案 3 :(得分:0)

我花了一天时间试图建造一个结构。不幸的是,我的c ++知识 - 经验不能胜任任务。我无法得到任何东西来编译。所以我采用了旧的Fortran方式,并使用此代码来完成我需要的工作。

代码臃肿?最有可能来自标题。运行?循环遍历整个长数据流超过两次。哦,好吧,它可以工作,但如果我可以使结构工作,我会改变它,或至少做一个基准。

#include <algorithm>    // std::sort
#include <sstream>      // std::istringstream
#include <vector>
#include <iostream>     // std::cout
#include <string>
#include <stdio.h>      // sprintf
using namespace std;

int main() {

std::vector<std::string> data(512);
int length = 8;
size_t arat[length];
int arid[length];
int arlen[length];
int n ;
int i ;
char buffer [17];

arat[0]=     0 ; arid[0] = 1;  arlen[0] = 1;
arat[1]=   418 ; arid[1] = 1;  arlen[1] = 1;
arat[2]=    57 ; arid[2] = 2;  arlen[2] = 1;
arat[3]=   442 ; arid[3] = 2;  arlen[3] = 91;
arat[4]=   178 ; arid[4] = 1;  arlen[4] = 1;
arat[5]= 178632 ; arid[5] =180;  arlen[5] = 226;
arat[6]=     0 ; arid[6] =26;  arlen[6] = 5;
arat[7]=    59 ; arid[7] =26;  arlen[7] = 5;
cout << '\n';
i = 0; 
while(i<length){
n=sprintf (buffer," %*lu  %*d  %*d", 6,arat[i], 3,arid[i], 3,arlen[i]);
if(n < 0) break;
cout << buffer ; data[i] = buffer; cout << data[i] <<'\n'; i++;}
cout << '\n';
std::sort (data.begin(), data.begin()+8); // sort data 0 thru 7, not 8.

i = 0;
while (i < length) {cout << data[i] << '\n';i++;}

cout << '\n';
i = 0;
while (i < length) {
std::istringstream iss (data[i]);
iss >> arat[i] ;        // pick off the first number
iss >> arid[i] ;        // pick off the next number
iss >> arlen[i] ;       // pick off the next number after that.
cout << " size_t value of arat[i] = "<< arat[i] << " int arid[i] = "<<arid[i]
    << " int arlen[i] "<< arlen[i]<<'\n';
 i++; }
cout << '\n';
return 0;
}

所以这不是我想要的答案。