📜  两个链表的并集和交集的 C 程序

📅  最后修改于: 2022-05-13 01:56:08.550000             🧑  作者: Mango

两个链表的并集和交集的 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 的算法非常相似。首先,我们对给定的列表进行排序,然后遍历排序的列表以获得并集和交集。
以下是获取联合和交集列表的步骤。

  1. 使用归并排序对第一个链表进行排序。这一步需要 O(mLogm) 时间。有关此步骤的详细信息,请参阅此帖子。
  2. 使用归并排序对第二个链表进行排序。这一步需要 O(nLogn) 时间。有关此步骤的详细信息,请参阅此帖子。
  3. 线性扫描两个排序列表以获得并集和交集。这一步需要 O(m + n) 时间。此步骤可以使用与此处讨论的排序数组算法相同的算法来实现。

该方法的时间复杂度为 O(mLogm + nLogn),优于方法 1 的时间复杂度。
请参阅关于两个链表的并集和交集的完整文章以获取更多详细信息!