📅  最后修改于: 2023-12-03 15:35:56.933000             🧑  作者: Mango
链表是一种常见的数据结构,其中的元素被链接在一起形成一个链式结构。在实际开发中,我们通常需要对两个链表进行操作,包括求它们的并集和相交。
并集指的是两个链表中所有的节点的集合,相交指的是两个链表中共有的节点的集合。
在程序中,我们通常使用指针来遍历链表,从而对其进行操作。
在实现之前,我们需要先定义链表节点的数据结构。
struct ListNode {
int val;
struct ListNode *next;
};
其中,val表示节点的值,next指向下一个节点。
对于两个链表,我们可以先将它们的节点值放入一个集合中,然后遍历该集合,依次创建新的链表节点。
struct ListNode* getUnion(struct ListNode* l1, struct ListNode* l2) {
if (!l1 && !l2) {
return NULL;
}
// 创建用于存放节点值的集合
set<int> s;
// 遍历l1链表,将节点值添加到集合中
while (l1) {
s.insert(l1->val);
l1 = l1->next;
}
// 遍历l2链表,将不在集合中的节点值添加到集合中
while (l2) {
if (!s.count(l2->val)) {
s.insert(l2->val);
}
l2 = l2->next;
}
// 遍历集合,创建新的链表节点并连接起来
struct ListNode* head = NULL;
struct ListNode* tail = NULL;
for (auto val : s) {
struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
node->val = val;
node->next = NULL;
if (!head) {
head = node;
tail = node;
} else {
tail->next = node;
tail = node;
}
}
return head;
}
在这个实现中,我们使用了set集合来存放节点值,这样可以避免重复元素的问题。
对于两个链表,我们可以先分别计算它们的长度,然后将较长的链表先移动一定步数,使其和较短的链表起点位置相同,然后同时遍历两个链表,找到第一个相同的节点。
struct ListNode* getIntersection(struct ListNode* l1, struct ListNode* l2) {
if (!l1 || !l2) {
return NULL;
}
// 计算l1和l2的长度
int len1 = 0, len2 = 0;
struct ListNode* p1 = l1;
struct ListNode* p2 = l2;
while (p1) {
len1++;
p1 = p1->next;
}
while (p2) {
len2++;
p2 = p2->next;
}
// 让较长的链表先移动一定步数
p1 = l1;
p2 = l2;
int diff = abs(len1 - len2);
if (len1 < len2) {
swap(p1, p2);
}
for (int i = 0; i < diff; i++) {
p1 = p1->next;
}
// 同时遍历两个链表,找到第一个相同的节点
while (p1 && p2) {
if (p1 == p2) {
return p1;
} else {
p1 = p1->next;
p2 = p2->next;
}
}
return NULL;
}
以上就是求两个链表并集和相交的实现。在实际开发中,我们要根据具体的需求选择合适的算法和数据结构来实现。
至此,两个链表的并集和相交介绍完毕.