链表简单实现集合交并

博主废话确实挺多的,想直接看代码点下面这里:

源代码


其实交并集可以用数组来完成的,不过最近学到了链表,就用链表来进行操作好了,也可以熟悉熟悉链表的操作。

操作还是就比较简单的,简单说下写代码的过程中遇到的问题就行了

遇到的问题只有一个:在进行交并集的操作过程中,直接对两个集合进行操作会影响后面进行的操作。简单的来说就是,在原来集合的基础上直接进行交集的话,会改变两个集合中的元素,以至于后面进行的并集操作得出的结果错误。

不过这个问题是比较好解决的,在进行交集操作的时候,重新创建一个集合(链表)来存结果就好了

下面是出现问题时的交并集代码:

//交集操作
set Intersection(set a, set b) {
	set p = a->next;
	while (p != NULL) {
		int flag = 0;
		set q = b->next;
		while (q != NULL) {
			if (p->data == q->data) {
				flag = 1;
				break;
			}
			q = q->next;
		}
		if (flag == 0 && p != NULL) {
			set s = p;
			p = p->next;
			a = Delete(a, s->data);
		}else p = p->next;
	}
	return a;
}

//并集操作
set Union(set a, set b) {
	set p = b->next;
	while (p != NULL) {
		set q = a->next;
		int flag = 0;
		while (q != NULL) {
			if (p->data == q->data) {
				flag = 1;
				break;
			}
			q = q->next;
		}
		if (flag == 0)a = Insert(a, p->data);
		p = p->next;
	}
	return a;
}

用来单独实现的话,还是可以的,同时多次进行就行不通:

 可以看到,运行结果的并集明显是错的

下面时修改后的交并集操作代码:

//交集:
set Intersection(set a, set b) {
	set c = (set)malloc(sizeof(struct Set));
	c->next = NULL;
	set p = a->next;
	while (p != NULL) {
		int flag = 0;
		set q = b->next;
		while (q != NULL) {
			if (p->data == q->data) {
				flag = 1;
				break;
			}
			q = q->next;
		}
		if (flag == 1)c = Insert(c, p->data);
		p = p->next;
	}
	return c;
}
//并集:
set Union(set a, set b) {
	set d = (set)malloc(sizeof(struct Set));
	d->next = NULL;
	set s = a->next, k = d;
	while (s != NULL) {
		set l = (set)malloc(sizeof(struct Set));
		l->data = s->data;
		l->next = NULL;
		k->next = l;
		k = l;
		s = s->next;
	}
	set p = b->next;
	while (p != NULL) {
		set q = a->next;
		int flag = 0;
		while (q != NULL) {
			if (p->data == q->data) {
				flag = 1;
				break;
			}
			q = q->next;
		}
		if (flag == 0)d = Insert(d, p->data);
		p = p->next;
	}
	return d;
}

这样子无论是先交集还是先并集都不会影响原先的两个集合啦!

可能有初学的小伙伴会问:为什么还要进行这样的操作:

set d = (set)malloc(sizeof(struct Set));
	d->next = NULL;
	set s = a->next, k = d;
	while (s != NULL) {
		set l = (set)malloc(sizeof(struct Set));
		l->data = s->data;
		l->next = NULL;
		k->next = l;
		k = l;
		s = s->next;
	}

也就是,将集合a(链表)的元素一一赋给d,而不是这样:

set d=a;

 其实这很好理解,直接将d=a;只是创建了一个和指针a指向同一个头结点的新指针d而已,它们的储存位置是一样的,只要d改变了,a也会改变。(多补充一句,对于任何一个链表,我们都是通过头结点找到它的其它结点的位置)(说这个这好像有些多余)

最后,我有添加了一个函数,是用来求集合a与集合b的差集的,和并集有些类似:

set Minus(set a, set b) {
	set c = (set)malloc(sizeof(struct Set));
	c->next = NULL;
	set p = b->next;
	while (p != NULL) {
		set q = a->next;
		int flag = 0;
		while (q != NULL) {
			if (p->data == q->data) {
				flag = 1;
				break;
			}
			q = q->next;
		}
		if (flag == 0)c = Insert(c, p->data);
		p = p->next;
	}
	return c;
}

运行结果(比较懒,举了比较简单的例子,要是运行其它例子出错的话可以评论提醒一下,博主看到了会进行修改的)

源代码

最后是源代码(挺佩服我自己的,这么简单的问题说一大堆,不过确实是博主在解决问题过程中的思考过程啦)

#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct Set {//定义结构体
	int data;
	struct Set* next;
}*set;
set CreateSet(int n) {//创建链表,也就是集合
	set head = (set)malloc(sizeof(struct Set));
	head->next = NULL;
	set p = head;
	for (int i = 0; i < n; i++) {
		set q = (set)malloc(sizeof(struct Set));
		cin >> q->data;
		p->next = q;
		q->next = NULL;
		p = q;
	}
	return head;
}
set Delete(set head,int x) {//按元素删除操作,只删除一次便退出
	set p = head, q = head->next;
	while (q != NULL) {
		if (q->data == x) {
			p->next = q->next;
			free(q);
			break;
		}
		p = q;
		q = q->next;
	}
	return head;
}
set Insert(set head, int x) {//头插法将元素插入链表(集合)
	set p = (set)malloc(sizeof(struct Set));
	p->data = x;
	p->next = head->next;
	head->next = p;
	return head;
}
set Intersection(set a, set b) {//求交集
	set c = (set)malloc(sizeof(struct Set));
	c->next = NULL;
	set p = a->next;
	while (p != NULL) {
		int flag = 0;
		set q = b->next;
		while (q != NULL) {
			if (p->data == q->data) {
				flag = 1;
				break;
			}
			q = q->next;
		}
		if (flag == 1)c = Insert(c, p->data);
		p = p->next;
	}
	return c;
}
set Union(set a, set b) {//求并集
	set d = (set)malloc(sizeof(struct Set));
	d->next = NULL;
	set s = a->next, k = d;
	while (s != NULL) {
		set l = (set)malloc(sizeof(struct Set));
		l->data = s->data;
		l->next = NULL;
		k->next = l;
		k = l;
		s = s->next;
	}
	set p = b->next;
	while (p != NULL) {
		set q = a->next;
		int flag = 0;
		while (q != NULL) {
			if (p->data == q->data) {
				flag = 1;
				break;
			}
			q = q->next;
		}
		if (flag == 0)d = Insert(d, p->data);
		p = p->next;
	}
	return d;
}
set Minus(set a, set b) {//求差集set(a,b)是求b-a,set(b,a)才是求a-b
	set c = (set)malloc(sizeof(struct Set));
	c->next = NULL;
	set p = b->next;
	while (p != NULL) {
		set q = a->next;
		int flag = 0;
		while (q != NULL) {
			if (p->data == q->data) {
				flag = 1;
				break;
			}
			q = q->next;
		}
		if (flag == 0)c = Insert(c, p->data);
		p = p->next;
	}
	return c;
}
set Set_Sort(set head) {//按从小到大将集合(链表)元素排序
	set p = head->next;
	while (p != NULL) {
		set q = p->next;
		while (q != NULL) {
			if (p->data > q->data) {
				int t = p->data;
				p->data = q->data;
				q->data = t;
			}
			q = q->next;
		}
		p = p->next;
	}
	return head;
}
void Print(set head) {//将集合(链表)进行输出
	head = Set_Sort(head);
	set p = head->next;
	while (p != NULL) {
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}
int main() {
	int n, m;
	cout << "请输入两个集合的元素个数:" << endl;
	cin >> n >> m;
	cout << "请输入集合a的所有元素:" << endl;
	set a = CreateSet(n);
	cout << "请输入集合b的所有元素:" << endl;
	set b = CreateSet(m);
	cout << "两个集合的交集为:" << endl;
	set c = Intersection(a, b);
	Print(c);
	cout << "两个集合的并集为:" << endl;
	c = Union(a, b);
	Print(c);
	cout << "两个集合的差集a-b为:" << endl;
	c = Minus(b, a);
	Print(c);
	cout << "两个集合的差集b-a为:" << endl;
	c = Minus(a, b);
	Print(c);
	return 0;
}
  • 4
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoyuer2815

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值