#include<iostream>
template<class t>
class triplet
{
private:
int mu, nu, tu;
typedef struct _elem {
int i, j;
t val;
_elem() {
i = 0, j = 0, val = 0;
}
_elem(const _elem& e) {
i = e.i, j = e.j, val = e.val;
}
_elem(int i, int j, const t& val)
: i(i), j(j), val(val)
{
}
void show() {
cout << '<' << i << ',' << j << ',' << val << '>';
}
}elem;
elem* data;
int* crow;
public:
triplet();
triplet(int m, int n, int* args, int len);
triplet(int m, int n);
~triplet();
void show();
triplet<t> transposition();
triplet<t> multiply(const triplet<t>& other);
void setCrow();
void insert(int row, int column, int val);
};
template<class t>
triplet<t>::triplet()
{
mu = 0, nu = 0, tu = 0;
data = nullptr;
crow = nullptr;
}
template<class t>
triplet<t>::triplet(int m, int n, int* args, int len) :mu(m), nu(n), tu(len / 3)
{
data = new elem[len / 3];
for (int i = 0, k = 0, _k = 0; i < len; i += 3, k += 1)
{
for (_k = 0; _k < k; _k++) {
if ((args[i] == data[_k].i && args[i + 1] < data[_k].j) || args[i] < data[_k].i) {
elem* temp = new elem(data[_k]);
data[_k].i = args[i], data[_k].j = args[i + 1], data[_k].val = args[i + 2];
for (int k2 = k; k2 > _k + 1; k2--) {
data[k2] = data[k2 - 1];
}
data[_k + 1] = *temp;
delete temp;
break;
}
}
if (_k >= k) {
data[k].i = args[i], data[k].j = args[i + 1], data[k].val = args[i + 2];
}
}
crow = new int[m + 1];
for (int i = 0; i < m + 1; i++) crow[i] = 0;
for (int i = 0; i < tu; i++) crow[data[i].i == m ? 0 : data[i].i + 1]++;
for (int i = 3; i < m + 1; i++) crow[i] += crow[i - 1];
}
template<class t>
triplet<t>::triplet(int m, int n)
{
mu = m, nu = n, tu = 0;
data = nullptr;
crow = nullptr;
}
template<class t>
triplet<t>::~triplet()
{
if (data != nullptr)
{
delete[]data;
}
if (crow != nullptr)
{
delete[]crow;
}
}
template<class t>
void triplet<t>::show()
{
for (int i = 0; i < tu; i++) {
cout << '<' << data[i].i << ','
<< data[i].j << ',' << data[i].val << '>' << endl;
}
for (int i = 1; i <= mu; i++) {
cout << crow[i] << '\t';
}
cout << endl;
}
template<class t>
triplet<t> triplet<t>::transposition()
{
elem* temp = new elem[tu];
int* ccol = new int[nu+1];
int* args = new int[tu * 3];
for (int i = 0; i <= nu; i++) ccol[i] = 0;
for (int i = 0; i < tu; i++)
{ ccol[data[i].j == nu ? 0 : data[i].j + 1]++; }
for (int i = 3; i <= nu; i++)
{ccol[i] += ccol[i - 1];}
for (int i = 0; i < tu; i++) {
temp[ccol[data[i].j]++] = data[i];
}
for (int i = 0, k = 0; i < tu; i++, k+=3) {
args[k] = temp[i].j;
args[k+1] = temp[i].i;
args[k+2] = temp[i].val;
}
triplet<t> res(nu, mu, args, tu * 3);
delete[] temp;
delete[] ccol;
delete[] args;
return res;
}
template<class t>
triplet<t> triplet<t>::multiply(const triplet<t>& other)
{
if (nu != other.mu) {
cout << "矩阵无法相乘" << endl;
triplet<t> res;
return res;
}
int* temp_rows = new int[other.nu + 1];
triplet<t> res(mu, other.nu);
for (int rows = 1; rows <= mu; rows++)
{
for (int i = 0; i <= other.nu; i++) temp_rows[i] = 0;
int left1 = crow[rows], left2 = 0, right1 = 0, right2 = 0;
if (rows == mu)right1 = tu - 1;
else {
right1 = crow[rows+1] - 1;
}
for (int i = left1; i <= right1; i++)
{
left2 = other.crow[data[i].j];
if (data[i].j == nu) right2 = other.tu - 1;
else right2 = other.crow[data[i].j + 1] - 1;
for (int j = left2; j <= right2; j++)
{
temp_rows[other.data[j].j] += data[i].val * other.data[j].val;
}
}
for (int k = 1; k <= other.nu; k++) {
if (temp_rows[k]) {
res.insert(rows, k, temp_rows[k]);
}
}
}
delete[]temp_rows;
return res;
}
template<class t>
void triplet<t>::setCrow()
{
if (tu == 0) return;
if (crow == nullptr) {
crow = new int[mu + 1];
if (!crow) exit(0);
}
for (int i = 0; i <= mu; i++)crow[i] = 0;
for (int i = 0; i < tu; i++) {
crow[data[i].i == mu ? 0 : data[i].i + 1]++;
}
for (int i = 3; i <= mu; i++) crow[i] += crow[i - 1];
}
template<class t>
void triplet<t>::insert(int row, int column, int val)
{
elem* temp = new elem(row, column, val);
if (data == nullptr) {
data = new elem[1];
data[0] = *temp;
tu++;
}
else {
elem* newbase = new elem[++tu];
bool get = 0;
for (int i = 0, j = 0; i < tu && j < tu - 1; i++)
{
if (!get && (data[j].i > temp->i || (data[j].i == temp->i && data[j].j > temp->j))) {
newbase[i] = *temp;
get = true;
}
else if(data[j].i == temp->i && data[j].j == temp->j) {
cout << "插入元素重复" << endl;
cout << data[j].i << ',' << data[j].j << ',' << data[j].val << endl;
newbase[i] = data[j++];
newbase[i].val = temp->val;
}
else {
newbase[i] = data[j++];
}
}
if (newbase[tu - 1].i == 0) {
newbase[tu - 1] = *temp;
}
delete[]data;
data = newbase;
}
delete temp;
setCrow();
return;
}
template<class t>
class matrix_LN2
//十字链表存储稀疏矩阵
{
private:
typedef struct _elem {
int i, j;
t val;
_elem* down, *right;
_elem() {
i = 0, j = 0, val = 0;
down = nullptr, right = nullptr;
}
_elem(int _i, int _j, t _val) :i(_i), j(_j), val(_val) {
down = nullptr, right = nullptr;
}
}elem;
int mu, nu, tu;
elem** hcol, **hrow;
public:
matrix_LN2();
matrix_LN2(int m, int n, int* args, int len);
matrix_LN2(int m, int n);
~matrix_LN2();
void add(const matrix_LN2& other);
};
template<class t>
matrix_LN2<t>::matrix_LN2()
{
mu = 0, nu = 0, tu = 0;
hcol = nullptr, hrow = nullptr;
}
template<class t>
matrix_LN2<t>::matrix_LN2(int m, int n, int* args, int len):mu(m), nu(n), tu(len/3)
{
if (len % 3 != 0) {
cout << "in 'matrix_LN2<t>::matrix_LN2(int m, int n, int* args, int len)' ,len is not right" << endl;
exit(0);
}
hcol = new elem * [nu + 1];
hrow = new elem * [mu + 1];
for (int i = 0; i <= nu; i++)hcol[i] = nullptr;
for (int i = 0; i <= mu; i++)hrow[i] = nullptr;
for (int i = 0; i < len; i += 3)
{
int r_index = args[i], c_index = args[i + 1];
elem* temp = new elem(r_index, c_index, args[i + 2]), *ptr = nullptr;
if (hrow[r_index] == nullptr) hrow[r_index] = temp;
else {
ptr = hrow[r_index];
while (ptr->right != nullptr && ptr->right->j < temp->j)ptr = ptr->right;
temp->right = ptr->right;
ptr->right = temp;
}
if (hcol[c_index] == nullptr) hcol[c_index] = temp;
else {
ptr = hcol[c_index];
while (ptr->down != nullptr && ptr->down->i < temp->i)ptr = ptr->down;
temp->down = ptr->down;
ptr->down = temp;
}
}
}
template<class t>
matrix_LN2<t>::matrix_LN2(int m, int n):mu(m), nu(n)
{
hcol = new elem * [nu + 1];
hrow = new elem * [mu + 1];
for (int i = 0; i <= nu; i++)hcol[i] = nullptr;
for (int i = 0; i <= mu; i++)hrow[i] = nullptr;
tu = 0;
}
template<class t>
matrix_LN2<t>::~matrix_LN2()
{
if (tu == 0 && hcol == nullptr && hrow == nullptr) return;
if (tu == 0) {
delete[] hcol;
delete[] hrow;
return;
}
elem* ptr = nullptr;
for (int i = 0; i < mu; i++) {
hrow[i] = nullptr;
}
for (int i = 0; i <= nu; i++) {
if (hcol[i] != nullptr)
{
for (ptr = hcol[i]; ptr != nullptr; ptr = hcol[i]) {
hcol[i] = ptr->down;
ptr->right = nullptr;
cout << '<' << ptr->i << ',' << ptr->j << ',' << ptr->val << '>' << endl;
delete ptr;
}
}
}
delete[]hcol;
delete[]hrow;
cout << endl;
}
template<class t>
void matrix_LN2<t>::add(const matrix_LN2& other)
{
elem* pre = nullptr;
elem* pa = nullptr, *pb = nullptr;
for (int rows = 1; rows <= mu; rows++) {
pa = this->hrow[rows], pb = other.hrow[rows], pre = nullptr;
while (pb != nullptr)
{
if (pa == nullptr || pa->j > pb->j)
{
elem* temp = new elem(pb->i, pb->j, pb->val);
if (pre == nullptr) this->hrow[rows] = temp;
else {
pre->right = temp;
}
temp->right = pa;
pre = temp;
if (this->hcol[temp->j] == nullptr || this->hcol[temp->j]->i > temp->i)
{
temp->down = this->hcol[temp->j];
this->hcol[temp->j] = temp;
}
else {
elem* hl = nullptr;
for (hl = this->hcol[temp->j]; hl->down != nullptr && hl->down->i < temp->i; hl = hl->down)
{
}
temp->down = hl->down;
hl->down = temp;
}
}
else if (pa != nullptr && pa->j < pb->j)
{
pre = pa;
pa = pa->right;
continue;
}
else if (pa->j == pb->j)
{
if (pa->val + pb->val != 0) {
pa->val += pb->val;
pa = pa->right;
}
else {
elem* temp = nullptr;
if (pre == nullptr) this->hrow[rows] = pa->right;
else {
pre->right = pa->right;
}
temp = pa;
pa = pre->right;
if (this->hcol[temp->j] == temp) {
this->hcol[temp->j] = temp->down;
}
else {
elem* hl = nullptr;
for (hl = this->hcol[temp->j]; hl->down != nullptr && hl->down != temp; hl = hl->down)
{
}
hl->down = temp->down;
}
delete temp;
}
}
pb = pb->right;
}
}
}