CalcSparseMatrix.cpp
上传用户:shown1022
上传日期:2022-08-06
资源大小:188k
文件大小:11k
源码类别:

数据结构

开发平台:

Visual C++

  1. /*******************************************************************************
  2.   《数据结构》之上机实践源代码 1 - 稀疏矩阵的操作
  3.    功    能:实现稀疏矩阵的加、减、乘法和转置操作
  4.    作    者:刘伟
  5.    编写日期:2008-05-08
  6.    版 本 号:v 1.0
  7.    备    注:使用标准 C 代码实现
  8.    
  9. *******************************************************************************/
  10. // 使用的库定义
  11. #include <stdio.h>
  12. // 常量定义
  13. #define MAX_ELEM_NUM 100    // 稀疏矩阵中的最大元素个数,假定矩阵操作(如加、减等)后的元素个数
  14.                             // 也不超过这个值。注意:因为采用三元组法表示稀疏矩阵,因此相加等操作
  15.                             // 后的矩阵元素个数可能比相加前的矩阵要多。 
  16. #define TRUE  1
  17. #define FALSE 0
  18. // 稀疏矩阵元素类型定义(三元组结构) - 记录体
  19. struct SparseMatrixElem
  20. {
  21.   // 非零元素的行号
  22.   int RowNo;
  23.   // 非零元素的列号
  24.   int ColNo;
  25.   // 非零元素的值(假定全部为整数)
  26.   int ElemValue;
  27. };
  28. // 采用一维数组的方式将稀疏矩阵中的元素组织起来 ...
  29. // 注意:数组的第一个元素(下标为 0)的 3 个数据域
  30. // 的含义依次为:矩阵的行数、列数、非零元素的个数
  31. SparseMatrixElem A[MAX_ELEM_NUM], B[MAX_ELEM_NUM], C[MAX_ELEM_NUM];
  32. // 按照给定的行号和列号在三元组组数组中寻找稀疏矩阵的元素值并返回 ...
  33. // 返回索引号(索引号为 0 - FALSE 则表示未找到) ...
  34. int GetElemValue(SparseMatrixElem *pA, int TargetRowNo, int TargetColNo)
  35. {
  36.   int i;
  37.   for(i=1; i<=pA -> ElemValue; i++)
  38.   {
  39.     if ( ((pA + i) -> RowNo == TargetRowNo) && ((pA + i) -> ColNo == TargetColNo) )
  40.       return i;
  41.   }
  42.   return 0;
  43. }
  44. // 注意:在 C 语言中,数组名表示数组的首地址,是一个指针
  45. // 下面的许多操作采用指针进行。该指针指向 SparseMatrixElem
  46. // 类型的元素。
  47. // 将三元组形式表示的稀疏矩阵输出为常规形式 ...
  48. // 如三元组表示为:
  49. // 
  50. // 3   3   3
  51. // 1   1   4
  52. // 2   1   5
  53. // 2   3   1
  54. //
  55. // 调用本函数后显示为:
  56. // 
  57. // 4   0   0
  58. // 5   0   1
  59. // 0   0   0
  60. void DisplayMatrix(SparseMatrixElem *pA)
  61. {
  62.   int m, n, k;
  63.   for (m=1; m<=pA->RowNo; m++)
  64.   {
  65. printf("| ");
  66.     for (n=1; n<=pA->ColNo; n++)
  67.     {
  68.       k = GetElemValue(pA, m, n);
  69.       if (k > 0)
  70.         printf("%d", (pA + k) -> ElemValue);
  71.   else
  72.         putchar('0');
  73.   // 输出 2 个空格符保证美观,最后一个元素不输出空格 ...
  74.   if (n < pA->ColNo)
  75.   {
  76.     putchar(' ');
  77.     putchar(' ');
  78.   }
  79. }
  80. printf(" |");
  81. // 矩阵一行元素输出完毕,换行 ...
  82. printf("n");
  83.   }
  84. }
  85. // 显示三元组数据 ...
  86. void DisplayTripleArray(SparseMatrixElem *pA)
  87. {
  88.   int k;
  89.   for (k=0; k<=pA->ElemValue; k++)
  90.   {
  91. printf("| %d  ", (pA + k) -> RowNo);
  92.     printf("%d  ", (pA + k) -> ColNo); 
  93. printf("%d |", (pA + k) -> ElemValue);
  94.     
  95. // 矩阵一行元素输出完毕,换行 ...
  96. printf("n");
  97.   }
  98. }
  99. // 显示稀疏矩阵数据 ...
  100. // (1) 显示矩阵格式;
  101. // (2) 显示三元组格式;
  102. void DisplaySparseMatrix(SparseMatrixElem *pA)
  103. {
  104.   printf("---------------------------------n");
  105.   printf("[Matrix] n");
  106.   DisplayMatrix(pA);
  107.   printf("[Triple Array] n");
  108.   DisplayTripleArray(pA);
  109.   printf("---------------------------------n");
  110. }
  111. // 从键盘输入稀疏矩阵数据 ...
  112. void GetSparseMatrixData(SparseMatrixElem *pA)
  113. {
  114.   int TotalRowNum;
  115.   int k;
  116.   // 表示 Triple Array 格式输入,如:
  117.   // 3   3   3
  118.   // 1   1   4
  119.   // 2   1   5
  120.   // 2   3   1
  121.   printf("Input matrix data with [Triple Array] format : n");
  122.   printf("n");
  123.   // 输入行数(三元组的总行数):
  124.   printf("Total row number for triple array : ");
  125.   scanf("%d", &TotalRowNum);
  126.   
  127.   // 输入实际数据 ...
  128.   printf("[Triple Array] data : n");
  129.   for(k=0; k<TotalRowNum; k++)
  130.   {
  131.     // 只有 3 列 ...
  132.     scanf("%d%d%d", &((pA + k) -> RowNo), &((pA + k) -> ColNo), &((pA + k) -> ElemValue));
  133.   }
  134. }
  135. // 从文件输入稀疏矩阵数据 ...
  136. int GetSparseMatrixData(SparseMatrixElem *pA, char*filename)
  137. {
  138.   FILE *fp;
  139.   int TotalRowNum;
  140.   int k;
  141.   // 打开数据文件 ...
  142.   if ((fp = fopen(filename, "r")) == NULL)
  143.   {
  144.     printf("Error open sparse matrix data file %s !n", filename);
  145.     return FALSE;
  146.   }
  147.   
  148.   // 读入行数(三元组的总行数):
  149.   fscanf(fp, "%d", &TotalRowNum);
  150.   
  151.   // 输入实际数据 ...
  152.   for(k=0; k<TotalRowNum; k++)
  153.   {
  154.     // 只有 3 列 ...
  155.     fscanf(fp, "%d%d%d", &((pA + k) -> RowNo), &((pA + k) -> ColNo), &((pA + k) -> ElemValue));
  156.   }
  157.   
  158.   // 关闭数据文件 ...
  159.   fclose(fp);
  160.   
  161.   return TRUE;
  162. }
  163. // pA 和 pB 为指向 SparseMatrixElem 类型数据的指针,计算时将数组的名称传入 ...
  164. // 本函数的功能是:稀疏矩阵 pA 和 pB 相加,计算结果存入 pC 中 ...
  165. // C = A + B
  166. void AddSparseMatrix(SparseMatrixElem *pA, SparseMatrixElem *pB, SparseMatrixElem *pC)
  167. {
  168.   int m, k;
  169.   int OverlapElemNum = 0; // 2 个矩阵对应重叠位置元素的个数 ...
  170.   int N = 0;
  171.   // 只有大小相等的矩阵才能相加 ...
  172.   if ( (pA -> RowNo !=  pB -> RowNo) || (pA -> ColNo !=  pB -> ColNo) )
  173.   {
  174.     printf("Matrix''s size NOT equal !n");
  175. return;
  176.   }
  177.   // 设置 C 矩阵的大小 :在大小上 'C = A = B' ...
  178.   pC -> RowNo = pA -> RowNo;
  179.   pC -> ColNo = pA -> ColNo;
  180.   
  181.   // 算法如下:
  182.   // (1) 将 A 矩阵中的所有元素 copy 到 C 矩阵中;
  183.   pC -> ElemValue = pA -> ElemValue;
  184.   N = pC -> ElemValue; // 记录当前 C 矩阵中元素的个数 ...
  185.   for (m=1; m<= pA -> ElemValue; m++)
  186.   {
  187.     (pC + m) -> RowNo     = (pA + m) -> RowNo;
  188.     (pC + m) -> ColNo     = (pA + m) -> ColNo;
  189.     (pC + m) -> ElemValue = (pA + m) -> ElemValue;
  190.   }
  191.   
  192.   // (2) 依次处理 B 矩阵中的每个元素,如果该元素对应位置上存在 A 矩阵元素则运算,否则
  193.   //     在 C 矩阵中增加一个新元素;
  194.   for (m=1; m<= pB -> ElemValue; m++)
  195.   {
  196.     // 在 C 矩阵中查找是否存在某个位置上的元素 ...
  197. // 如找到则返回该元素的位置,否则返回 0 ...
  198. k = GetElemValue(pC, (pB + m) -> RowNo, (pB + m) -> ColNo);
  199.     if (k > 0)
  200.     {
  201.       // 相加 ...
  202.       (pC + k) -> ElemValue = (pC + k) -> ElemValue + (pB + m) -> ElemValue;
  203.       OverlapElemNum++; // 重叠位置数累加,用于计算 C 矩阵的三元组表示中元素的个数 ...
  204. }
  205. else // 返回 0 - FALSE,表示矩阵 B 中出现一个新位置的元素 ...
  206. {
  207.       N++;
  208.       (pC + N) -> RowNo     = (pB + m) -> RowNo;
  209.       (pC + N) -> ColNo     = (pB + m) -> ColNo;
  210.       (pC + N) -> ElemValue = (pB + m) -> ElemValue;
  211. }
  212.   }
  213.   // 计算 C 矩阵中元素的个数 ...
  214.   pC -> ElemValue = (pA -> ElemValue + pB -> ElemValue) - OverlapElemNum;
  215.   // (3) 对 C 矩阵中元素进行排序,保证其行、列标号为递增序(暂略);
  216.   // ...
  217. }
  218. // pA 和 pB 为指向 SparseMatrixElem 类型数据的指针,计算时将数组的名称传入 ...
  219. // 本函数的功能是:稀疏矩阵 pA 和 pB 相减,计算结果存入 pC 中 ...
  220. // C = A - B
  221. void SubtractSparseMatrix(SparseMatrixElem *pA, SparseMatrixElem *pB, SparseMatrixElem *pC)
  222. {
  223.   int k;
  224.   
  225.   // C = A - B = A + (-B)
  226.   // 本函数可以调用 [AddSparseMatrix] 函数 ...
  227.   // 注意:下面的循环从 1 开始,这是存放稀疏矩阵中非零元素开始的位置 ...
  228.   for (k=1; k<=pB -> ElemValue; k++)
  229.   {
  230.     (pB + k) -> ElemValue = -1 * (pB + k) -> ElemValue; 
  231.   }
  232.    
  233.   AddSparseMatrix(pA, pB, pC);
  234.   // 因为可能进行后续计算,所以必须将 B 矩阵的值复原 ...
  235.   for (k=1; k<=pB -> ElemValue; k++)
  236.   {
  237.     (pB + k) -> ElemValue = -1 * (pB + k) -> ElemValue; 
  238.   }
  239. }
  240. // pA 和 pB 为指向 SparseMatrixElem 类型数据的指针,计算时将数组的名称传入 ...
  241. // 本函数的功能是:稀疏矩阵 pA 和 pB 相乘,计算结果存入 pC 中 ...
  242. // C = A * B
  243. //
  244. // 提示:先要判断 2 个矩阵是否可以进行相乘运算 ...
  245. void MultipleSparseMatrix(SparseMatrixElem *pA, SparseMatrixElem *pB, SparseMatrixElem *pC)
  246. {
  247. // [上机作业] - 自己上机实现 ...
  248. }
  249. // 本函数的功能是:稀疏矩阵 pA 进行转置操作,计算结果存入 pC 中 ...
  250. // C = A - B
  251. void TransposeSparseMatrix(SparseMatrixElem *pA, SparseMatrixElem *pC)
  252. {
  253.   int m;
  254.   // 设置 C 矩阵的大小 :在大小上 'C = A' ...
  255.   pC -> RowNo = pA -> RowNo;
  256.   pC -> ColNo = pA -> ColNo;
  257.   // “转置”操作:交换“三元组”中各个元素的行、列号即可 ...
  258.   pC -> ElemValue = pA -> ElemValue;
  259.   for (m=1; m<= pA -> ElemValue; m++)
  260.   {
  261.     (pC + m) -> RowNo     = (pA + m) -> ColNo;
  262.     (pC + m) -> ColNo     = (pA + m) -> RowNo;
  263.     (pC + m) -> ElemValue = (pA + m) -> ElemValue;
  264.   }
  265. }
  266. // ####################################################################### //
  267. //                                                                         // 
  268. //                           下面是主程序开始                              // 
  269. //                                                                         // 
  270. // ####################################################################### //
  271. void main(void)
  272. {
  273.   SparseMatrixElem *pA;
  274.   SparseMatrixElem *pB;
  275.   SparseMatrixElem *pC;
  276.   char ch;
  277.   char *filename_A = "SparseMatrix_A.txt";
  278.   char *filename_B = "SparseMatrix_B.txt";
  279.   /************************************************
  280.     
  281.                        初始化
  282.   *************************************************/
  283.   // C 语言中,数组的首地址即为指针 ...
  284.   pA = A;
  285.   pB = B;
  286.   pC = C;
  287.   /************************************************
  288.     
  289.                 输入稀疏矩阵数据
  290.   *************************************************/
  291.   // 显示菜单 ...
  292.   printf("**********************************n");
  293.   printf("!         Menu Selection         !n");
  294.   printf("!                                !n");
  295.   printf("! 1) Input from file             !n");
  296.   printf("! 2) Input from keyboard         !n");
  297.   printf("! 0) Exit                        !n");
  298.   printf("!                                !n");
  299.   printf("**********************************n");
  300.   printf("Your choice[1/2/0] : ");
  301.   do
  302.   {
  303.     ch = getchar();
  304.   }
  305.   while ( (ch != '0') && (ch != '1') && (ch != '2') );
  306.   switch (ch)
  307.   {
  308.     case '1' : // 从文件输入稀疏矩阵数据
  309.       // 输入 A 矩阵数据 ...
  310.       printf("Loading from data file for matrix A : n");
  311.       if (!GetSparseMatrixData(pA, filename_A))
  312.       {
  313.         return; 
  314.   }
  315.       printf("Matrix A is : n");
  316.       DisplaySparseMatrix(pA);
  317.       
  318.       printf("n");
  319.       
  320.       // 输入 B 矩阵数据 ...
  321.   printf("Loading from data file for matrix B : n");
  322.       if (!GetSparseMatrixData(pB, filename_B))
  323.   {
  324.         return;
  325.   }
  326.       printf("Matrix B is : n");
  327.       DisplaySparseMatrix(pB);
  328.       
  329.   break;
  330.     case '2' : // 从键盘输入稀疏矩阵数据
  331.       // 输入 A 矩阵数据 ...
  332.       printf("Input data for matrix A : n");
  333.       GetSparseMatrixData(pA);
  334.       printf("Matrix A is : n");
  335.       DisplaySparseMatrix(pA);
  336.   
  337.       printf("n");
  338.       // 输入 B 矩阵数据 ...
  339.       printf("Input data for matrix B : n");
  340.       GetSparseMatrixData(pB);
  341.       printf("Matrix B is : n");
  342.       DisplaySparseMatrix(pB);
  343.   break;
  344.     case '0' : // 退出
  345.       return;
  346.   
  347.   break;
  348.     default :
  349.       return;
  350.   
  351.   break;
  352.   } 
  353.   /************************************************
  354.     
  355.                       稀疏矩阵运算
  356.   *************************************************/
  357.   // 加法 ...
  358.   printf("n");
  359.   printf("Matrix [ADDITION] operation : n");
  360.   printf("[C = A + B] ==> Matrix C is : n");
  361.   AddSparseMatrix(pA, pB, pC);
  362.   DisplaySparseMatrix(pC);
  363.   // 减法 ...
  364.   printf("n");
  365.   printf("Matrix [SUBTRACTION] operation : n");
  366.   printf("[C = A - B] ==> Matrix C is : n");
  367.   SubtractSparseMatrix(pA, pB, pC);
  368.   DisplaySparseMatrix(pC);
  369.   
  370.   // 乘法 ...
  371.   printf("n");
  372.   printf("Matrix [MULTIPLICATION] operation : n");
  373.   printf("[C = A x B] ==> Matrix C is : n");
  374.   MultipleSparseMatrix(pA, pB, pC);
  375.   DisplaySparseMatrix(pC);
  376.   // 转置 ...
  377.   printf("n");
  378.   printf("Matrix [TRANSPOSE] operation : n");
  379.   printf("[C = A'] ==> Matrix C is : n");
  380.   TransposeSparseMatrix(pA, pC);
  381.   DisplaySparseMatrix(pC);
  382. }