请求想法 - 如何对具有多行和 3 列的 2d 数组进行排序,维护数据行

Request ideas- How to sort a 2d array with many rows and 3 columns, maintaining data rows

本文关键字:数组 2d 列的 排序 数据 维护 请求      更新时间:2023-10-16

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

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

除了它们按"找到"顺序,而不是按输入顺序排列。我注意到字符位置可能会变得非常大,很容易进入数千行的 10(即数千行),而令牌标识符和令牌长度都低于 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

一种可能性是将行定义为结构体{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;
}

这有帮助吗?

应将

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

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]);
        }
    }
}

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

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

我花了一天时间试图建立一个结构。不幸的是,我的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;
}

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