数据结构:稀疏矩阵的快速转置

这是一个比较简单的算法,考到数组或矩阵考它的概率我觉得还是蛮高的。

假设有如下数组:

f1c7dfe11c4c750eb4b5e63a011b55f1.png

体现于数组存储结构中(第一排表示行数,列数,非零元个数):

ab72e6493b4595726e3e7dafa2bc73d7.png

很明显直接交换ij的转置是不符合存放要求的。存放要求要求我们按照i进行排序,当然此处可以用上前面的排序算法进行排序,但是今天要研究的快速转置方法是在转置时就一步到位的按位存放。

(正确的存放结果)

96be13c452b654a3c1ba5d8e92d03929.png

稀疏矩阵的快速转置算法

方法:使用辅助数组,记录原数组中每一列非零元的个数,得到非零元个数后就可以方便地计算出转置后的位置。对于上面的数组,每一列的非零元分别为3、4、2、3;我们就可以推算出,转置后的矩阵第一行、第二行、第三行、第四行分别的元素个数为3、3、2、3,便得到对应第一到四列元素转置后应该按序从第1、4、7、9开始存放.

7aa8680c1edb20aaa9758b9c3d03b17e.png

得到上面这个数组后再进行一趟扫描就可以完成矩阵的转置。

矩阵的快速转置代码实现:

#include <iostream>
using namespace std;


void quicktransposition(int (*data)[3])
{
    int num[data[0][1] + 1] = {0};
    for (int i = 0; i < data[0][2]; i++)
        num[data[i + 1][1]]++;//制作num[col]数组
    int p[data[0][1] + 1] = {1, 1};
    for (int i = 2; i < data[0][2]; i++)
        p[i] = num[i - 1] + p[i - 1];//制作p[col]数组
    int tmp[data[0][2]][3];//新建临时数组
    tmp[0][1] = data[0][0];
    tmp[0][0] = data[0][1];
    tmp[0][2] = data[0][2];
    for (int i = 1; i <= data[0][2]; i++)
    {
        int pi;
        pi = p[data[i][1]]++;
        tmp[pi][0] = data[i][1];
        tmp[pi][1] = data[i][0];
        tmp[pi][2] = data[i][2];
    }
    for (int i = 0; i < data[0][2]; i++)
    {
        data[i][0] = tmp[i][0];
        data[i][1] = tmp[i][1];
        data[i][2] = tmp[i][2];
    }//临时数组赋值给原数组
}


int main()
{
    int i, j, n;
    cin >> i >> j >> n;
    int data[n + 1][3];
    data[0][0] = i;
    data[0][1] = j;
    data[0][2] = n;
    for (int k = 1; k <= n; k++)
        cin >> data[k][0] >> data[k][1] >> data[k][2];
    quicktransposition(data);
    cout << "__________________" << endl;
    for (int k = 0; k < data[0][2]; k++)
        cout << data[k][0] << ' ' << data[k][1] << ' ' << data[k][2] << endl;
}

输出结果:

__________________
4 7 11
1 2 3
1 5 7
1 7 10
2 1 1
2 3 4
2 6 8
3 4 6
3 7 11
4 1 2
4 3 5

矩阵的快速排序算法,空间复杂度其实并不算低,如果想要降低空间复杂度,可以参考矩阵的就地转置算法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值