【问题标题】:Problem when inserting in a Sparse Matrix插入稀疏矩阵时出现问题
【发布时间】:2020-07-02 01:23:41
【问题描述】:

我必须使用 3 个动态数组(索引从 0 开始)在 C++ 中实现 CSR 矩阵数据结构,但我遇到了困难。所以我必须实现2个功能:

1) modify(int i, int j, TElem e) - 将 (i,j) 的值修改为 e 或添加 if(如果它不存在)或如果 e 为 null 则删除它。

2) element(int i, int j) const - 返回在 (i,j) 上找到的值

我想用下一种方式测试我的代码:

Matrix m(10, 10);
    for (int j = 0; j < m.nrColumns(); j++) {
        m.modify(4, j, 3);
    }                                                             
    for (int i = 0; i < m.nrLines(); i++)
        for (int j = 0; j < m.nrColumns(); j++)
            if (i == 4)
                assert(m.element(i, j) == 3);
            else
                assert(m.element(i, j) == NULL_TELEM);

我惊讶地发现 m.element(4,j) 在 (0,8) 范围内的 j 将为 0,而对于 j=9 则只有 3。

这是我对 element(int i, int j) 的实现:

    int currCol;
    for (int pos = this->lines[i]; pos < this->lines[i+1]; pos++) {
        currCol = this->columns[pos];
        if (currCol == j)
            return this->values[pos];
        else if (currCol > j)
            break;
    }
    return NULL_TELEM;

构造函数如下所示:

Matrix::Matrix(int nrLines, int nrCols) {
    if (nrLines <= 0 || nrCols <= 0)
        throw exception();
    this->nr_lines = nrLines;
    this->nr_columns = nrCols;
    this->values = new TElem[1000];
    this->values_capacity = 1;
    this->values_size = 0; 
    this->lines = new int[nrLines + 1];
    this->columns = new TElem[1000];
    this->columns_capacity = 1;
    this->columns_size = 0; 
    for (int i = 0; i <= nrLines; i++)
        this->lines[i] = NULL_TELEM;
}

这是“修改”方法:

TElem Matrix::modify(int i, int j, TElem e) {
    if (i < 0 || j < 0 || i >= this->nr_lines || j >= nr_columns)
        throw exception();
    int pos = this->lines[i];
    int currCol = 0;
    for (; pos < this->lines[i + 1]; i++) {
        currCol = this->columns[pos];
        if (currCol >= j)
            break;
    }
    if (currCol != j) {
        if (!(e == 0)) 
            add(pos, i, j, e);
    }
    else if (e == 0)
        remove(pos, i);
    else
        this->values[pos] = e;
    return NULL_TELEM;
}

这是插入方法:

void Matrix::add(int index, int line, int column, TElem value)
{
    this->columns_size++;
    this->values_size++;
    for (int i = this->columns_size; i >= index + 1; i--) {
        this->columns[i] = this->columns[i - 1];
        this->values[i] = this->values[i - 1];
    }
    this->columns[index] = column;
    this->values[index] = value;
    for (int i = line + 1; i <= this->nr_lines; i++)
        this->lines[i]++;
}

有人可以帮帮我吗?我不知道为什么会发生这种情况,我现在真的需要完成这个实现。看到这些位置的值为 0,这很奇怪。

所以下一个测试以下一个方式开始,我得到一个内存访问冲突:

Matrix m(200, 300);
    for (int i = m.nrLines() / 2; i < m.nrLines(); i++) {
        for (int j = 0; j <= m.nrColumns() / 2; j++)
        {
            int v1 = j;
            int v2 = m.nrColumns() - v1 - 1;
            if (i % 2 == 0 && v1 % 2 == 0)
                m.modify(i, v1, i * v1);
            else
                if (v1 % 3 == 0)
                    m.modify(i, v1, i + v1);
            if (i % 2 == 0 && v2 % 2 == 0)
                m.modify(i, v2, i * v2);
            else
                if (v2 % 3 == 0)
                    m.modify(i, v2, i + v2);
        }

在 currCol = this->column[pos]; 方法“修改”中抛出错误

如果我查看调试器,它看起来像:i=168,lines[i]=-842150451,lines[i+1]=10180,pos=-842150451。

有人知道为什么会这样吗?

【问题讨论】:

    标签: c++ algorithm matrix data-structures sparse-matrix


    【解决方案1】:

    您的代码有两个小错误。

    当您尝试在modify 中查找插入位置时,您会遍历该行中的非空元素:

    int currCol = 0;
    
    for (; pos < this->lines[i + 1]; i++) {
        currCol = this->columns[pos];
        if (currCol >= j)
            break;
    }
    

    在这里,您必须在每次迭代中更新pos++,而不是i++

    将元素插入第 0 列时发生第二个错误。currCol 将为零,但您添加新元素的条件是

    if (currCol != j) {
        if (!(e == 0)) 
            add(pos, i, j, e);
    }
    

    但是j 也是零,所以不会插入任何内容。您可以从不存在的列开始解决此问题:

    int currCol = -1;
    

    【讨论】:

    • 非常感谢!现在它在该测试中完美运行。现在我有另一个测试,我得到一个内存访问冲突错误......我不知道为什么会发生这种情况。我将立即编辑帖子并发布。
    • 我很高兴它现在可以工作,但请不要在事后编辑问题。 SO 应该是问题和答案的存储库,而不是讨论。通过编辑问题,我的分析器现在仅指问题的一部分。如果您遇到其他问题,我认为您应该提出一个新问题。
    • 另一方面,您还可以尝试通过在每个步骤之后打印数组的内容来找出发生了什么。矩阵只有 10x10,你可以看到发生了什么。 (奇怪的索引看起来好像你已经从有效数组限制之外交换了一些垃圾。)
    • 好吧,减少测试。在较小的矩阵上很可能会发生相同的错误。不要太靠近课程脚本。您必须尝试一下!
    • 它在 20x30 上完美运行,但在 200x300 上应该表现相同。没有区别。我得到了内存访问违规。此外,我已将向量的大小更改为 [1000],但这不是问题。
    猜你喜欢
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2014-09-27
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    • 2018-01-19
    相关资源
    最近更新 更多