Méthode de mise en œuvre de la matrice clairsemée de structure de données

Implémentation d'une matrice clairsemée

Qu'est-ce qu'une matrice clairsemée et comment définir une matrice clairsemée ? Supposons qu'il y ait t éléments qui ne valent pas 0 dans la matrice mxn. Soit z=t/(mxn), si z<=0,05, cette matrice est appelée matrice clairsemée. Étant donné que les matrices clairsemées contiennent moins d'éléments non nuls, le stockage de grande capacité entraînera inévitablement un gaspillage de mémoire. Par conséquent, seules les valeurs d'éléments non nulles sont nécessaires. Vous trouverez ci-dessous trois méthodes couramment utilisées pour stocker des matrices clairsemées.

table de séquence triple

La mise en œuvre d'une table triple séquence est mise en œuvre par une structure de stockage séquentielle. Définissez une structure de tableau, qui stocke un triplet (c'est-à-dire un ensemble composé de 3 parties de données). Les données du groupe sont représentées séparément (étiquette de ligne, étiquette de colonne, valeur d'élément). La mise en œuvre de la structure est la suivante :

//三元组结构体
typedef struct {
    
    
    int i,j;//行标i,列标j
    int data;//元素值
}triple;
//矩阵的结构表示
typedef struct {
    
    
    triple data[number];//存储该矩阵中所有非0元素的三元组
    int n,m,num;//n和m分别记录矩阵的行数和列数,num记录矩阵中所有的非0元素的个数
}TSMatrix;

définir papassaddsa
Comme le montre la figure ci-dessus, il s'agit d'une table ternaire qui est insérée séquentiellement dans le tableau. Le processus spécifique de mise en œuvre est le suivant :

#include <stdio.h>
#define MAXSIZE 100
#define OK 1
#define ERROR 0
#define ELEMTYPE int

typedef struct {
    
    
	int i;   //行
	int j;   //列
	ELEMTYPE e; //元素
}Triple;
typedef struct {
    
    
	Triple data[MAXSIZE+1];
	int mu, nu, tu;
}TSmatrix;
void display(TSmatrix *s);
int main(void)
{
    
    
	TSmatrix s;
	s.mu = 3;
	s.nu = 3;
	s.tu = 3;
	s.data[0].i = 3;
	s.data[0].j = 3;
	s.data[0].e = 6;
	s.data[1].i = 2;
	s.data[1].j = 3;
	s.data[1].e = 8;
	s.data[2].i = 2;
	s.data[2].j = 1;
	s.data[2].e = 4;
	display(&s);
	getchar();
	return 0;
}

void display(TSmatrix *s)
{
    
    
	for (int i = 1; i <= s->mu; i++)
	{
    
    
		for (int j = 1; j <= s->nu; j++)
		{
    
    
			int value = 0;            //用来判断是否到了指定的(i,j)位置
			for (int k = 0; k < s->tu; k++)//遍历数组中的三元表值
			{
    
    
				if (s->data[k].i == i && s->data[k].j == j) //若遍历至指定(i,j)就打印元素值
				{
    
    
					value = 1;
					printf("%d ", s->data[k].e);
					break;
				}
			}
			if(value==0)  //若不为三元表中存储的值就打印0
			printf("%d ", 0);
		
		}
		printf("\n");
	}
}

Insérer la description de l'image ici
Les résultats sont présentés dans la figure ci-dessus. La vérification de la matrice montre qu'il n'y a aucun problème avec la position d'impression.
La méthode présentée ci-dessus peut réaliser le stockage de matrices clairsemées, mais elle est relativement inefficace dans l'extraction de données. Maintenant, ce n'est qu'une matrice 3x3 qui peut ne pas être visible, mais si m et n sont tous deux en dizaines de millions, le non- 0 dans la matrice clairsemée Si le nombre d'éléments est d'environ n, alors la complexité temporelle atteindra O(mxn xn), ce qui sera une énorme perte de temps. Par conséquent, la méthode suivante a été améliorée par rapport à cette méthode.

Table de séquence de lignes liées logiquement

La séquence de liens logiques de ligne représente une amélioration basée sur la méthode ci-dessus. Sur la base de ce qui précède, un tableau est ajouté pour stocker la position du premier élément non nul de chaque ligne dans le tableau utilisé pour stocker la triple table, donc qu'il n'est pas nécessaire de parcourir l'ensemble du tableau ternaire n'a besoin que de parcourir les données des lignes correspondantes, ce qui améliore considérablement l'efficacité.
Insérer la description de l'image ici
Insérer la description de l'image ici
Utilisez le tableau rpos pour enregistrer l'emplacement de stockage du premier élément non nul dans chaque ligne de la matrice dans le tableau unidimensionnel. Le processus spécifique de parcours est le suivant :
il peut être vu sur le tableau rpos que le premier élément non nul de la première ligne est situé dans data[1], donc lors du parcours de cette ligne, vous pouvez directement partir de la position de data[1] et passage au suivant La position du premier élément non-0 dans une ligne (avant data[3] ; lors du
parcours de la deuxième ligne, il peut être vu dans le tableau rpos que le premier élément non-0 dans cette ligne est située dans data[3], elle peut donc être obtenue directement à partir de data[3] Commencez et parcourez jusqu'à ce que le premier élément non nul de la ligne suivante soit localisé (data[4]) ; lors du parcours de la troisième
ligne , on peut voir sur le tableau rpos que le premier élément non 0 de cette ligne est situé à data[4], car c'est la dernière ligne de la matrice, elle peut donc être parcourue jusqu'à la fin du tableau rpos ( c'est-à-dire data[tu], tu fait référence au nombre total d'éléments non nuls dans la matrice).

#include <stdio.h>
#define MAXSIZE 100
#define MAXSD  100
#define ELEMTYPE int

typedef struct {
    
    
	int i;
	int j;
	ELEMTYPE e;
}Triple;
typedef struct {
    
    
	Triple data[MAXSIZE];
	int rpos[MAXSD];  //定义rpos数组用于存储每一行第一个非0元素
	int mu, nu, tu;
}RLSmatrix;
void display(RLSmatrix *s);
int main(void)
{
    
    
	RLSmatrix s;
	s.mu = 4;
	s.nu = 3;
	s.tu = 4;

	s.data[1].i = 1;
	s.data[1].j = 1;
	s.data[1].e = 3;
	s.data[2].i = 2;
	s.data[2].j = 2;
	s.data[2].e = 4;
	s.data[3].i = 3;
	s.data[3].j = 3;
	s.data[3].e = 6;
	s.data[4].i = 4;
	s.data[4].j = 3;
	s.data[4].e = 3;

	s.rpos[1] = 1;
	s.rpos[2] = 2;
	s.rpos[3] = 3;
	s.rpos[4] = 4;
	display(&s);
	getchar();
	return 0;

}

void display(RLSmatrix *s)
{
    
    
	for (int i = 1; i <= s->mu; i++)
	{
    
    
		for (int j = 1; j <= s->nu; j++)
		{
    
    
			int value = 0;
			if(i+1<=s->mu) //假设一共i行则前面的i-1行遍历对应行的元素
			{
    
    
				for (int k = s->rpos[i]; k < s->rpos[i + 1]; k++) //遍历数组中对应行的非0元素即可
				{
    
    
					if (s->data[k].i == i && s->data[k].j == j) 
					{
    
    
						value = 1;
						printf("%d ", s->data[k].e);
						break;
					}
					if (value == 0)
						printf("0 ");
				}
			}
			else  //最后一行只需遍历到最后一个非0元素即可
			{
    
    
				for (int k = s->rpos[i]; k <=s->tu; k++)
				{
    
    
					if (s->data[k].i == i && s->data[k].j == j)
					{
    
    
						value = 1;
						printf("%d ", s->data[k].e);
						break;
					}
					if (value == 0)
						printf("0 ");
				}
			}
			
		}
		printf("\n");
	}
}

Insérer la description de l'image ici

Méthode de liste chaînée pour stocker des matrices clairsemées

Les deux méthodes de stockage ci-dessus peuvent bien fonctionner lorsqu'elles sont utilisées pour un stockage fixe, mais lorsqu'elles impliquent l'insertion ou la suppression d'éléments non nuls, cela entraînera le mouvement des valeurs des éléments, comme l'opération d'ajout de deux matrices. utilisez une chaîne. Il est plus approprié d'utiliser le stockage triple pour représenter les triples. Cette méthode de stockage utilise une structure "liste chaînée + tableau".
Insérer la description de l'image ici
Insérer la description de l'image ici
Comme le montre la figure ci-dessus, les éléments non nuls sont représentés par un nœud contenant cinq champs, et deux pointeurs sont utilisés pour pointer respectivement vers les éléments de la même colonne et de la même ligne. Utilisez ensuite deux tableaux unidimensionnels pour stocker les listes chaînées de lignes et les listes chaînées de colonnes pour stocker ces listes chaînées. Chaque élément non nul est à la fois un nœud dans une liste chaînée en lignes et un nœud dans une liste chaînée en colonnes. La matrice entière forme une liste chaînée entrecroisée.

#include<stdio.h>
#include<stdlib.h>
typedef struct OLNode
{
    
    
    int i, j, e; //矩阵三元组i代表行 j代表列 e代表当前位置的数据
    struct OLNode *right, *down; //指针域 右指针 下指针
}OLNode, *OLink;
typedef struct
{
    
    
    OLink *rhead, *chead; //行和列链表头指针
    int mu, nu, tu;  //矩阵的行数,列数和非零元的个数
}CrossList;
CrossList CreateMatrix_OL(CrossList M);
void display(CrossList M);
int main()
{
    
    
    CrossList M;
    M.rhead = NULL;
    M.chead = NULL;
    M = CreateMatrix_OL(M);
    printf("输出矩阵M:\n");
    display(M);
    return 0;
}
CrossList CreateMatrix_OL(CrossList M)
{
    
    
    int m, n, t;
    int i, j, e;
    OLNode *p, *q;
    printf("输入矩阵的行数、列数和非0元素个数:");
    scanf("%d%d%d", &m, &n, &t);
    M.mu = m;
    M.nu = n;
    M.tu = t;
    if (!(M.rhead = (OLink*)malloc((m + 1) * sizeof(OLink))) || !(M.chead = (OLink*)malloc((n + 1) * sizeof(OLink))))
    {
    
    
        printf("初始化矩阵失败");
        exit(0);
    }
    for (i = 1; i <= m; i++)
    {
    
    
        M.rhead[i] = NULL;
    }
    for (j = 1; j <= n; j++)
    {
    
    
        M.chead[j] = NULL;
    }
    for (scanf("%d%d%d", &i, &j, &e); 0 != i; scanf("%d%d%d", &i, &j, &e)) {
    
    
        if (!(p = (OLNode*)malloc(sizeof(OLNode))))
        {
    
    
            printf("初始化三元组失败");
            exit(0);
        }
        p->i = i;
        p->j = j;
        p->e = e;
        //链接到行的指定位置
        if (NULL == M.rhead[i] || M.rhead[i]->j > j)
        {
    
    
            p->right = M.rhead[i];
            M.rhead[i] = p;
        }
        else
        {
    
    
            for (q = M.rhead[i]; (q->right) && q->right->j < j; q = q->right);
            p->right = q->right;
            q->right = p;
        }
        //链接到列的指定位置
        if (NULL == M.chead[j] || M.chead[j]->i > i)
        {
    
    
            p->down = M.chead[j];
            M.chead[j] = p;
        }
        else
        {
    
    
            for (q = M.chead[j]; (q->down) && q->down->i < i; q = q->down);
            p->down = q->down;
            q->down = p;
        }
    }
    return M;
}
void display(CrossList M) {
    
    
    for (int i = 1; i <= M.nu; i++)
    {
    
    
        if (NULL != M.chead[i])
        {
    
    
            OLink p = M.chead[i];
            while (NULL != p)
            {
    
    
                printf("%d\t%d\t%d\n", p->i, p->j, p->e);
                p = p->down;
            }
        }
    }
}

Je suppose que tu aimes

Origine blog.csdn.net/ccjjjjdff/article/details/114760836
conseillé
Classement