十字链表的加法

创建十字链表还好,主要麻烦的是加法的部分

将a作为最终输出链表,将b中元素加到a中 ,可能有三种情况

  1. 二者对应元素和为0 ,即需要删去该结点
  2. 二者之和不为0 ,继续
  3. 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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值