• 使用C语言实现矩阵转置(稀疏矩阵)


    目录

    1.转置矩阵(普通矩阵)

    2.转置矩阵(稀疏矩阵)

    (1)稀疏矩阵

    (2)稀疏矩阵的压缩存储方式

    (3)理论运算方法


    1.转置矩阵(普通矩阵)

    矩阵的转置:根据主对角元素作为对称轴进行元素的互换。转置运算是一种最简单的矩阵运算。对一个mxn的矩阵M进行转置得到矩阵T(nxm),且T(i,j)=M(j,i),1<=i<=n,1<=j<=m.

    注:虽然矩阵的转置非常的简单,但是对于其在计算机上的时间复杂度也是做了很多的优化,特别是对稀疏矩阵的转置,因为稀疏矩阵的存储方式不是直接使用nxn的方式进行存储的,而是采用其他的方式:如三元组等。

    1. #include
    2. #include
    3. #define Mat_n 5
    4. typedef int ElemType;
    5. int M[Mat_n][Mat_n];
    6. //矩阵的转置
    7. void TransposeMatrix(int N[Mat_n][Mat_n],int n,int m){
    8. for(int col=1;col<=m;col++){
    9. for(int row=1;row<=n;row++){
    10. M[col][row]=N[row][col];
    11. }
    12. }
    13. }
    14. int main(){
    15. int n,m;
    16. int N[Mat_n][Mat_n];
    17. printf("请输入矩阵(方阵)行和列: ");
    18. scanf("%d %d",&n,&m);
    19. //初始化
    20. for(int i=1;i<=n;i++){
    21. for(int j=1;j<=m;j++){
    22. N[i][j]=M[i][j]=0;
    23. }
    24. }
    25. printf("请输入矩阵(方阵):\n");
    26. for(int i=1;i<=n;i++){
    27. for(int j=1;j<=m;j++){
    28. scanf("%d",&N[i][j]);
    29. }
    30. }
    31. TransposeMatrix(N,n,m);
    32. for(int i=1;i<=n;i++){
    33. for(int j=1;j<=m;j++){
    34. printf("%d ",M[i][j]);
    35. }
    36. printf("\n");
    37. }
    38. return 0;
    39. }
    40. /*
    41. 4 4
    42. 1 2 0 3
    43. 5 6 3 8
    44. 12 23 45 67
    45. 9 5 3 5
    46. */

    2.转置矩阵(稀疏矩阵)

    (1)稀疏矩阵

    (2)稀疏矩阵的压缩存储方式

    由于是稀疏矩阵,所以只需要存储非零元即可,非零元的位置为(i,j),所以采用三元组的形式(i,j,aij)唯一确定矩阵A的非零元。

    比如:((1,2,2),(1,3,9),(3,1,3),(3,6,4),(4,3,2),(5,2,8),(6,1,5),(6,4,7))

    (3)理论运算方法

    假设M矩阵的三元组形式如下:

    M.data

    元素

    1

    2

    12

    1

    3

    9

    3

    1

    -3

    3

    6

    14

    4

    3

    24

    5

    2

    18

    6

    1

    15

    6

    1

    -7

    转置之后的T矩阵三元组如下:

    T.data

    元素

    1

    3

    -1

    1

    6

    15

    2

    1

    12

    2

    5

    18

    2

    1

    9

    2

    4

    24

    4

    6

    -7

    6

    3

    14

    步骤:

          第一步:将矩阵的行列值进行互换;

          第二步:将每个元组中的i和j值进行调换;

          第三步:重排三元组之间的次序即可实现矩阵的转置;

    而对于第三步的具体实现步骤:

          方法一:

    按照T.data中的三元组的次序依次在M.data中找到相应的三元组进行转置。也就是说对其M.data中的三元组表进行扫描一遍(从第一行到最后一行),由于M.data是以行序为主序来存放每个非零元的,所以也可以得到T.data应有的次序。

    1. #include
    2. #include
    3. #define MAXSIZE 10
    4. typedef int ElemType;
    5. typedef struct {
    6. int i,j;
    7. ElemType e;
    8. }Triple;
    9. typedef struct {
    10. Triple data[MAXSIZE];
    11. int mu,nu,tu;//矩阵的行,列和非零元个数
    12. }TSMatrix;
    13. void TransposeSMatrix(TSMatrix M,TSMatrix&T){
    14. //矩阵的行列互换
    15. T.mu=M.nu;
    16. T.nu=M.mu;
    17. T.tu=M.tu;
    18. if(T.tu){
    19. int q=1;
    20. for(int col=1;col<=M.nu;col++){
    21. for(int p=1;p<=M.tu;p++){
    22. if(M.data[p].j==col){
    23. T.data[q].i=M.data[p].j;
    24. T.data[q].j=M.data[p].i;
    25. T.data[q].e=M.data[p].e;
    26. q++;
    27. }
    28. }
    29. }
    30. }
    31. }
    32. int main(){
    33. TSMatrix M,T;
    34. printf("请输入矩阵的行,列和非零元数: \n");
    35. scanf("%d %d %d",&M.mu,&M.nu,&M.tu);
    36. printf("请输入矩阵(三元组): \n");
    37. for(int i=1;i<=M.tu;i++){
    38. scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e);
    39. }
    40. printf("----------------------------------------------\n");
    41. TransposeSMatrix(M,T);
    42. printf("转置矩阵T: \n");
    43. for(int i=1;i<=T.tu;i++){
    44. printf("%d %d %d\n",T.data[i].i,T.data[i].j,T.data[i].e);
    45. }
    46. return 0;
    47. }
    48. /*
    49. 6 6 8
    50. 1 2 12
    51. 1 3 9
    52. 3 1 -3
    53. 3 6 14
    54. 4 3 24
    55. 5 2 18
    56. 6 1 15
    57. 6 4 -7
    58. */

     注:但是方法一从时间复杂度上来说:O(nu x tu),所以和非零元的个数是成正比的;普通的矩阵的转置时间复杂度为O(mu x nu);但是对于方法一来说,当tu的数量级和nu x mu相同时,就会出现时间复杂度为O(mu x nu x nu),所以这个时候比普通的方法还要耗时。因此方法二对其进行了改进。

    方法二:

    假设:如果能够预先确定矩阵M中的每一列(也就是转置之后的矩阵中的每一行)的第一个非零元在T.data中的应有位置,那么在对M.data中的三元组依次做转置时,便可直接放到T.data中恰当的位置。

    为了提前确定位置,首先需要设置两个数组变量:num和cpot。

    其中num[col]表示矩阵M中的第col列中非零元的个数,cpot[col]表示M中第col列的第一个非零元在T.data中的恰当位置。

    矩阵M的数组cpot的值
    col1234567
    num[co]2221010
    cpot[col]1357889

    num[co]更加形象的计算方式:

    1. #include
    2. #include
    3. #define MAXSIZE 10
    4. const int maxn=100;
    5. typedef int ElemType;
    6. typedef struct {
    7. int i,j;
    8. ElemType e;
    9. }Triple;
    10. typedef struct {
    11. Triple data[MAXSIZE];
    12. int mu,nu,tu;//矩阵的行,列和非零元个数
    13. }TSMatrix;
    14. void TransposeSMatrix_1(TSMatrix M,TSMatrix&T){
    15. //矩阵的行列互换
    16. T.mu=M.nu;
    17. T.nu=M.mu;
    18. T.tu=M.tu;
    19. int num[100];
    20. int cpot[100];
    21. if(T.tu){
    22. //初始化
    23. for(int col=1;col<=M.nu;col++){
    24. num[col]=0;
    25. }
    26. for(int t=1;t<=M.tu;t++){
    27. ++num[M.data[t].j];
    28. }
    29. cpot[1]=1;
    30. for(int col=2;col<=M.nu;col++){
    31. cpot[col]=cpot[col-1]+num[col-1];
    32. }
    33. for(int p=1;p<=M.tu;p++){
    34. int col=M.data[p].j;
    35. //提前得到在T.data中第q行
    36. int q=cpot[col];
    37. T.data[q].i=M.data[p].j;
    38. T.data[q].j=M.data[p].i;
    39. T.data[q].e=M.data[p].e;
    40. //这里之所以要加就是因为一行有多个元素
    41. ++cpot[col];
    42. }
    43. }
    44. }
    45. int main(){
    46. TSMatrix M,T;
    47. printf("请输入矩阵的行,列和非零元数: \n");
    48. scanf("%d %d %d",&M.mu,&M.nu,&M.tu);
    49. printf("请输入矩阵(三元组): \n");
    50. for(int i=1;i<=M.tu;i++){
    51. scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e);
    52. }
    53. printf("----------------------------------------------\n");
    54. TransposeSMatrix_1(M,T);
    55. printf("转置矩阵T: \n");
    56. for(int i=1;i<=T.tu;i++){
    57. printf("%d %d %d\n",T.data[i].i,T.data[i].j,T.data[i].e);
    58. }
    59. return 0;
    60. }
    61. /*
    62. 6 6 8
    63. 1 2 12
    64. 1 3 9
    65. 3 1 -3
    66. 3 6 14
    67. 4 3 24
    68. 5 2 18
    69. 6 1 15
    70. 6 4 -7
    71. */

    注:方法二比之前多用了两个辅助的数组空间num和cpot,但是从时间上来看的话,时间复杂度为O(nu+tu),如果tu的数量级和nu x mu同等,时间复杂度为O(nu x mu).

     参考书籍《数据结构》(清华大学版)

  • 相关阅读:
    Java面试题学习-单例模式
    【uniapp基础篇】实现微信登录
    [MySQL]基本介绍及安装使用详细讲解
    Mac mov转mp4,详细转换步骤
    搭建Conda虚拟环境让python程序脚本更干净
    win10 上PHP artisan storage:link 出现 symlink (): Protocol error的解决办法
    logrotate日志轮转
    AtCoder Regular Contest 146 C Even XOR题解
    中秋节主题征文 | 那些不朽的描写月亮的诗词
    Python-文件
  • 原文地址:https://blog.csdn.net/Keep_Trying_Go/article/details/126337285