Featured image of post 我是如何学会十字链表的

我是如何学会十字链表的

本库包含作业答案,请确保阅读并完全同意重要声明

题目来源

6-4 稀疏矩阵的链式结构构建
Author:陈越

例题AC代码

题目

请设计两个函数,一个根据读入的“行号 列号 元素值”三元组构建十字链表表示的稀疏矩阵,另一个从矩阵中查询指定行列上元素的值。

函数接口定义

1
2
SparseMatrix BuildSparseMatrix( int n_row, int n_col, int n );
ElemSet GetElem( SparseMatrix matrix, int row, int col );

其中稀疏矩阵 SparseMatrix 的十字链表结构定义如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
typedef enum { head, term } NodeTag;
struct TermNode { /* 非零元素结点 */
    int row, col; /* 行号,列号 */
    ElemSet value;/* 元素值 */
};
typedef struct SparseMatrixNode *Position; /* 结点位置是指针 */
typedef Position SparseMatrix;
struct SparseMatrixNode {
    Position down;            /* 向下的列指针 */ 
    Position right;           /* 向右的行指针 */
    NodeTag tag;              /* 结点标记 */
    union {
        Position next;        /* 头结点链接指针 */
        struct TermNode term; /* 非零元素结点 */
    } u_region;               /* head和term的共用体 */
};

函数接口定义中,ElemSet 是用户定义的数据类型,这里默认为 int。函数 BuildSparseMatrix 的功能是创建 n_row 行、n_col 列、有 n 个非零元素的矩阵,非零元素按行优先、列号增序输入。注意:行、列号从 0 开始。函数 GetElem 的功能是返回矩阵 matrix 中第 row 行、第 col 列的元素值。若输入的行、列号非法,则在一行中输出 ERROR 并返回 0。

裁判测试程序样例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include <stdlib.h>

typedef int ElemSet;
typedef enum { head, term } NodeTag;
struct TermNode { /* 非零元素结点 */
    int row, col; /* 行号,列号 */
    ElemSet value;/* 元素值 */
};
typedef struct SparseMatrixNode *Position; /* 结点位置是指针 */
typedef Position SparseMatrix;
struct SparseMatrixNode {
    Position down;            /* 向下的列指针 */ 
    Position right;           /* 向右的行指针 */
    NodeTag tag;              /* 结点标记 */
    union {
        Position next;        /* 头结点链接指针 */
        struct TermNode term; /* 非零元素结点 */
    } u_region;               /* head和term的共用体 */
};

SparseMatrix BuildSparseMatrix( int n_row, int n_col, int n );
ElemSet GetElem( SparseMatrix matrix, int row, int col );

int main(void)
{
    SparseMatrix matrix;
    int n_row, n_col, n;
    int m, row, col, i;
    
    scanf("%d %d %d", &n_row, &n_col, &n);
    matrix = BuildSparseMatrix(n_row, n_col, n);
    scanf("%d", &m);
    for (i=0; i<m; i++) {
        scanf("%d %d", &row, &col);
        printf("%d\n", GetElem(matrix, row, col));
    }
    
    return 0;
}
/* 你的代码将被嵌在这里 */

输入样例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
4 5 7
0 0 18
0 3 2
1 1 27
2 3 -4
3 0 23
3 1 -1
3 4 12
6
0 0
3 4
1 1
2 3
1 4
2 2

输出样例:

1
2
3
4
5
6
18
12
27
-4
0
0

语法知识补充

什么是 enum { head, term }

定义一个枚举类型,需要使用 enum 关键字,后面跟着枚举类型的名称,以及用大括号 {} 括起来的一组枚举常量。每个枚举常量可以用一个标识符来表示,也可以为它们指定一个整数值,如果没有指定,那么默认从 0 开始递增。1

— C enum(枚举) | 菜鸟教程

下面给出题设代码和题设代码的调用,读者可以自行前往资料1学习 enum 的使用。

题设代码

1
typedef enum { head, term } NodeTag;

例示调用

1
2
struct SparseMatrixNode matrix;
matrix.tag = term; //设置matrix为非零节点

什么是 union

The Union is a user-defined data type in C language that can contain elements of the different data types just like structure. But unlike structures, all the members in the C union are stored in the same memory location. Due to this, only one member can store data at the given instance.2

— C Unions - GeeksforGeeks

通俗地说,union 是一个可以包含多种不同数据类型的数据的结构,每个 union 对象只能存放一个成员。

1
2
3
4
union {
        Position next;        /* 头结点链接指针 */
        struct TermNode term; /* 非零元素结点 */
    } u_region;               /* head和term的共用体 */

以题目中给出的代码为例子,当 SparseMatrixNode 是头节点时,即 matrix->tag 值为 head 时,martix->u_region 存放 next 成员;当 SparseMatrixNode 是非零节点时,即 matrix->tag 值为 term 时,martix->u_region 存放 term 成员。

数据结构学习

前置知识

  1. 链表的定义和代码实现3
  2. 邻接表的定义和代码实现4
  3. 逆邻接表的定义5
  4. 图论基础&离散数学基础

十字链表

例题AC代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* 初始化一个空十字链表 */
SparseMatrix InitMatrix(int n_row, int n_col){
    SparseMatrix matrix = (SparseMatrix)malloc(sizeof(struct SparseMatrixNode));
    matrix->down = (SparseMatrix)malloc(n_row * sizeof(struct SparseMatrixNode));
    matrix->right = (SparseMatrix)malloc(n_col * sizeof(struct SparseMatrixNode));

    for(int i = 0; i < n_row; i++){
        matrix->down[i].tag = head;
        matrix->down[i].down = &matrix->down[i];
        matrix->down[i].right = &matrix->down[i];
    }

    for(int i = 0; i < n_col; i++){
        matrix->right[i].tag = head;
        matrix->right[i].down = &matrix->right[i];
        matrix->right[i].right = &matrix->right[i];
    }

    matrix->tag = head;
    return matrix;
}

/* 对于每个非零元素,初始化一个非零元素结点 */
SparseMatrix InitNode(int row, int col, int value){
    SparseMatrix node = (SparseMatrix)malloc(sizeof(struct SparseMatrixNode));
    node->u_region.term.row = row;
    node->u_region.term.col = col;
    node->u_region.term.value = value;
    node->right = NULL;
    node->down = NULL;
    node->tag = term;
    return node;
}

SparseMatrix BuildSparseMatrix(int n_row, int n_col, int n){
    SparseMatrix matrix = InitMatrix(n_row, n_col);
    int row, col;
    ElemSet value;

    for(int i = 0; i < n; i++){
        scanf("%d %d %d", &row, &col, &value);

        if(row < 0 || row >= n_row || col < 0 || col >= n_col){
            printf("ERROR");
            continue;
        }

        SparseMatrix node = InitNode(row, col, value);

        SparseMatrix rowHead = &matrix->down[row];
        SparseMatrix p = rowHead;
        while(p->right != rowHead && p->right->u_region.term.col < col){
            p = p->right;
        }
        node->right = p->right;
        p->right = node;

        SparseMatrix colHead = &matrix->right[col];
        p = colHead;
        while(p->down != colHead && p->down->u_region.term.row < row){
            p = p->down;
        }
        node->down = p->down;
        p->down = node;
    }
    return matrix;
}

ElemSet GetElem(SparseMatrix matrix, int row, int col){
    if(row < 0 || col < 0 || matrix->down[row].down == NULL || matrix->right[col].right == NULL){
        printf("ERROR\n");
        return 0;
    }

    SparseMatrix rowHead = &matrix->down[row];
    SparseMatrix p = rowHead->right;

    while(p != rowHead && p->u_region.term.col < col){
        p = p->right;
    }

    if(p != rowHead && p->u_region.term.col == col){
        return p->u_region.term.value;
    }

    return 0;
}
使用 Hugo 构建
主题 StackJimmy 设计