三元组顺序标的快速转置
对于稀疏矩阵,为了节省空间,通常使用 三元组顺序表 和 十字链表存储。
对于矩阵,转置运算是很常见的。对于三元组顺序表,如果仅仅将顺序表中每个元素的行号和列号进行交换,生成的新三元组顺序表不是真正的三元组顺序表,因为,行号不是依次递增的,当然,也可以先进行交换行号列号,再对它进行按行号升序的排序,但涉及到排序,就会很麻烦,所以,介绍一种快速转置的方法。
如果要遍历一次三元组顺序表,就要将其转置成功,那么,在遍历每一个元素时,除了交换它的行号和列号,还要将它放到新的顺序表中的特定位置,但是我们怎么知道这个位置呢,我们可以使用一个pos数组进行定位,即pos[列号]就是这个元素在新的三元组顺序表中的位置。
例如,现在第一次遍历到列号为n的元素,那它应该放在哪个位置?这与列号为n-1的最后一个元素的位置有关,要知道列号为n-1的最后一个元素的下一个位置,就要知道列号为n-1的起始位置,和列号为n-1的元素的个数,所以,要引进一个新的数组num,则 pos[n]=pos[n-1]+num[n-1]
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
/****类型声明****/
typedef struct{
int row,col;
int value;
}Triple;
typedef struct{
Triple data[MAXSIZE+1];
int rows,cols,nums;
}TSMatrix;
/****函数声明****/
//初始化三元组顺序表
//@flag 1表明需要进行输入,0表示不需要进行输入
TSMatrix * Init(int flag);
//对顺序表进行排序,这个在初始化中用到
void Sorttable(TSMatrix *A,int left,int right);
//按照矩阵的形式输出三元组顺序表
void Print(TSMatrix *A);
//矩阵转置,将结果存到B中
void TransposeTSMatrix(TSMatrix *B,TSMatrix *A);
int main(void){
TSMatrix *A=Init(1);
Print(A);
TSMatrix *B=Init(0);
TransposeTSMatrix(B,A);
Print(B);
return 0;
}
TSMatrix * Init(int flag){
TSMatrix *A=(TSMatrix *)malloc(sizeof(TSMatrix));
if(flag){
printf("请输入矩阵的行数和列数:");
int rows,cols;
scanf("%d%d",&rows,&cols);
A->rows=rows;
A->cols=cols;
printf("请输入矩阵非0元素个数:");
int nums;
scanf("%d",&nums);
A->nums=nums;
printf("请输入非零元素所在的行数,列数以及该元素的值:\n");
int row,col,value;
printf("row col value\n");
for(int i=0;i<nums;++i){
scanf("%d%d%d",&row,&col,&value);
A->data[i+1].row=row;
A->data[i+1].col=col;
A->data[i+1].value=value;
}
Sorttable(A,1,A->nums);
//在输入时,不一定按照行号升序输入,这里用快速排序进行排序
}
return A;
}
void Print(TSMatrix *A){
int k=1;//用于遍历三元组顺序表
printf("\n ");
for(int i=1;i<A->cols+1;++i)
printf("%5d",i);
printf("\n");
for(int i=1;i<10*A->cols;++i)
printf("-");
for(int i=1;i<A->rows+1;++i){
printf("\n%d|",i);
for(int j=1;j<A->cols+1;++j){
if(A->data[k].row==i && A->data[k].col==j && k<A->nums+1)
printf("%5d",A->data[k++].value);
else
printf("%5d",0);
}
}
printf("\n");
for(int i=1;i<10*A->cols;++i)
printf("-");
return ;
}
void TransposeTSMatrix(TSMatrix *B,TSMatrix *A){//将A的转置存在B里
B->rows=A->cols;
B->cols=A->rows;
B->nums=A->nums;
int num[MAXSIZE]={0};
int position[MAXSIZE]={0,1};
//计算num数组
for(int i=1;i<A->nums+1;++i)
++num[A->data[i].col];
//计算pos数组,将pos[1]初始化为1
for(int i=2;i<A->cols+1;++i)
position[i]=num[i-1]+position[i-1];
int pos;//记录转置后的位置
for(int i=1;i<A->nums+1;++i){
pos=position[A->data[i].col];
B->data[pos].col=A->data[i].row;
B->data[pos].row=A->data[i].col;
B->data[pos].value=A->data[i].value;
++position[A->data[i].col];
}
}
void Sorttable(TSMatrix *A,int left,int right){
if(left>=right)
return ;
Triple temp=A->data[left],t;
int i=left,j=right;
while(i<j){
while(A->data[j].row>=temp.row && i<j)
--j;
while(A->data[i].row<=temp.row && i<j)
++i;
t=A->data[j];
A->data[j]=A->data[i];
A->data[i]=t;
}
A->data[left]=A->data[i];
A->data[i]=temp;
Sorttable(A,left,i-1);
Sorttable(A,i+1,right);
return ;
}