zoukankan      html  css  js  c++  java
  • 求链表的并集和交集

    给定2个链表,求这2个链表的并集(链表)和交集(链表)。不要求并集(链表)和交集(链表)中的元素有序。

    如,输入:

    List1: 10->15->4->20

    List2: 8->4->2->10

    输出:

    交集(链表):4->10

    并集(链表):2->8->20->4->15->10

    方法一(简单、直观的方法):

            下面是得到2个链表的并集和交集的简单算法。

            InterSection(list1,list2): 初始化结果链表为空,遍历链表1,在链表2中查找它的每一元素,如果链表2中也有这个元素,则将该元素插入到结果链表中。

            Union(list1,list2): 初始化结果链表为空,将链表1中的所有元素都插入到结果链表中。遍历链表2,如果结果链表中没有该元素,则插入,否则跳过该元素。

    1. #include <stdio.h>  
    2. #include <stdlib.h>  
    3.   
    4. /*Link list node*/  
    5. struct node  
    6. {  
    7.     int data;  
    8.     struct node* next;  
    9. };  
    10.   
    11. /* A utility function to insert a node at the begining of a linked list */  
    12. void push(struct node **head_ref, int new_data);  
    13.   
    14. /* A utility function to chec if given data is present in a list */  
    15. bool isPresent(struct node *head, int data);  
    16.   
    17. /* Function to get union of two linked lists head1 and head2*/  
    18. struct node *getUnion(struct node *head1, struct node *head2)  
    19. {  
    20.     struct node *result = NULL;  
    21.     struct node *t1 = head1, *t2 = head2;  
    22.   
    23.     //Insert all elements of list1 to result list  
    24.     while(t1 != NULL)  
    25.     {  
    26.         push(&result, t1->data);  
    27.         t1 = t1->next;  
    28.     }  
    29.   
    30.     //Insert those elements of list2 which are not present in result list  
    31.     while(t2 != NULL)  
    32.     {  
    33.         if(!isPresent(result, t2->data))  
    34.             push(&result, t2->data);  
    35.         t2 = t2->next;  
    36.     }  
    37.   
    38.     return result;  
    39. }  
    40.   
    41. /* Function to get intersection of two linked lists head1 and head2 */  
    42. struct node *getIntersection(struct node *head1, struct node *head2)  
    43. {  
    44.     struct node *result = NULL;   
    45.     struct node *t1 = head1;  
    46.   
    47.     //Traverse list1 and search each element of it in list2. If the element  
    48.     //is present in list2, then insert the element to result  
    49.     while( t1 != NULL )  
    50.     {  
    51.         if(isPresent(head2, t1->data))  
    52.             push(&result, t1->data);  
    53.         t1 = t1->next;  
    54.     }  
    55.   
    56.     return result;  
    57. }  
    58.   
    59. /* A utility function to insert a node at the begining of a linked list */  
    60. void push(struct node**head_ref, int new_data)  
    61. {  
    62.     /*allocate node*/  
    63.     struct node* new_node = (struct node*)malloc(sizeof(struct node));  
    64.   
    65.     /* put in the data */  
    66.     new_node->data = new_data;  
    67.   
    68.     /*link the old list off the new node*/  
    69.     new_node->next = (*head_ref);  
    70.   
    71.     /* move the head to point to the new node*/  
    72.     (*head_ref) = new_node;  
    73. }  
    74.   
    75. /*A utility function fto print a linked list*/  
    76. void printList(struct node *node)  
    77. {  
    78.     while( node != NULL )  
    79.     {  
    80.         printf("%d ", node->data);  
    81.         node = node->next;  
    82.     }  
    83. }  
    84.   
    85. /*A utility function that returns true  if data is present in  
    86.   linked list else reurn false */  
    87. bool isPresent(struct node *head, int data)  
    88. {  
    89.     struct node *t = head;  
    90.     while(t != NULL)  
    91.     {  
    92.         if( t->data == data )  
    93.             return 1;  
    94.         t = t->next;  
    95.     }  
    96.     return 0;  
    97. }  
    98.   
    99. /* Drier program to test above function*/  
    100. int main()  
    101. {  
    102.     /* Start with the empty list */  
    103.     struct node* head1 = NULL;  
    104.     struct node* head2 = NULL;  
    105.     struct node* intersecn = NULL;  
    106.     struct node* unin = NULL;  
    107.   
    108.     /*create a linked lits 10->15->5->20 */  
    109.     push (&head1, 20);  
    110.     push (&head1, 4);  
    111.     push (&head1, 15);  
    112.     push (&head1, 10);  
    113.   
    114.     /*create a linked lits 8->4->2->10 */  
    115.     push (&head2, 10);  
    116.     push (&head2, 2);  
    117.     push (&head2, 4);  
    118.     push (&head2, 8);  
    119.   
    120.     intersecn = getIntersection (head1, head2);  
    121.     unin = getUnion (head1, head2);  
    122.   
    123.     printf ("  First list is  ");  
    124.     printList (head1);  
    125.   
    126.     printf ("  Second list is  ");  
    127.     printList (head2);  
    128.   
    129.     printf ("  Intersection list is  ");  
    130.     printList (intersecn);  
    131.   
    132.     printf ("  Union list is  ");  
    133.     printList (unin);  
    134.   
    135.     printf(" ");   
    136.     return 0;  
    137. }  

            时间复杂度:在这个程序中,链表的并和交操作的时间复杂度都是O(mn),m是链表1的元素个数,n是链表2的元素个素。

    方法2(使用归并排序):

            使用这个方法,求2个链表的并集和交集的操作非常相似。首先,将对2个链表进行排序,然后遍历2个链表,得到2个了表的交集和并集。

    下面是具体实现步骤:

    1. 用归并排序对第1个链表进行排序,这个操作的时间复杂度为O(mLogm).[点击这里查看详细]

    2. 用归并排序堆第2个链表进行排序,这个操作的时间复杂度为O(nLogn).

    3. 线性遍历2个有序的链表,得到2个链表的交集和并集。这个操作的时间复杂度为O(m+n).[这步类似于求有序数组的交集和并集,后者之前已经实现过,点击这里查看详细]

    这个方法的时间复杂度是O(mLogm+ nLogn),优于第一种方法。

    方法3(hash法):

    Union(list1, list2)

            首先初始化结果链表为NULL,创建一个空的hash表,遍历两个链表,将链表中的元素插入到hash表,插入元素的时候同时检查hash表中时候是否已经存在该元素,如果hash表中不存在该元素,则同时将该元素插入到结果链表中,如果hash表中已经存在,则忽略该元素,继续遍历下一个元素。

    InterSection(list1, list2)

            首先初始化结果链表为NULL,创建一个空的hash表,遍历list1,将list1中的每一个元素都插入到hash表中。然后遍历list2,对于list2中的元素,如果已经存在于hash表中,则将该元素插入到结果链表,如果不存在与hash表中,则忽略该元素,继续遍历下一个元素。

    具体实现可以用hashMap,将链表中的元素当做key,value为此元素出现的次数。

    具体代码可参考下面代码修改后实现

    package com.xtfggef.hashmap;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * 打印在数组中出现n/2以上的元素
     * 利用一个HashMap来存放数组元素及出现的次数
     * @author erqing
     *
     */
    public class HashMapTest {
        
        public static void main(String[] args) {
            
            int [] a = {2,3,2,2,1,4,2,2,2,7,9,6,2,2,3,1,0};
            
            Map<Integer, Integer> map = new HashMap<Integer,Integer>();
            for(int i=0; i<a.length; i++){
                if(map.containsKey(a[i])){
                    int tmp = map.get(a[i]);
                    tmp+=1;
                    map.put(a[i], tmp);
                }else{
                    map.put(a[i], 1);
                }
            }
            Set<Integer> set = map.keySet();//------------1------------
            for (Integer s : set) {
                if(map.get(s)>=a.length/2){
                    System.out.println(s);
                }
            }//--------------2---------------
        }
    }

            这个方法的效率取决与hash表的实现技术,一般情况下,这个方法都比上面两种要好。

    原文地址:http://www.geeksforgeeks.org/archives/18615?utm_source=rss&utm_medium=rss&utm_campaign=union-and-intersection-of-two-linked-lists

  • 相关阅读:
    【Luogu】P1402 酒店之王 题解
    CSP/S 2019 游记
    【Luogu】P1306 斐波那契公约数 题解
    【Luogu】P1072 Hankson 的趣味题 题解
    字符串函数
    对数换底公式
    round(x,y)和format(x,y)
    约束和索引
    复合主键对外键的影响
    外键
  • 原文地址:https://www.cnblogs.com/bendantuohai/p/4496559.html
Copyright © 2011-2022 走看看