对于转置,如果我们不考虑转置之后的元素顺序,实际上只需要遍历一遍整个三元组,交换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
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
yCount[originMat[i].y]++;
}
}
void getxStart(int n){
for(int i=1;i
xStart[i]=xStart[i-1]+yCount[i-1];
}
}
void fastTransMat(int n){
getyCount(n);
getxStart(n);
for(int i=0;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
cout<
' '<
}
}
int main(void){
int n;
cout<
cin>>n;
cout<
for(int i=0;i
cin>>originMat[i].x>>originMat[i].y>>originMat[i].value;
}
fastTransMat(n);
display(n);
}