📌  相关文章
📜  用于查找两个排序链表的交集的 C++ 程序

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

用于查找两个排序链表的交集的 C++ 程序

给定两个按升序排序的列表,创建并返回一个表示两个列表交集的新列表。新列表应该用它自己的内存来创建——原始列表不应该改变。

例子:

Input: 
First linked list: 1->2->3->4->6
Second linked list be 2->4->6->8, 
Output: 2->4->6.
The elements 2, 4, 6 are common in 
both the list so they appear in the 
intersection list. 

Input: 
First linked list: 1->2->3->4->5
Second linked list be 2->3->4, 
Output: 2->3->4
The elements 2, 3, 4 are common in 
both the list so they appear in the 
intersection list.

方法一使用虚拟节点。
方法:
这个想法是在结果列表的开头使用一个临时虚拟节点。指针尾始终指向结果列表中的最后一个节点,因此可以轻松添加新节点。虚拟节点最初给尾巴一个指向的内存空间。这个虚拟节点是有效的,因为它只是临时的,并且是在堆栈中分配的。循环继续,从“a”或“b”中删除一个节点并将其添加到尾部。当遍历给定列表时,结果是虚拟的。接下来,因为这些值是从虚拟的下一个节点分配的。如果两个元素相等,则删除两者并将元素插入尾部。否则删除两个列表中较小的元素。

下面是上述方法的实现:

C++
#include
using namespace std;
  
// Link list node 
struct Node 
{
    int data;
    Node* next;
};
  
void push(Node** head_ref, 
          int new_data);
  
/* This solution uses the temporary
  dummy to build up the result list */
Node* sortedIntersect(Node* a, Node* b)
{
    Node dummy;
    Node* tail = &dummy;
    dummy.next = NULL;
  
    /* Once one or the other 
       list runs out -- we're done */
    while (a != NULL && b != NULL) 
    {
        if (a->data == b->data) 
        {
            push((&tail->next), a->data);
            tail = tail->next;
            a = a->next;
            b = b->next;
        }
        // Advance the smaller list 
        else if (a->data < b->data)
            a = a->next;
        else
            b = b->next;
    }
    return (dummy.next);
}
  
// UTILITY FUNCTIONS 
/* Function to insert a node at 
   the beginning of the linked list */
void push(Node** head_ref, int new_data)
{
    // Allocate node 
    Node* new_node = 
          (Node*)malloc(sizeof(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;
}
  
/* Function to print nodes in 
   a given linked list */
void printList(Node* node)
{
    while (node != NULL) 
    {
        cout << node->data <<" ";
        node = node->next;
    }
}
  
// Driver code
int main()
{
    // Start with the empty lists 
    Node* a = NULL;
    Node* b = NULL;
    Node* intersect = NULL;
  
    /* Let us create the first sorted 
       linked list to test the functions
       Created linked list will be 
       1->2->3->4->5->6 */
    push(&a, 6);
    push(&a, 5);
    push(&a, 4);
    push(&a, 3);
    push(&a, 2);
    push(&a, 1);
  
    /* Let us create the second sorted 
       linked list. Created linked list 
       will be 2->4->6->8 */
    push(&b, 8);
    push(&b, 6);
    push(&b, 4);
    push(&b, 2);
  
    // Find the intersection two linked lists 
    intersect = sortedIntersect(a, b);
  
    cout << 
    "Linked list containing common items of a & b ";
    printList(intersect);
}


C++
// C++ program to implement
// the above approach
#include 
using namespace std;
  
// Link list node 
struct Node 
{
    int data;
    struct Node* next;
};
  
struct Node* sortedIntersect(struct Node* a,
                             struct Node* b)
{    
    // Base case 
    if (a == NULL || b == NULL)
        return NULL;
  
    // If both lists are non-empty 
  
    /* Advance the smaller list and
       call recursively */
    if (a->data < b->data)
        return sortedIntersect(a->next, b);
  
    if (a->data > b->data)
        return sortedIntersect(a, b->next);
  
    // Below lines are executed only
    // when a->data == b->data
    struct Node* temp = 
           (struct Node*)malloc(sizeof(struct Node));
    temp->data = a->data;
  
    // Advance both lists and call recursively
    temp->next = sortedIntersect(a->next, 
                                 b->next);
    return temp;
}
  
// UTILITY FUNCTIONS 
/* Function to insert a node at 
   the beginning of the 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;
}
  
/* Function to print nodes in
   a given linked list */
void printList(struct Node* node)
{
    while (node != NULL)
    {
        cout << " " << node->data;
        node = node->next;
    }
}
  
// Driver code
int main()
{    
    // Start with the empty lists 
    struct Node* a = NULL;
    struct Node* b = NULL;
    struct Node* intersect = NULL;
  
    /* Let us create the first sorted
       linked list to test the functions
       Created linked list will be 
       1->2->3->4->5->6 */
    push(&a, 6);
    push(&a, 5);
    push(&a, 4);
    push(&a, 3);
    push(&a, 2);
    push(&a, 1);
  
    /* Let us create the second sorted 
       linked list. Created linked list 
       will be 2->4->6->8 */
    push(&b, 8);
    push(&b, 6);
    push(&b, 4);
    push(&b, 2);
  
    // Find the intersection two linked lists 
    intersect = sortedIntersect(a, b);
  
    cout << "Linked list containing " << 
            "common items of a & b ";
    printList(intersect);
  
    return 0;
}
// This code is contributed by shivanisinghss2110


输出:

Linked list containing common items of a & b 
2 4 6 

复杂性分析:

  • 时间复杂度: O(m+n) 其中 m 和 n 分别是第一个和第二个链表中的节点数。
    只需要遍历一次列表。
  • 辅助空间: O(min(m, n))。
    输出列表最多可以存储 min(m,n) 个节点。

方法2递归解决方案。
方法:
递归方法与上述两种方法非常相似。构建一个递归函数,它接受两个节点并返回一个链表节点。比较两个列表的第一个元素。

  • 如果它们相似,则使用两个列表的下一个节点调用递归函数。用当前节点的数据创建一个节点,并将递归函数返回的节点放到所创建节点的next指针上。返回创建的节点。
  • 如果值不相等,则删除两个列表中较小的节点并调用递归函数。

下面是上述方法的实现:

C++

// C++ program to implement
// the above approach
#include 
using namespace std;
  
// Link list node 
struct Node 
{
    int data;
    struct Node* next;
};
  
struct Node* sortedIntersect(struct Node* a,
                             struct Node* b)
{    
    // Base case 
    if (a == NULL || b == NULL)
        return NULL;
  
    // If both lists are non-empty 
  
    /* Advance the smaller list and
       call recursively */
    if (a->data < b->data)
        return sortedIntersect(a->next, b);
  
    if (a->data > b->data)
        return sortedIntersect(a, b->next);
  
    // Below lines are executed only
    // when a->data == b->data
    struct Node* temp = 
           (struct Node*)malloc(sizeof(struct Node));
    temp->data = a->data;
  
    // Advance both lists and call recursively
    temp->next = sortedIntersect(a->next, 
                                 b->next);
    return temp;
}
  
// UTILITY FUNCTIONS 
/* Function to insert a node at 
   the beginning of the 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;
}
  
/* Function to print nodes in
   a given linked list */
void printList(struct Node* node)
{
    while (node != NULL)
    {
        cout << " " << node->data;
        node = node->next;
    }
}
  
// Driver code
int main()
{    
    // Start with the empty lists 
    struct Node* a = NULL;
    struct Node* b = NULL;
    struct Node* intersect = NULL;
  
    /* Let us create the first sorted
       linked list to test the functions
       Created linked list will be 
       1->2->3->4->5->6 */
    push(&a, 6);
    push(&a, 5);
    push(&a, 4);
    push(&a, 3);
    push(&a, 2);
    push(&a, 1);
  
    /* Let us create the second sorted 
       linked list. Created linked list 
       will be 2->4->6->8 */
    push(&b, 8);
    push(&b, 6);
    push(&b, 4);
    push(&b, 2);
  
    // Find the intersection two linked lists 
    intersect = sortedIntersect(a, b);
  
    cout << "Linked list containing " << 
            "common items of a & b ";
    printList(intersect);
  
    return 0;
}
// This code is contributed by shivanisinghss2110

输出:

Linked list containing common items of a & b 
2 4 6

复杂性分析:

  • 时间复杂度: O(m+n) 其中 m 和 n 分别是第一个和第二个链表中的节点数。
    只需要遍历一次列表。
  • 辅助空间: O(max(m, n))。
    输出列表最多可以存储 m+n 个节点。

有关详细信息,请参阅有关两个排序链表的交集的完整文章!