使用C语言中的链表创建稀疏矩阵

使用C语言中的链表创建稀疏矩阵,c,sparse-matrix,C,Sparse Matrix,我有一个任务是创建两个稀疏矩阵(A和B),然后将它们相加到第三个稀疏矩阵(C)。我已经用向量做过了(接收两个稀疏向量并将它们添加到第三个向量中),所以我决定使用一系列向量来表示矩阵会更容易。将来,我可能需要不使用向量而使用实际矩阵(我甚至有一个函数的psuedo代码,它将一个数字插入稀疏矩阵),所以一定要理解为什么我要问所有这些,即使下面的代码有点起作用 因为它是一个矩阵,所以它有两个指针数组,即行数组和列数组。数组的每个单元格都指向相应的行/列。如下图所示: 作为一个稀疏矩阵,其中有零,您可

我有一个任务是创建两个稀疏矩阵(A和B),然后将它们相加到第三个稀疏矩阵(C)。我已经用向量做过了(接收两个稀疏向量并将它们添加到第三个向量中),所以我决定使用一系列向量来表示矩阵会更容易。将来,我可能需要不使用向量而使用实际矩阵(我甚至有一个函数的psuedo代码,它将一个数字插入稀疏矩阵),所以一定要理解为什么我要问所有这些,即使下面的代码有点起作用

因为它是一个矩阵,所以它有两个指针数组,即行数组和列数组。数组的每个单元格都指向相应的行/列。如下图所示:

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

为了简化问题,我宁愿只处理行数组,如图所示,这些行指向每一新行的头。假设每一行是一个向量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;
}
List*创建向量(List*A,List*B,int i,int m)
{
int l,flag=0;
清单*C;
List_node*node=NULL,*next,*Pointer_A,*Pointer_B;
C=创建_列表();
指针A=A->head;
指针B=B->head;
对于(l=0;lkey+指针\U B->键)!=0)
{
如果(标志==0)
{
node=mk_节点(指针A->key+指针B->key,i,l);
首先插入_(节点C);
flag=1;
}
其他的
{
next=mk_节点(指针A->键+指针B->键,i,l);
插入(下一步,节点);
节点=下一个;
}
}
指针A=指针A->next;
指针\u B=指针\u B->下一步;
}
返回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();
}
void main()
{
列表节点*行A、*行B、*行C;
名单*A、*B、*C;
列出_节点*节点,*下一步;
int数据,m,n,l;
printf(“输入列表行\n”);
scanf(“%d”、&m);
行A=(列表节点*)malloc(sizeof(int)*(m));
行B=(列表节点*)malloc(sizeof(int)*(m));
行C=(列表节点*)malloc(sizeof(int)*(m));
printf(“输入列表列\n”);
scanf(“%d”和“&n”);

对于(int i=0;i一些可能让您开始的观察:

  • 您可以按照创建动态数组的方式创建头列表。这些头列表不应该是独立的数据结构。它们应该是
    矩阵
    结构的一部分,就像
    列表
    结构的一部分一样。头数组的分配应该是其crea的一部分tor函数
    创建矩阵

  • 每个
    矩阵
    存储自己的头列表这一事实也是覆盖
    C
    的解决方案:要反复分配给
    C
    ,请分配给
    C->head[i]
    。同样,对于
    A
    B
    。描述矩阵的所有日期都应封装在一个结构中,以便将所有内容整齐地存储在一起

  • 此时,将矩阵表示为行列表。这对于打印和矩阵加法很好,但一旦进行乘法运算,还需要列标题。然后,节点结构必须准备好两个指针,如草图所示:一个指针用于行中的下一个元素(
    右侧
    ,例如)一个用于列中的下一个元素(

  • 矩阵不是稀疏的。例如,添加两个列表的代码(不应称为
    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;
}
typedef结构矩阵;
类型定义结构矩阵节点矩阵节点;
结构矩阵{
int n,m;
矩阵节点*行;
矩阵节点*col;
};
矩阵*创建矩阵(整数n,整数m)
{
矩阵*mx=malloc(sizeof(*mx));
mx->n=n;
mx->m=m;
mx->row=malloc(m*sizeof(*m->row));
mx->col=malloc(n*sizeof(*n->col));
返回mx;
}
矩阵*矩阵加(常数矩阵*a,常数矩阵*b)
{
断言(a->m==b->m);
断言(a->n==b->n);
矩阵*c=创建矩阵(a->n,a->m);
对于(int i=0;im;i++){
c->行[i]=行添加(a->行[i],b->行[i]);
}
返回c;
}

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

谢谢。你能详细说明第一个和第二个观察结果吗,甚至可以在示例代码中说明你的意思吗?这会很有帮助,因为我不确定我是否理解你的意思。另外,关于你的第四个观察结果,请注意,
如果((指针a->键+指针B->键)!=0)
create_vector
函数中,确保跳过零个条目。