创建十字链表还好,主要麻烦的是加法的部分
将a作为最终输出链表,将b中元素加到a中 ,可能有三种情况
- 二者对应元素和为0 ,即需要删去该结点
- 二者之和不为0 ,继续
- b中元素a中没有,新插入结点
可以考虑的方法:
在加法时不考虑结点的删除 ,在全部加完之后再删除值为 0 的 结点 。这样可以有效减少复杂的分类和讨论
注意了:矩阵认为从第一行第一列开始,与数组默认从第0个元素开始不同 。因此为了减少麻烦,可以在分配的时候多分配一个空间,这样可以通过下标对应访问,即 a[i] 就是对应第 i 行/列 。
若不按照此默认规则 ,可能会导致越界 (共有 n行 ,但行下标为 0到 n-1 , 这样若输入数据含有 第n行会导致数组越界 。
由于没有额外设置头结点,因此插入和删除都要单独讨论第一个元素,为了减少麻烦,可以采用 prev 指针, prev指针随 p 指针一起移动,这样可以省去对最后一个元素的讨论
否则 p->right->value 可能会因为 p->right 是 NULL 而导致错误 ,这样的话就还要对 p 是否是最后一个元素分类 。
#include<bits/stdc++.h>
using namespace std;
struct node {
int row, col, value;
node* down;
node* right;
};
struct Olink {
int rows, cols, nodes;
node** downlist;
node** rightlist;
};
void setNULL(node** a, int n)
{
node** pp = a+1;
for (int i = 1; i <= n; i++, pp++)
*pp = NULL;
}
void initcol(node*& a, node*& p)
{
node* t = a;
if (a == NULL) a = p;
else
{
while (t->down != NULL)
{
t = t->down;
}
t->down = p;
}
}
void initrow(node*& a, node*& p)
{
node* t = a;
if (a == NULL)
{
a = p;
return;
}
while (t->right != NULL)
{
t = t->right;
}
t->right = p;
}
void Init(Olink& a, int n)
{
node* p;
a.downlist = (node**)malloc(sizeof(node*) * (a.rows+1));
a.rightlist = (node**)malloc(sizeof(node*) * (a.cols+1));
setNULL(a.downlist, a.rows);
setNULL(a.rightlist, a.cols);
for (int i = 0; i < n; i++)
{
p = (node*)malloc(sizeof(node));
cin >> p->row >> p->col >> p->value;
p->down = NULL;
p->right = NULL;
initcol(a.rightlist[p->col], p);
initrow(a.downlist[p->row], p);
}
}
void showrow(node* a)
{
node* p = a;
while (p != NULL)
{
cout << p->row << ' ' << p->col << ' ' << p->value << endl;
p = p->right;
}
}
void showwhole(Olink& a)
{
for (int i = 1; i <= a.rows; i++)
{
if (a.downlist[i] != NULL)
showrow(a.downlist[i]);
}
}
void deletenode(node* prev, node* p)
{
prev->right = p->right;
free(p);
}
void deletelinenode(node*& a)
{
node* p = a->right, * prev = a;
if (a->value == 0)
{
a = a->right;
}
while (p != NULL)
{
if (a->value == 0)
{
a = a->right;
}
if (p->value == 0)
{
deletenode(prev, p);
p = prev->right;
}
else
{
p = p->right;
prev = prev->right;
}
}
}
void insert(node* a, node* p)
{
node* prev = a;
node* t = a->right;
while (t != NULL && t->col < p->col)
{
t = t->right;
prev = prev->right;
}
if (t == NULL)
{
prev->right = p;
return;
}
if (p->col == t->col)
t->value += p->value;
else
{
prev->right = p;
p->right = t;
}
}
void addcol(node*& a, node* b)
{
node* pb = b, * t = pb->right;
if (a == NULL)
{
a = b;
node* pa = a;
pb = b->right;
while (pb != NULL)
{
pa->right = pb;
pa = pb;
pb = pb->right;
}
return;
}
if (b->col == a->col)
{
a->value += b->value;
}
else if (b->col < a->col)
{
b->right = a;
a = b;
}
else insert(a, pb);
pb = t;
while (pb != NULL)
{
t = pb->right;
insert(a, pb);
pb = t;
}
}
void add(Olink& a, Olink& b)
{
for (int i = 1; i <= a.rows; i++)
{
if (b.downlist[i] == NULL) continue;
else
{
addcol(a.downlist[i], b.downlist[i]);
if (a.downlist[i] == NULL) continue;
deletelinenode(a.downlist[i]);
}
}
}
int main()
{
Olink a, b;
cin >> a.rows >> a.cols;
b.rows = a.rows;
b.cols = a.cols;
cin >> a.nodes >> b.nodes;
Init(a, a.nodes);
Init(b, b.nodes);
add(a, b);
showwhole(a);
}