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

📅  最后修改于: 2022-05-13 01:56:06.876000             🧑  作者: 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 
using namespace std;
 
// 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)
    {
        cout << " " << 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* intersection = 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 lists 8->4->2->10
    push(&head2, 10);
    push(&head2, 2);
    push(&head2, 4);
    push(&head2, 8);
    intersection =
    getIntersection(head1, head2);
    unin = getUnion(head1, head2);
    cout << "First list is " << endl;
    printList(head1);
    cout << "Second list is " << endl;
    printList(head2);
    cout << "Intersection list is " << endl;
    printList(intersection);
    cout << "Union list is " << endl;
    printList(unin);
    return 0;
}
// This code is contributed by shivanisingh2110


输出

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 的时间复杂度。
请参阅关于两个链表的并集和交集的完整文章以获取更多详细信息!