《数据结构》复习之稀疏矩阵(矩阵转置)

  • 矩阵的表示方法
  • 矩阵的转置

矩阵的表示方法

  矩阵在数据结构中常用二维数组(int A[m][n],m为列的元素个数,n为行的元素个数)表示,这也是最简单的表示方法。
  然而当矩阵中含有大量0元素时,也称为稀疏矩阵,这样的表示方法会浪费大量的存储空间,为了节省存储单元,最好只存非零元素。常用的存储稀疏矩阵的方法有顺序存储和链式存储两种,这里只介绍顺序存储。
  稀疏矩阵的顺序存储方法也被称为三元组表示法,数据结构如下:
  

typedef struct ele
{
    int x;    //行坐标
    int y;   //列坐标
    int val;   //值
}ele;

typedef struct T
{
    int mu;    //行的元素个数
    int nu;    //列的元素个数
    int tu;     //元素的总个数
    ele elem[maxSize];    
}T;

  除了结构体的定义,总的来说就是用一个数组来记录非零元素的信息。

矩阵的转置

  对于普通的矩阵来说,矩阵转置很简单,比如要将A[nu][mu]转置成B[mu][nu]。只需要两个for循环,代码如下:

fori=0;i<mu;i++)
{ for(j=0;j<nu;j++) { B[j][i]=A[i][j]; }
}

  它的时间复杂度为O(n2)。
  对于稀疏矩阵来说,转置算法可以是这样的。
  《数据结构》复习之稀疏矩阵(矩阵转置)_第1张图片
  它的时间复杂度也是O(n2)。
  但是我们可以用技巧将转置的复杂度O(n)。代码如下:  

#include<iostream>
#include<string.h>
using namespace std;

typedef struct ele
{
    int x;    //行坐标
    int y;   //列坐标
    int val;   //值
}ele;

typedef struct T
{
    int mu;    //行的元素个数
    int nu;    //列的元素个数
    int tu;     //元素的总个数
    ele elem[12500];    
}T;

void tran(T t1, T &t2)
{
    int i, temp;
    t2.mu = t1.nu;        
    t2.nu = t1.mu;
    t2.tu = t1.tu;
    int count[1000];
    memset(count, 0, sizeof(count));
    for (i = 0; i<t1.tu; i++)        //记录每列元素的个数
    {
        count[t1.elem[i].y]++;
    }
    int loc[1000];
    memset(loc, 0, sizeof(loc));
    loc[0] = 0;
    for (i = 1; i<t1.nu; i++)   //计算每列元素应该在数组中存储的起始位置
    {
        loc[i] = loc[i - 1] + count[i - 1];
    }
    for (i = 0; i<t1.tu; i++)    //开始在数组中
    {
        temp = loc[t1.elem[i].y];   //找到当前列应该存放元素的位置
        loc[t1.elem[i].y]++;    //由于已经存放了一个元素,该列存放元素的起始位置应该加1
        t2.elem[temp].x = t1.elem[i].y;
        t2.elem[temp].y = t1.elem[i].x;
        t2.elem[temp].val = t1.elem[i].val;
    }
}

int main()
{
    T t1, t2;
    t1.tu = 0;
    cin >> t1.mu >> t1.nu;  //输入行数列数
    int i, j, temp=0, num = 0;
    for (i = 0; i<t1.mu; i++)     //输入矩阵,并把存储在三元组表示法中
    {
        for (j = 0; j<t1.nu; j++)
        {
            cin >> temp;
            if (temp != 0)
            {
                t1.tu++;
                t1.elem[num].val = temp; //不要写错
                t1.elem[num].x = i;
                t1.elem[num].y = j;
                //全部弄完之后再++ 
                num++;
            }
        }
    }
    tran(t1, t2);  //调用转置函数
    num = 0;
    for (i = 0; i<t2.mu; i++)      //输出矩阵
    {
        for (j = 0; j<t2.nu; j++)
        {
            if (t2.elem[num].x == i&&t2.elem[num].y == j)
            {
                cout << t2.elem[num].val << " ";
                num++;
            }
            else
            {
                cout << 0 << " ";
            }
        }
        cout << endl;
    }

    return 0;
}

  代码中展示了稀疏矩阵的输入输出和转置。对于转置算法,最主要的是找到转置的元素在数组中的位置,如果找到了位置,我们将它放入相应的位置即可。由于,转置过程中,列变成了行,为了找到位置,我们计算列坐标为0-n的元素的个数(思想是列坐标为0转置后行坐标就为0,应该放在数组前面),在计算每列元素应该在数组中存储的起始位置(loc[i] = loc[i - 1] + count[i - 1]),起始位置等于前面的列的起始位置+前面列元素的个数。计算算出起始位置后,就可以将元素放入相应的位置。记住,每放一个元素后,起始位置要加1。

你可能感兴趣的:(数据结构,矩阵转置-稀疏矩阵)