两个链表的并集和交集的 C 程序
给定两个链表,创建并集和交集列表,其中包含给定列表中元素的并集和交集。输出列表中元素的顺序无关紧要。
例子:
Input:
List1: 10->15->4->20
List2: 8->4->2->10
Output:
Intersection List: 4->10
Union List: 2->8->20->4->15->10
方法1(简单):
以下是分别获取并集和交集列表的简单算法。
1、路口(list1,list2):
将结果列表初始化为 NULL。遍历list1并查找list2中的每个元素,如果该元素存在于list2中,则将该元素添加到结果中。
2.联合(list1,list2):
将结果列表初始化为 NULL。遍历 list1 并将其所有元素添加到结果中。
遍历list2。如果 list2 的元素已经存在于结果中,则不要将其插入结果中,否则插入。
此方法假定给定列表中没有重复项。
感谢 Shekhu 提出这种方法。以下是此方法的 C 和Java实现。
C
// C program to find union
// and intersection of two unsorted
// linked lists
#include
#include
#include
// Link list node
struct Node
{
int data;
struct Node* next;
};
/* A utility function to insert a
node at the beginning ofa linked list*/
void push(struct Node** head_ref,
int new_data);
/* A utility function to check if
given data is present in a list */
bool isPresent(struct Node* head,
int data);
/* Function to get union of two
linked lists head1 and head2 */
struct Node* getUnion(struct Node* head1,
struct Node* head2)
{
struct Node* result = NULL;
struct Node *t1 = head1, *t2 = head2;
// Insert all elements of
// list1 to the result list
while (t1 != NULL)
{
push(&result, t1->data);
t1 = t1->next;
}
// Insert those elements of list2
// which are not present in result list
while (t2 != NULL)
{
if (!isPresent(result, t2->data))
push(&result, t2->data);
t2 = t2->next;
}
return result;
}
/* Function to get intersection of
two linked lists head1 and head2 */
struct Node* getIntersection(struct Node* head1,
struct Node* head2)
{
struct Node* result = NULL;
struct Node* t1 = head1;
// Traverse list1 and search each element
// of it in list2. If the element is
// present in list 2, then insert the
// element to result
while (t1 != NULL)
{
if (isPresent(head2, t1->data))
push(&result, t1->data);
t1 = t1->next;
}
return result;
}
/* A utility function to insert a
node at the beginning of a linked list*/
void push(struct Node** head_ref,
int new_data)
{
// Allocate node
struct Node* new_node =
(struct Node*)malloc(
sizeof(struct Node));
// Put in the data
new_node->data = new_data;
/* link the old list off the
new node */
new_node->next = (*head_ref);
/* Move the head to point to the
new node */
(*head_ref) = new_node;
}
/* A utility function to print a
linked list*/
void printList(struct Node* node)
{
while (node != NULL)
{
printf("%d ", node->data);
node = node->next;
}
}
/* A utility function that returns true
if data is present in linked list
else return false */
bool isPresent(struct Node* head,
int data)
{
struct Node* t = head;
while (t != NULL)
{
if (t->data == data)
return 1;
t = t->next;
}
return 0;
}
// Driver code
int main()
{
// Start with the empty list
struct Node* head1 = NULL;
struct Node* head2 = NULL;
struct Node* intersecn = NULL;
struct Node* unin = NULL;
/* Create a linked lists
10->15->5->20 */
push(&head1, 20);
push(&head1, 4);
push(&head1, 15);
push(&head1, 10);
/* Create a linked lits
8->4->2->10 */
push(&head2, 10);
push(&head2, 2);
push(&head2, 4);
push(&head2, 8);
intersecn = getIntersection(head1,
head2);
unin = getUnion(head1, head2);
printf("First list is ");
printList(head1);
printf("Second list is ");
printList(head2);
printf("Intersection list is ");
printList(intersecn);
printf("Union list is ");
printList(unin);
return 0;
}
输出:
First list is
10 15 4 20
Second list is
8 4 2 10
Intersection list is
4 10
Union list is
2 8 20 4 15 10
复杂性分析:
- 时间复杂度: O(m*n)。
这里的“m”和“n”分别是第一个和第二个列表中存在的元素数。
对于联合:对于 list-2 中的每个元素,我们检查该元素是否已经存在于使用 list-1 生成的结果列表中。
对于交集:对于 list-1 中的每个元素,我们检查该元素是否也存在于 list-2 中。 - 辅助空间: O(1)。
不使用任何数据结构来存储值。
方法二(使用归并排序):
在这种方法中,Union 和 Intersection 的算法非常相似。首先,我们对给定的列表进行排序,然后遍历排序的列表以获得并集和交集。
以下是获取联合和交集列表的步骤。
- 使用归并排序对第一个链表进行排序。这一步需要 O(mLogm) 时间。有关此步骤的详细信息,请参阅此帖子。
- 使用归并排序对第二个链表进行排序。这一步需要 O(nLogn) 时间。有关此步骤的详细信息,请参阅此帖子。
- 线性扫描两个排序列表以获得并集和交集。这一步需要 O(m + n) 时间。此步骤可以使用与此处讨论的排序数组算法相同的算法来实现。
该方法的时间复杂度为 O(mLogm + nLogn),优于方法 1 的时间复杂度。
请参阅关于两个链表的并集和交集的完整文章以获取更多详细信息!