1. 程式人生 > >(13)稀疏矩陣的壓縮-三元組表(轉置)

(13)稀疏矩陣的壓縮-三元組表(轉置)

若矩陣中的非零元素遠遠小於矩陣元素的個數,且分佈沒有規律,則稱這個矩陣為稀疏矩陣。
壓縮儲存是指對多個值相同的元素只分配一個儲存空間,對零元素不分配空間。

稀疏矩陣的壓縮儲存有兩種方法:三元組的順序儲存(三元組表)和鏈式儲存(十字連結串列)。

現在主要講三元組表,由於兩個階數不同的矩陣可能具有相同的非零元素,為了區別,在儲存三元組時,同時還應儲存該矩陣的行數、列數。通常為了運算的方便,也存放非零元素的個數。這種以順序儲存

結構來表示三元組的線性表,稱之為三元組表。稀疏矩陣的儲存的三元組表的儲存結構可定義如下:

#define MAXSIZE 1000			//使用者自定義三元組最大個數
typedef int ElemType;
typedef struct {				//三元組
	int row,col;				//非零元素的行數和列數
	ElemType e;					//非零元素的值
}Triple;
typedef struct {
	Triple data[MAXSIZE];		//三元組表
	int m,n, len;				//矩陣的行數、列數和非零個數
}TSMatrix;

(1)三元組表的矩陣轉置運算-“直接取,順序存”

//轉置
TSMatrix TransTSMatrixSlow(TSMatrix a,TSMatrix b) {
	int q;
	b.m = a.n;
	b.n = a.m;
	b.len = a.len;
	if (b.len) {
		q = 0;							//B中的非零個數
		for (int j = 0; j < a.n;j++) {			//按列轉置
			for (int h = 0; h < a.len; h++) {
				if (j==a.data[h].col) {			//本列中一個非零元素
					b.data[q].row = a.data[h].col;
					b.data[q].col = a.data[h].row;
					b.data[q].e = a.data[h].e;
					q++;
				}
			}
		}
	}
	else {
		cout << "矩陣為空,無需轉置!" << endl;
	}
	return b;
}
但是每處理一列就要查遍三元組表,工作量比較大

(2)三元組表的矩陣快速轉置運算-“順序取,直接存”

//快速轉置
TSMatrix TransTSMatrixFast(TSMatrix a, TSMatrix b) {
	int number[MAXSIZE],position[MAXSIZE];
	b.m = a.n;
	b.n = a.m;
	b.len = a.len;
	for (int j = 0; j < a.n;j++) {
		number[j] = 0;		//將矩陣a每一列非零元素的個數初始化為零
	}
	for (int t = 0; t < a.len; t++) {
		number[a.data[t].col]++;		//求每一列非零元素的個數
	}
	position[0] = 0;
	for (int j = 1; j < a.n; j++) {	//a.data[]的第j列第一個非零元素在b.data中的序號
		position[j] = position[j - 1] + number[j - 1];
	}
	int j,q;
	for (int p = 0; p < a.len; p++) {	//求轉置矩陣b的三元組表
		j = a.data[p].col;
		q = position[j];
		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[j]++;
	}
	return b;
}
核心:若用number陣列記錄矩陣A中每列的非零元素個數,用position陣列記錄A中每列第一個非零元素在三元組表中的位置,則若第j-1列的第一個非零元素在position[j-1]的位置上,第j列的第一個非零元素必在第position[j-1]+number[j-1]位置上。

完整程式碼:

#include<iostream>
using namespace std;
#define MAXSIZE 1000			//使用者自定義三元組最大個數
typedef int ElemType;
typedef struct {				//三元組
	int row,col;				//非零元素的行數和列數
	ElemType e;					//非零元素的值
}Triple;
typedef struct {
	Triple data[MAXSIZE];		//三元組表
	int m,n, len;				//矩陣的行數、列數和非零個數
}TSMatrix;
//輸出矩陣
void print(TSMatrix a){
	int k;
	for (int i = 0; i < a.m;i++) {
		for (int j = 0; j < a.n;j++) {
			k = 0;
			for(int h=0;h<a.len;h++){
				if (i == a.data[h].row && j==a.data[h].col) {
					cout <<"     "<< a.data[h].e;
					k = 1;
				}
			}
			if (k == 0) {
				cout << "     " << k;
			}
		}
		cout << endl;
	}
}
//轉置
TSMatrix TransTSMatrixSlow(TSMatrix a,TSMatrix b) {
	int q;
	b.m = a.n;
	b.n = a.m;
	b.len = a.len;
	if (b.len) {
		q = 0;							//B中的非零個數
		for (int j = 0; j < a.n;j++) {			//按列轉置
			for (int h = 0; h < a.len; h++) {
				if (j==a.data[h].col) {			//本列中一個非零元素
					b.data[q].row = a.data[h].col;
					b.data[q].col = a.data[h].row;
					b.data[q].e = a.data[h].e;
					q++;
				}
			}
		}
	}
	else {
		cout << "矩陣為空,無需轉置!" << endl;
	}
	return b;
}
//快速轉置
TSMatrix TransTSMatrixFast(TSMatrix a, TSMatrix b) {
	int number[MAXSIZE],position[MAXSIZE];
	b.m = a.n;
	b.n = a.m;
	b.len = a.len;
	for (int j = 0; j < a.n;j++) {
		number[j] = 0;		//將矩陣a每一列非零元素的個數初始化為零
	}
	for (int t = 0; t < a.len; t++) {
		number[a.data[t].col]++;		//求每一列非零元素的個數
	}
	position[0] = 0;
	for (int j = 1; j < a.n; j++) {	//a.data[]的第j列第一個非零元素在b.data中的序號
		position[j] = position[j - 1] + number[j - 1];
	}
	int j,q;
	for (int p = 0; p < a.len; p++) {	//求轉置矩陣b的三元組表
		j = a.data[p].col;
		q = position[j];
		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[j]++;
	}
	return b;
}
void main() {
	TSMatrix A, B;
	A.m = 5;
	A.n = 6;
	A.len = 7;
	A.data[0].row = 0; A.data[0].col = 1; A.data[0].e = 6;
	A.data[1].row = 0; A.data[1].col = 5; A.data[1].e = -2;
	A.data[2].row = 2; A.data[2].col = 3; A.data[2].e = -8;
	A.data[3].row = 3; A.data[3].col = 1; A.data[3].e = 3;
	A.data[4].row = 3; A.data[4].col = 5; A.data[4].e = 7;
	A.data[5].row = 4; A.data[5].col = 0; A.data[5].e = -12;
	A.data[6].row = 4; A.data[6].col = 2; A.data[6].e = 9;
	cout << "矩陣A為:" << endl;
	print(A);
	cout << "求係數矩陣A的轉置矩陣B?" << endl;
	B = TransTSMatrixSlow(A,B);
	cout << "轉置矩陣B為:" << endl;
	print(B);
	cout << endl;
	B = TransTSMatrixFast(A,B);
	print(B);
	system("pause");
}