这是一个比较简单的算法,考到数组或矩阵考它的概率我觉得还是蛮高的。
假设有如下数组:
体现于数组存储结构中(第一排表示行数,列数,非零元个数):
很明显直接交换ij的转置是不符合存放要求的。存放要求要求我们按照i进行排序,当然此处可以用上前面的排序算法进行排序,但是今天要研究的快速转置方法是在转置时就一步到位的按位存放。
(正确的存放结果)
稀疏矩阵的快速转置算法
方法:使用辅助数组,记录原数组中每一列非零元的个数,得到非零元个数后就可以方便地计算出转置后的位置。对于上面的数组,每一列的非零元分别为3、4、2、3;我们就可以推算出,转置后的矩阵第一行、第二行、第三行、第四行分别的元素个数为3、3、2、3,便得到对应第一到四列元素转置后应该按序从第1、4、7、9开始存放.
得到上面这个数组后再进行一趟扫描就可以完成矩阵的转置。
矩阵的快速转置代码实现:
#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
矩阵的快速排序算法,空间复杂度其实并不算低,如果想要降低空间复杂度,可以参考矩阵的就地转置算法。