[Data structure] Compressed storage of sparse matrix (triple table, cross-linked list) (C language)


A sparse matrix is ​​one in which most of the elements are zero. Intuitively, when the number of non-zero elements is less than 30% of the total elements, such a matrix is ​​a sparse matrix.

1. Triple table

1.1 Storage structure of triple table

The three-tuple table representation of a sparse matrix means that only non-zero elements are stored, and at the same time, the position information of the row number and column number of the non-zero element in the matrix is ​​stored.
triple structureFor the convenience of processing, the triples corresponding to the non-zero elements in the sparse matrix are stored in a one-dimensional structure array with "row order as the main order", and all non-zero elements in each row of the matrix (from small to large) The triplets of are stored incrementally by the column number, and the triplet table of the matrix is ​​obtained .
Matrices and triplet tables
the code

# define MAXSIZE 1000				//设非零元素的个数最多为1000
/*三元组的存储结构*/
typedef struct {
    
    
	int row, col;					//该非零元素的行下标和列下标
	int e;							//该非零元素的值
}Triple;
/*三元组表的存储结构*/
typedef struct {
    
    
	Triple data[MAXSIZE + 1];		//非零元素的三元组表,下标从1开始
	int m, n, len;					//矩阵的行数、列数和非零元素的个数
}TSMatrix;

1.2 Matrix transposition based on triple table

① The rows and columns of the triplets in the triplet table are swapped.
② The triplet table is re-sorted in ascending order according to the row subscript.

1.2.1 Incremental column order transposition method
Transpose according to the increasing order of the column order of the transposed matrix triple table A, and send it to the triple table B of the transposed matrix in turn.
Sequence-increasing transpose

/*转置:列序递增转置法*/
void TransposeTSMatrix(TSMatrix* A, TSMatrix* B) {
    
    
	int i, j, k;
	B->m = A->n;
	B->n = A->m;
	B->len = A->len;
	if (B->len > 0) {
    
    
		j = 1;											//记录转置后的三元组在三元组表B中的下标值
		for (k = 1; k <= A->n; k++) {
    
    
			for (i = 1; i < A->len; i++) {
    
    				//从头至尾扫描三元组表A,寻找col值为k的三元组进行转置
				if (A->data[i].col == k) {
    
    
					B->data[j].row = A->data[i].col;
					B->data[j].col = A->data[i].row;
					B->data[j].e = A->data[i].e;
					j++;
				}
			}
		}
	}
}

1.2.2 One-time fast transposition method
Only scan triplet table A once, so that all triplets with non-zero elements in A can be directly placed in the correct position in triplet B in "one-time positioning".

num[col] : used to store the total number of non-zero elements in column col of triple table A
position[col] : used to store the first non-zero element in column col of triple table A before transposition Storage location (subscript value) in triple table B
position[1] = 1
position[col] = position[col - 1] + num[col - 1] (col > 1)
one quick transpose

/*一次定位快速转置法*/
void FastTransposeTSMatrix(TSMatrix* A, TSMatrix* B) {
    
    
	int col, t, p, q;
	int num[MAXSIZE], position[MAXSIZE];
	B->m = A->n;
	B->n = A->m;
	B->len = A->len;
	if (B->len) {
    
    
		for (col = 1; col <= A->n; col++)				//初始化num数组
			num[col] = 0;
		for (t = 1; t <= A->len; t++)
			num[A->data[t].col]++;						//扫描三元组表A,求num数组
		position[1] = 1;
		for (col = 2; col < A->n; col++)				//根据num数组求position数组
			position[col] = position[col - 1] + num[col - 1];

		for (p = 1; p <= A->len; p++) {
    
    					//扫描三元组表A,实现转置
			col = A->data[p].col;
			q = position[col];
			B->data[q].row = A->data[p].col;
			B->data[q].col = A->data[p].row;
			B->data[q].e = A->data[p].e;
			position[col]++;							//表示该列的下一个非零元素
		}
	}
}

1.3 Complete implementation code

# include<stdio.h>
# define MAXSIZE 1000				//设非零元素的个数最多为1000

/*三元组*/
/*三元组的存储结构*/
typedef struct {
    
    
	int row, col;					//该非零元素的行下标和列下标
	int e;							//该非零元素的值
}Triple;
/*三元组表的存储结构*/
typedef struct {
    
    
	Triple data[MAXSIZE + 1];		//非零元素的三元组表
	int m, n, len;					//矩阵的行数、列数和非零元素的个数
}TSMatrix;

/*根据数组创建三元组表*/
void CreateTSMatrix(TSMatrix* A, int arry[][7], int m, int n) {
    
    
	int i, j, k = 1;
	for (i = 0; i < m; i++) {
    
    
		for (j = 0; j < n; j++) {
    
    
			if (arry[i][j] != 0) {
    
    
				A->data[k].row = i + 1;
				A->data[k].col = j + 1;
				A->data[k].e = arry[i][j];
				k++;
			}
		}
	}
	A->len = k - 1;
	A->m = m;
	A->n = n;
}

/*转置:列序递增转置法*/
void TransposeTSMatrix(TSMatrix* A, TSMatrix* B) {
    
    
	int i, j, k;
	B->m = A->n;
	B->n = A->m;
	B->len = A->len;
	if (B->len > 0) {
    
    
		j = 1;											//记录转置后的三元组在三元组表B中的下标值
		for (k = 1; k <= A->n; k++) {
    
    
			for (i = 1; i < A->len; i++) {
    
    				//从头至尾扫描三元组表A,寻找col值为k的三元组进行转置
				if (A->data[i].col == k) {
    
    
					B->data[j].row = A->data[i].col;
					B->data[j].col = A->data[i].row;
					B->data[j].e = A->data[i].e;
					j++;
				}
			}
		}
	}
}

/*一次定位快速转置法*/
/* num[col]用来存放三元组表A第col列中非零元素总个数
   position[col]用来存放转置前三元组表A中第col列中第一个非零元素在三元组表B中的存储位置(下标值)
   position[col]=position[col-1]+num[col-1](col>1) */
void FastTransposeTSMatrix(TSMatrix* A, TSMatrix* B) {
    
    
	int col, t, p, q;
	int num[MAXSIZE], position[MAXSIZE];
	B->m = A->n;
	B->n = A->m;
	B->len = A->len;
	if (B->len) {
    
    
		for (col = 1; col <= A->n; col++)				//初始化num数组
			num[col] = 0;
		for (t = 1; t <= A->len; t++)
			num[A->data[t].col]++;						//扫描三元组表A,求num数组
		position[1] = 1;
		for (col = 2; col < A->n; col++)				//根据num数组求position数组
			position[col] = position[col - 1] + num[col - 1];

		for (p = 1; p <= A->len; p++) {
    
    					//扫描三元组表A,实现转置
			col = A->data[p].col;
			q = position[col];
			B->data[q].row = A->data[p].col;
			B->data[q].col = A->data[p].row;
			B->data[q].e = A->data[p].e;
			position[col]++;							//表示该列的下一个非零元素
		}
	}
}

/*根据三元组表输出稀疏矩阵*/
void Display(TSMatrix* A) {
    
    
	int i, j, k = 1;
	for (i = 1; i <= A->m; i++) {
    
    
		for (j = 1; j <= A->n; j++) {
    
    
			if (i == A->data[k].row && j == A->data[k].col) {
    
    
				printf("%3d", A->data[k].e);
				k++;
			}
			else
				printf("  0");
		}
		printf("\n");
	}
}

int main() {
    
    
	int M[6][7] = {
    
     {
    
    0,12,9,0,0,0,0},
				{
    
    0,0,0,0,0,0,0},
				{
    
    -3,0,0,0,0,14,0},
				{
    
    0,0,24,0,0,0,0},
				{
    
    0,18,0,0,0,0,0},
				{
    
    15,0,0,-7,0,0,0} };
	TSMatrix A, B, C;
	CreateTSMatrix(&A, M, 6, 7);
	TransposeTSMatrix(&A, &B);
	printf("列序递增转置法:\n");
	Display(&B);
	FastTransposeTSMatrix(&A, &C);
	printf("\n一次定位快速转置法:\n");
	Display(&C);
	return 0;
}

1.4 Running results

operation result

2. Cross linked list

2.1 The storage structure of cross linked list

The cross-linked list is a linked storage method for sparse matrices. Each non-zero element of the matrix is ​​represented by a node. In addition to (row, col, vaule), this node also needs to add two chain domains: right is used to link the next non-zero element in the same row, down is used to link to the next nonzero element in the same column.
The node structure of the cross listcross linked listCode

/*十字链表的存储结构*/
typedef struct OLNode {
    
    
	int row, col;						//非零元素的行和列下标
	int vaule;
	struct OLNode* right, * down;		//非零元素所在行表、列表的后继链域
}OLNode, *OLink;

typedef struct {
    
    
	OLink* row_head, * col_head;		//行、列链表的头指针向量
	int m, n, len;						//稀疏矩阵的行数、列数、非零元素个数
}CrossList;

Reference: Geng Guohua "Data Structure - Described in C Language (Second Edition)"

For more data structure content, follow my "Data Structure" column : https://blog.csdn.net/weixin_51450101/category_11514538.html?spm=1001.2014.3001.5482

Guess you like

Origin blog.csdn.net/weixin_51450101/article/details/122722271