稀疏矩阵快速转置算法实现

对于转置,如果我们不考虑转置之后的元素顺序,实际上只需要遍历一遍整个三元组,交换x和y的值就ok了。之所以需要快速转置算法是因为如果三元组在初始时是按照每个三元组x的值从大到小排的,我们希望在转置后,其顺序依旧是按照x的值大小排列。

算法思想

对于这个问题,我们可以先统计y每个取值的数量,接着我们就可算出来对于每个y转置成x后每个x会有几个,即我们可以知道我们放置转置后的三元组的开始位置。
举个例子来说,假设我们有如下三元组:

//Origin matrix
   x  | y  | value
  ----------------
   1    4     0
   1    2     1
   1    1     -3
   2    3     4
   3    4     9
   3    3     1
   4    1     2

那么我们可以遍历一遍获得y取1,2,3,4的数目分别为2,1,2,2。那么我们转置后的三元组排列一定是这样的:

一个短下划线代表一个三元组
x=1    x=2        x=3  x=4
|_ _   | _        |_ _ |_ _

如果这样的话我们就可以知道对于原矩阵中的每一个三元组中,根据其y的取值我们就可以对应找到我们要放入的位置,即指向x取值开始的指针(xStart数组记录)。然后每在某一个指针指的区域中放入一个数就让指针向后移动一位。
通过这样我们只需要遍历一遍原来的矩阵就可以得到转置好的矩阵了。

代码实现

对于我之前提到的如何获得指向x取不同值的指针,我们需要两个辅助数组yCount & xStart.先得到yCount然后根据yCount来计算得到xStart即我们想要的指针。

//Origin matrix
/* x  | y  | value
  ----------------
   1    4     0
   1    2     1
   1    1     -3
   2    3     4
   3    4     9
   3    3     1
   4    1     2
*/
#include<iostream>
using namespace std;
int yCount[100],xStart[100];        //two extra array
class Node{
public:
    Node(){}
    int x;
    int y;
    int value;
};
Node originMat[100];
Node transMat[100];
void getyCount(int n){
    for(int i=0;i<n;i++){
        yCount[originMat[i].y]++;
    }
}
void getxStart(int n){
    for(int i=1;i<n;i++){
        xStart[i]=xStart[i-1]+yCount[i-1];
    }
}
void fastTransMat(int n){
    getyCount(n);
    getxStart(n);
    for(int i=0;i<n;i++){
        int start=xStart[originMat[i].y]++;  //get the pos and pointer++
        transMat[start]=originMat[i];
        swap(transMat[start].x,transMat[start].y);
    }
}
void display(int n){
    for(int i=0;i<n;i++){
        cout<<transMat[i].x<<' '<<transMat[i].y<<
            ' '<<transMat[i].value<<endl;
    }
}
int main(void){
    int n;
    cout<<"the number of originMat elements"<<endl;
    cin>>n;
    cout<<"input originMat with x|y|value"<<endl;
    for(int i=0;i<n;i++){
        cin>>originMat[i].x>>originMat[i].y>>originMat[i].value;
    }
    fastTransMat(n);
    display(n);
}

原始文章发布在我的博客loveSnowBest's blog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值