三元组快速转置矩阵

  算法原理:
 
  在列增序算法的基础上,只对A扫描一次
  预先计算A中每列非零元素的总个数
  预先计算矩阵每一列中第一非零元在三元组表B中正确的位置
  在从A开始遍历,每一个列值 第二次出现后 没出现一次 cpot值+1
  实现在B中的定位
  这样只要遍历一遍A就实现转置
 
时间复杂度:
时间注意啊消耗在4个并列的单循环上,这4个并列的单循环分别执行了A.n、A.len,  A.n-1,A.len
所以时间复杂度 为 O(A.n)+O(A.len)+O(A.n-1)+O(A.len)
                            =O(A.n+A.len)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 1000
typedef struct
{
 int row,col;
 int elem;
}Triple;
typedef struct
{
 Triple data[MAXN];
 int m,n,len;
}Triplematrix;
int num[1000],cpot[1000];
//num用来存放每一种列值的非零元的个数
//cpot用来计算矩阵每一种列值中第一非零元在三元组表B中的位置
void tsmatrix(Triplematrix *a,Triplematrix *b)
{
 int i,j,cnt,col;
 b->m=a->n,b->n=a->m,b->len=a->len;
 if(a->len)
 {
     for(i=0;i<a->n;i++)
     num[i]=0;
     for(j=0;j<a->len;j++)  //data是从0开始记的
     {
        num[a->data[j].col]++; //记录每一列非零元的个数
     }
     cpot[0]=0;  //cpot是三元组中每一列第一个元素,cpot也符合有0下标的矩阵的,
                 //第0列第一个元素的位置自然是0
    for(i=1;i<a->n;i++)     //本例列数是从0开始的
    {
      cpot[i]=cpot[i-1]+num[i-1];
    }
    for(i=0;i<a->len;i++)
    {
       col=a->data[i].col;
       cnt=cpot[col];       //cnt纪录cpot的反馈
       b->data[cnt].row=a->data[i].col;
       b->data[cnt].col=a->data[i].row;
       b->data[cnt].elem=a->data[i].elem;
       ++cpot[col];//就跑到这一列的第二个元素去了
    }
 }
}
void print(Triplematrix *b)
{
    int cnt;
    printf("\n");
    for(cnt=0;cnt<(b->len);cnt++)
    {
        printf("%d %d %d\n",b->data[cnt].row,b->data[cnt].col,b->data[cnt].elem);
    }
}
int main()
{
 Triplematrix a;
 scanf("%d %d",&a.m,&a.n);
 a.len=0;
 int x1,x2,x3;
 while(scanf("%d%d%d",&x1,&x2,&x3),x1||x2||x3)
   {
       a.data[a.len].row=x1;
       a.data[a.len].col=x2;
       a.data[a.len].elem=x3;
       a.len++;
   }            //三元组下标从0开始
    Triplematrix b;
    tsmatrix(&a,&b);
    print(&b);
    return 0;
}

/*
测试用例:
7 7
1 2 13
1 3 9
3 1 -3
3 6 14
4 3 24
5 2 18
6 1 15
6 4 -7
0 0 0



测试结果:
1 3 -3
1 6 15
2 1 13
2 5 18
3 1 9
3 4 24
4 6 -7
6 3 14
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值