zoukankan      html  css  js  c++  java
  • 有序单链表的合并

      #返回上一级

    @Author: 张海拔

    @Update: 2014-01-23

    @Link: http://www.cnblogs.com/zhanghaiba/p/3531142.html

      1 /*
      2  *Author: ZhangHaiba
      3  *Date: 2014-1-23
      4  *File: sorted_list_merge.c
      5  *
      6  *a demo shows how to merge two sorted single linked list by
      7  *creating a new list or in-place.
      8  */
      9 
     10 #include <stdio.h>
     11 #include <stdbool.h>
     12 #include <stdlib.h>
     13 #define INF 0x7fffffff
     14 #define CMD_LNE 128
     15 
     16 typedef struct node* link;
     17 typedef struct node {
     18     int item;
     19     link next;
     20 }node;
     21 
     22 //public
     23 link NODE(int item, link next);
     24 link list_create(int n);
     25 link sorted_list_merge_create1(link list_src_a, link list_src_b);
     26 link sorted_list_merge_create2(link list_src_a, link list_src_b);
     27 link sorted_list_merge_in_place1(link list_src_a, link list_src_b);
     28 link sorted_list_merge_in_place2(link list_src_a, link list_src_b);
     29 void list_travel(link head);
     30 void list_destroy(link head);
     31 //private
     32 //accept list without Head Node, and return list without Head Node as well
     33 link sorted_list_merge_create_iter(link a, link b);
     34 link sorted_list_merge_in_place_iter(link a, link b);
     35 link sorted_list_merge_create_rec(link a, link b);
     36 link sorted_list_merge_in_place_rec(link a, link b);
     37 
     38 
     39 int main(void)
     40 {
     41     int len_a, len_b;
     42 
     43     scanf("%d", &len_a);
     44     link list_a = list_create(len_a);
     45     printf("list_a travel: ");
     46     list_travel(list_a);
     47 
     48     scanf("%d", &len_b);
     49     link list_b = list_create(len_b);
     50     printf("list_b travel: ");
     51     list_travel(list_b);
     52 
     53     printf("create list_c by using(merging) list_a and list_b nodes.
    ");
     54     //link list_c = sorted_list_merge_create1(list_a, list_b);
     55     link list_c = sorted_list_merge_create2(list_a, list_b);
     56     printf("list_c travel: ");
     57     list_travel(list_c);
     58 
     59     printf("merge list_c and list_a to list_d.
    ");
     60     //link list_d = sorted_list_merge_in_place1(list_c, list_a);
     61     link list_d = sorted_list_merge_in_place2(list_c, list_a);
     62     printf("list_d travel: ");
     63     list_travel(list_d);
     64 
     65     list_c = list_a = NULL;
     66     list_destroy(list_b);
     67     printf("list_b destroyed!
    ");
     68     list_destroy(list_d);
     69     printf("list_d destroyed!
    ");
     70     return 0;
     71 }
     72 
     73 link NODE(int item, link next)
     74 {
     75     link born = malloc(sizeof (node));
     76     born->item = item;
     77     born->next = next;
     78     return born;
     79 }
     80 
     81 //tail insert
     82 link list_create(int n)
     83 {
     84     int i, item;
     85     link head = NODE(INF, NULL);
     86     link tail = head;
     87 
     88     for (i = 0; i < n; ++i) {
     89         scanf("%d", &item);
     90         tail->next = NODE(item, NULL);
     91         tail = tail->next;
     92     }
     93     return head;
     94 }
     95 
     96 //Iterative implementation begin here
     97 link sorted_list_merge_create_iter(link a, link b)
     98 {
     99     link tmp_head = NODE(INF, NULL);
    100     link c = tmp_head; //c as tail pointer for the list_c
    101 
    102     for (; a != NULL && b != NULL; c = c->next)
    103         if (a->item < b->item)
    104               c->next = NODE(a->item, NULL), a = a->next;
    105         else
    106             c->next = NODE(b->item, NULL), b = b->next;
    107     for (; a != NULL; c = c->next, a = a->next)
    108         c->next = NODE(a->item, NULL);
    109     for (; b != NULL; c = c->next, b = b->next)        
    110         c->next = NODE(b->item, NULL);
    111     link first = tmp_head->next;
    112     free(tmp_head);
    113     return first;
    114 }
    115 
    116 link sorted_list_merge_create1(link a, link b)
    117 {
    118     if (a == NULL || b == NULL)
    119         return NULL;
    120     return NODE(INF, sorted_list_merge_create_iter(a->next, b->next));
    121 }
    122 
    123 link sorted_list_merge_in_place_iter(link a, link b)
    124 {
    125     link tmp_head = NODE(INF, NULL);
    126     link c = tmp_head; //c as tail pointer for the list_c
    127 
    128     for (; a != NULL && b != NULL; c = c->next)
    129         if (a->item < b->item)
    130             c->next = a, a = a->next;
    131         else
    132             c->next = b, b = b->next;
    133     c->next = a != NULL ? a : b; //link left ordered list
    134     link first = tmp_head->next;
    135     free(tmp_head);
    136     return first;
    137 }
    138 
    139 link sorted_list_merge_in_place1(link a, link b)
    140 {
    141     if (a == NULL || b == NULL)
    142         return NULL;
    143     link head = NODE(INF, sorted_list_merge_in_place_iter(a->next, b->next));
    144     free(a);
    145     free(b);
    146     return head;
    147 }
    148 //Iterative implementation end here
    149 
    150 
    151 //Recursive implementation begin here
    152 link sorted_list_merge_create_rec(link a, link b)
    153 {
    154     link first = NULL;
    155 
    156     if (a == NULL) {
    157         link tmp_head = NODE(INF, NULL);
    158         link c = tmp_head; //c as tail pointer for left list
    159         while (b != NULL) {
    160             c->next = NODE(b->item, NULL);
    161             c = c->next;
    162             b = b->next;
    163         }
    164         link left = tmp_head->next;
    165         free(tmp_head);
    166         return left;
    167     }
    168     if (b == NULL) {
    169         link tmp_head = NODE(INF, NULL);
    170         link c = tmp_head; //c as tail pointer for left list
    171         while (a != NULL) {
    172             c->next = NODE(a->item, NULL);
    173             c = c->next;
    174             a = a->next;
    175         }
    176         link left = tmp_head->next;
    177         free(tmp_head);
    178         return left;
    179     }
    180     if (a->item < b->item) {
    181         first = NODE(a->item, NULL);
    182         first->next = sorted_list_merge_create_rec(a->next, b);
    183     } else {
    184         first = NODE(b->item, NULL);
    185         first->next = sorted_list_merge_create_rec(b->next, a);
    186     }
    187     return first;
    188 }
    189 
    190 link sorted_list_merge_create2(link a, link b)
    191 {
    192     if (a == NULL || b == NULL)
    193         return NULL;
    194     return NODE(INF, sorted_list_merge_create_rec(a->next, b->next));
    195 }
    196 
    197 link sorted_list_merge_in_place_rec(link a, link b)
    198 {
    199     if (a == NULL)
    200         return b;
    201     if (b == NULL)
    202         return a;
    203     link first = NULL;
    204     if (a->item < b->item) {
    205         first = a;
    206         first->next = sorted_list_merge_in_place_rec(a->next, b);
    207     } else {
    208         first = b;
    209         first->next = sorted_list_merge_in_place_rec(a, b->next);
    210     }
    211     return first;
    212 }
    213 
    214 link sorted_list_merge_in_place2(link a, link b)
    215 {
    216     if (a == NULL || b == NULL)
    217         return NULL;
    218     link head = NODE(INF, sorted_list_merge_in_place_rec(a->next, b->next));
    219     free(a);
    220     free(b);
    221     return head;
    222 }
    223 //Recursive implementation end here
    224 
    225 void list_travel(link head)
    226 {
    227     for (head = head->next; head != NULL; head = head->next)
    228         printf(head->next == NULL ? "%d
    " : "%d ", head->item);
    229 }
    230 
    231 void list_destroy(link head)
    232 {
    233     head->next == NULL ? free(head) : list_destroy(head->next);
    234 }

    测试示例:

    ZhangHaiba-MacBook-Pro:code apple$ ./a.out
    6
    30 53 65 77 88 99
    list_a travel: 30 53 65 77 88 99
    9
    11 22 33 44 55 100 120 199 211
    list_b travel: 11 22 33 44 55 100 120 199 211
    create list_c by using(merging) list_a and list_b nodes.
    list_c travel: 11 22 30 33 44 53 55 65 77 88 99 100 120 199 211
    merge list_c and list_a to list_d.
    list_d travel: 11 22 30 30 33 44 53 53 55 65 65 77 77 88 88 99 99 100 120 199 211
    list_b destroyed!
    list_d destroyed!

    单链表的合并,给出了两个接口(函数):sorted_list_merge_create()和sorted_list_merge_in_place()。分别对应非就地合并和就地合并。

    两个函数各有用武之地,非就地合并生成一个新链表,输入的两个链表还可以继续使用;

    就地合并则把输入的两个链表a和b合并为一个链表c,合并后a和b逻辑上就不存在了。

    由于这里操作的链表是:带头节点的单链表。

    考虑函数的复用性,首先设计的合并函数A:接收两个不带头节点的链表,返回一个不带头节点的(新)链表。

    带头节点的链表只是不带头节点的链表的一种限定(子集),

    所以通过设计一个外壳函数包装上一步实现的合并函数A,就可以实现带头节点的单链表合并的函数B。

    合并函数B:接收两个带头节点的链表,返回一个带头节点的(新)链表。规定传入链表的头节点不能为空,否则返回NULL。

    A函数对应上述实现中的

    sorted_list_merge_create_iter()和sorted_list_merge_create_rec()

    sorted_list_merge_in_place_iter()和sorted_list_merge_in_place_rec()

    下面从实现方法的角度做一个纵向对比——

    (1)迭代实现

    迭代实现中,借助了一个临时头节点,这样才能保存第一个节点的指针first,返回first之前先释放临时头节点

    1)非就地合并

    如果b遍历完了a还没完,则把a剩下的依次复制到新链表后面;b同理。

    2)就地合并

    如果b遍历完了a还没完,则把a剩下的链表一次链接到tail指针c中即可,效率很高的说;b同理。

    (2)递归实现

    1)非就地合并

    若链表a为空,则复制b剩下的链表(借助了临时头节点来实现,返回left前释放临时头节点);b同理。

    否则选较小的节点复制作为当前链表的根节点,然后合并剩下的链表作为子链表。

    2)就地合并

    若链表a为空,则直接返回链表b;b同理。

    否则选较小的节点作为当前链表的根节点,然后合并剩下的链表作为子链表。

    对于外壳函数,非就地合并没啥可说,就地合并返回前还需要释放a和b的头节点。

    客户端程序(主函数)中,就地合并c和a之后,有责任把c和a置为NULL,因为调用方知道此时c和a已经不存在了。

    小结:单链表的非就地合并和就地合并,都是利用了链表的“尾插法”来建表。区别是,前者生成节点,后者链入节点,且后者的效率会更高。

      #返回上一级

  • 相关阅读:
    CSS快速入门
    Kafka (一) 核心概念
    软件工程模型
    函数式编程
    spark计算操作整理
    HBase 文件合并
    HBase 数据存储结构
    目的论浅谈
    PHP8的注解
    JS的移入移除
  • 原文地址:https://www.cnblogs.com/zhanghaiba/p/3531142.html
Copyright © 2011-2022 走看看