【问题标题】:Creating a sparse matrix using linked lists in C在 C 中使用链表创建稀疏矩阵
【发布时间】:2015-01-17 14:03:36
【问题描述】:

我有一个任务是创建两个稀疏矩阵(A 和 B),然后将它们添加到第三个稀疏矩阵(C)中。我已经用向量完成了它(接收两个稀疏向量并将它们添加到第三个)所以我决定使用一系列向量来表示矩阵会更容易。将来,我可能需要在没有向量但使用实际矩阵的情况下执行此操作(我什至有一个将数字插入稀疏矩阵的函数的伪代码),所以请理解 为什么 我'我问这一切,即使下面的代码有点工作。

因为它是一个矩阵,所以它有两个指针数组,分别是行数组和列数组。数组的每个单元都指向各自的行/列。如下图:

作为一个稀疏矩阵,其中有零,您会看到这些箭头,因为那些带有零的节点不存在。

为了简化问题,我更喜欢只处理行数组,如图所示,这些行指向每个新行的头部。假设每一行都是一个向量C(就像我上面说的,我想用一系列向量来表示矩阵)。

这是我构建的所有链表函数的代码:

typedef struct List_node
{
    int key;
    int i,j;
    struct List_node *next;
}List_node;

typedef struct List
{
    List_node *head;
}List;

List *create_list()
{
    List *list = (List*)malloc(sizeof(List));
    list->head = NULL;
    return list;
}

void insert_first(List_node *x, List *list)
{
    x->next = list->head;
    list->head = x;
}

void insert(List_node *x, List_node *y)
{
    x->next = y->next;
    y->next = x;
}

List_node *mk_node(int data, int row, int col)
{
    List_node *node = (List_node *)malloc(sizeof(List_node));
    node->key = data;
    node->i = row + 1;
    node->j = col + 1;
    return node;
}

void delete_list(List *list) 
{
    List_node *node, *temp;
    node = list->head;
    while (node != NULL) 
    {
        temp = node->next;
        free(node);
        node = temp;
    }
    free(list);
}

void print_list(List *list, char name)
{
    List_node *p;
    p = list->head;
    printf("\nThe linked list %c consists of: ",name);
    while (p != NULL)
    {
        printf("%d(i = %d) (j = %d) ", p->key, p->i, p->j);
        p = p->next;
    }
    printf("\n");
}

这是创建向量的代码:

List *Create_vector (List *A, List *B, int i, int m)
{
    int l,flag = 0;
    List *C;
    List_node *node=NULL, *next, *Pointer_A, *Pointer_B;
    C = create_list();
    Pointer_A = A->head;
    Pointer_B = B->head;

    for (l = 0; l<m; l++)
    {
        if ((Pointer_A->key + Pointer_B->key) != 0)
        {
            if (flag == 0)
            {
                node = mk_node(Pointer_A->key + Pointer_B->key, i,l);
                insert_first(node, C);
                flag = 1;
            }
            else
            {
                next = mk_node(Pointer_A->key + Pointer_B->key, i,l);
                insert(next, node);
                node = next;
            }
        }
        Pointer_A = Pointer_A->next;
        Pointer_B = Pointer_B->next;
    }
    return C;
}

这是主程序:

void main()
{
    List_node *Row_A, *Row_B, *Row_C;

    List *A, *B, *C;
    List_node *node, *next;
    int data, m,n,l;
    printf("Enter list row\n");
    scanf("%d", &m);

    Row_A = (List_node*)malloc(sizeof(int)*(m));
    Row_B = (List_node*)malloc(sizeof(int)*(m));
    Row_C = (List_node*)malloc(sizeof(int)*(m));

    printf("Enter list columns\n");
    scanf("%d", &n);

    for (int i=0; i<m; i++)
    {

        A = create_list();
        B = create_list();

        printf("\nInsert first number into A\n");
        scanf("%d", &data);
        node = mk_node(data, i,0);
        insert_first(node, A);
        for (l = 1; l<n; l++)
        {
            printf("Now insert the rest of the numbers\n");
            scanf("%d", &data);
            next = mk_node(data, i,l);
            insert(next, node);
            node = next;
        }
        print_list(A,'A');

        printf("\nInsert first number into B\n");
        scanf("%d", &data);
        node = mk_node(data,i,0);
        insert_first(node, B);
        for (l = 1; l<n; l++)
        {
            printf("Now insert the rest of the numbers\n");
            scanf("%d", &data);
            next = mk_node(data, i,l);
            insert(next, node);
            node = next;
        }
        print_list(B,'B');

        C = Create_vector(A,B,i,n);
    }
    getchar(); getchar();
}

希望你能走到这一步。所以我的问题是:

  1. 我不确定如何创建我需要的指针数组,它们是 Row_A、Row_B、Row_C。意思是,如果每个单元格都指向向量的头部 - 我如何定义数组?作为列表?列出节点?如何使数组的每个单元格都指向每个向量的头部?

  2. 每次执行 for 循环时都会覆盖列表 C。我看到可以保留每个向量 C 并将其放入矩阵的唯一方法是使每个数组单元指向每个向量的头部,这使我们回到问题 #1。真的吗?我该怎么做?

非常感谢。

【问题讨论】:

    标签: c sparse-matrix


    【解决方案1】:

    一些可以帮助您入门的观察:

    • 您可以像创建动态数组Row_A 一样创建磁头列表,依此类推。这些头列表不应该是独立的数据结构。它们应该是Matrix 结构的一部分,就像headList 结构的一部分一样。头数组的分配应该是其创建者函数create_matrix的一部分。

    • 每个Matrix 存储自己的磁头列表这一事实也是覆盖C 的解决方案:而不是一遍又一遍地分配给C,而是分配给C-&gt;head[i]AB 也是如此。描述矩阵的所有日期都应封装在一个结构中,以便将所有内容整齐地存储在一起。

    • 目前,您将矩阵表示为行列表。这对于打印和矩阵加法来说很好,但是一旦你开始乘法,你还需要列头。然后,您的节点结构必须准备好有两个指针,如草图所示:一个指向行中的下一个元素(例如right),一个指向列中的下一个元素(below)。

    • 您的矩阵不是稀疏的。例如,添加两个列表的代码(不应称为 create_vector;选择更具表现力的名称)应检查与节点关联的索引,以便可以跳过零条目。

    • 您应该将列表或矩阵的维度存储在结构中。这不是遍历列表所必需的,但它允许快速检查操作是否合法。例如,您只能添加相同维度的矩阵。

    例如:

    typedef struct Matrix Matrix;
    typedef struct Matrixnode Matrixnode;
    
    struct Matrix {
        int n, m;
        Matrixnode *row;
        Matrixnode *col;
    };
    
    Matrix *create_matrix(int n, int m)
    {
        Matrix *mx = malloc(sizeof(*mx));
    
        mx->n = n;
        mx->m = m;
    
        mx->row = malloc(m * sizeof(*m->row));
        mx->col = malloc(n * sizeof(*n->col));
    
        return mx;
    }
    
    Matrix *matrix_add(const Matrix *a, const Matrix *b)
    {
        assert(a->m == b->m);
        assert(a->n == b->n);
    
        Matrix *c = create_matrix(a->n, a->m);
    
        for (int i = 0; i < c->m; i++) {
            c->row[i] = row_add(a->row[i], b->row[i]);
        }
    
        return c;
    }
    

    这是如何制作行向量数组的粗略草图。 (我创建了一个col 数组,但不要使用它。添加矩阵时,您还必须注意保持列指针一致。)

    【讨论】:

    • 谢谢。您能否详细说明第一个和第二个观察结果,甚至可以在示例代码中说明您的意思?这真的很有帮助,因为我不确定我理解你的意思。另外,关于您的第 4 次观察,请注意 if ((Pointer_A-&gt;key + Pointer_B-&gt;key) != 0) 函数中的 create_vector 行确保跳过零条目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 2012-01-10
    • 2017-03-31
    • 1970-01-01
    • 2018-12-14
    • 2016-10-23
    相关资源
    最近更新 更多