在处理大规模但元素稀少的矩阵(即稀疏矩阵)时,传统的二维数组会浪费大量内存。为了解决这个问题,C语言十字链表提供了一种高效、灵活的存储方式。本文将从零开始,手把手教你理解并实现十字链表,即使是编程小白也能轻松掌握!
十字链表(Orthogonal List)是一种用于表示稀疏矩阵的链式存储结构。它通过将非零元素组织成“行链表”和“列链表”的交叉形式,既节省空间,又便于按行或按列遍历。
如上图所示,每个非零元素用一个节点表示,节点包含以下信息:
首先,我们需要定义十字链表的节点结构。在C语言中,可以这样写:
typedef struct OLNode { int row, col; // 行号和列号 int value; // 非零元素的值 struct OLNode *right; // 指向同行的下一个非零元素 struct OLNode *down; // 指向同列的下一个非零元素} OLNode;typedef struct { OLNode **rowHead; // 行头指针数组 OLNode **colHead; // 列头指针数组 int rows, cols, nums; // 矩阵行数、列数、非零元素个数} CrossList; 接下来,我们实现一个函数来初始化十字链表。假设我们要创建一个 m 行 n 列的稀疏矩阵:
#include <stdio.h>#include <stdlib.h>// 初始化十字链表int CreateCrossList(CrossList *M, int m, int n) { M->rows = m; M->cols = n; M->nums = 0; // 分配行头和列头指针数组 M->rowHead = (OLNode**)malloc(m * sizeof(OLNode*)); M->colHead = (OLNode**)malloc(n * sizeof(OLNode*)); if (!M->rowHead || !M->colHead) return 0; // 初始化所有头指针为 NULL for (int i = 0; i < m; i++) M->rowHead[i] = NULL; for (int j = 0; j < n; j++) M->colHead[j] = NULL; return 1;} 当我们读取到一个非零元素 (i, j, value) 时,需要将其插入到对应的行链表和列链表中。注意要保持链表有序(通常按列号或行号递增):
// 插入一个非零元素int InsertElement(CrossList *M, int i, int j, int value) { if (i < 0 || i >= M->rows || j < 0 || j >= M->cols) return 0; OLNode *newNode = (OLNode*)malloc(sizeof(OLNode)); newNode->row = i; newNode->col = j; newNode->value = value; // 插入到行链表(按列号递增) OLNode *p = M->rowHead[i]; OLNode *prev = NULL; while (p && p->col < j) { prev = p; p = p->right; } if (prev == NULL) { newNode->right = M->rowHead[i]; M->rowHead[i] = newNode; } else { newNode->right = p; prev->right = newNode; } // 插入到列链表(按行号递增) p = M->colHead[j]; prev = NULL; while (p && p->row < i) { prev = p; p = p->down; } if (prev == NULL) { newNode->down = M->colHead[j]; M->colHead[j] = newNode; } else { newNode->down = p; prev->down = newNode; } M->nums++; return 1;} 为了验证我们的实现是否正确,可以编写一个打印函数:
void PrintCrossList(CrossList *M) { printf("稀疏矩阵 (%d x %d),非零元素个数:%d\n", M->rows, M->cols, M->nums); for (int i = 0; i < M->rows; i++) { OLNode *p = M->rowHead[i]; while (p) { printf("(%d, %d) = %d\n", p->row, p->col, p->value); p = p->right; } }} 下面是一个完整的测试程序:
int main() { CrossList M; CreateCrossList(&M, 3, 4); // 创建 3x4 的稀疏矩阵 // 插入非零元素 InsertElement(&M, 0, 1, 5); InsertElement(&M, 1, 2, 8); InsertElement(&M, 2, 0, 3); InsertElement(&M, 2, 3, 6); PrintCrossList(&M); return 0;} 通过本文,你已经掌握了C语言十字链表的基本原理和实现方法。这种结构特别适用于稀疏矩阵存储,能显著减少内存占用,并支持高效的行列遍历。无论你是学习C语言数据结构的学生,还是需要优化矩阵运算的开发者,掌握十字链表实现都将为你带来巨大优势。
希望这篇教程对你有帮助!动手试试吧,实践是掌握数据结构的最佳方式。
本文由主机测评网于2025-12-12发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025126683.html