实验内容
在m×n 的矩阵中,有t个非零元。令δ= t/(m*n),称δ矩阵的稀疏因子,常认为δ≤0.05时称为稀疏矩阵。稀疏矩阵在工程中有着大量的应用,不少工程问题都可以转化为对稀疏矩阵的计算问题。用三元组表实现稀疏矩阵的转置,用(顺序取,直接存)方法。
实验说明:
引入两个数组作为辅助数据结构:
num[nu]:表示矩阵A中某列的非零元素的个数;
cpot[nu]:初始值表示矩阵A中某列的第一个非零元素在B中的位置。
num与cpot递推关系:
cpot[0]=0;
cpot[col]=cpot[col-1]+num[col-1]; 1<col<nu
三元组表实现稀疏矩阵的转置(顺序取,直接存)算法伪代码如下:
1. 设置转置后矩阵B的行数、列数和非零元素的个数;
2. 计算A中每一列的非零元素个数;
3. 计算A中每一列的第一个非零元素在B中的下标;
4. 依次取A中的每一个非零元素对应的三元组;
2.1 确定该元素在B中的下标pb;
2.2 将该元素的行号列号交换后存入B中pb的位置;
2.3 预置该元素所在列的下一个元素的存放位置;
1.三元组顺序表的声明当矩阵为稀疏矩阵时,用三元组表示更简洁方便。 #include<iostream> using namespace std; #define M 6 #define N 6 #define MaxSize 100//矩阵中非0元素的最大个数 typedef int ElemType; typedef struct { int r;//行号 int c;//列号 ElemType d;//元素值 }TupNode;//三元组的定义 typedef struct {
int cols;//总列数 int nums;//非零元素的个数 TupNode data[MaxSize]; }TSMatrix; 2.创建三元组表示时间复杂度为O(m*n),m与n分别为矩阵的行数与列数。 int num[N] = {};//表示矩阵中某列非零元素的个数 int cpot[N] = {};//矩阵A中某列的第一个非零元素在B中的位置 void CreateMat(TSMatrix& t, ElemType A[M][N]) {//产生矩阵的三元组表示 int i, j; t.rows = M; t.cols = N; t.nums = 0; for (i = 0; i < M; i++) { for (j = 0; j < N; j++) { if (A[i][j] != 0) {//只存储非零元素 num[j]++; t.data[t.nums].r = i; t.data[t.nums].c = j; t.data[t.nums].d = A[i][j]; t.nums++; } } } } 3.输出三元组时间复杂度为O(n),n为矩阵元素的非零个数。 void DispMat(TSMatrix t) {//输出三元组 int k; if (t.nums <= 0) return; for (k = 0; k < t.nums; k++) { cout << t.data[k].r <<" " << t.data[k].c<<" "<< t.data[k].d << endl; } } 4.矩阵的转置求出原稀疏矩阵的每一列的第一个非0元素在转置后的三元组中的哪个位置,扫描原三元组列上元素依次存放到转置后的三元组位置。稀疏矩阵第一列中的第一个非0元素一定存放在转置后三元组数组的 0 位置,第二列的第一个非0元素的位置等于第一列第一个非0元素在转置后三元组数组的位置加上第一列的非0元素个数,以此类推。\n\n若能先计算出稀疏矩阵中每列非0元素存储在转置后三元组的某个位置,那只需对原三元组扫描一遍即可把元素放在相应的位置上。 时间复杂度为O(n+t),n为矩阵的列数,t为矩阵非零元素的个数。 void TranMat(TSMatrix A, TSMatrix& B) {//求转置矩阵 B.rows = A.cols; B.cols = B.rows; B.nums = A.nums;//矩阵B的行数、列数、非零元素个数 cpot[0] = 0;//初始值为0 for (int i = 0; i < MaxSize; i++) { cpot[i] = cpot[i - 1] + num[i - 1];//两者的递推关系 } for (int i = 0; i < A.nums; i++) {//依次取A中每一个元素对应的三元组 int pb = A.data[i].c;//该元素在B中的下标j int k = cpot[pb]; B.data[k].r = A.data[i].c; B.data[k].c = A.data[i].r; B.data[k].d = A.data[i].d; //将该元素的行号列号交换后存入B中pb的位置 cpot[pb]++;//该元素所在列下一个元素的存放位置 } } 5.主函数int main() { ElemType a[M][N] = { {1,0,0,0,0,0},{5,2,4,0,0,0},{0,0,3,0,0,0}, {8,0,0,0,0,0},{0,0,6,0,0,0},{0,0,0,0,0,0} };//矩阵的赋值 TSMatrix T,T1;//T表示原矩阵,T1表示转置后的矩阵 CreateMat(T, a); cout << "——————————原矩阵三元组—————————————" << endl; DispMat(T); cout << "————————转制后的矩阵三元组————————————" << endl; TranMat(T, T1); DispMat(T1); }
|
实 验 总 结 |
了解了稀疏矩阵的声明以及基本应用方法,由于稀释矩阵非零元素相比矩阵的总元素个数非常小,所以用三元组表示更加方便。在矩阵转置方面,普通转置需要对原三元组进行循环扫描,而上述的方法仅需要对原三元组扫描一遍即可将对应的元素放在相应的位置,时间复杂度更低,是一个更高效的算法。 |