Advertisement
B1KMusic

Linked List Insertion Sort Benchmark

Dec 3rd, 2018
309
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.97 KB | None | 0 0
  1. /* A benchmark of three different implementations of selection sort on a linked list
  2.  * 1: singly-linked (reverse loop)
  3.  * 2: singly-linked (recursive)
  4.  * 3: doubly-linked (normal loop)
  5.  * A stack overflow can be simulated with valgrind: valgrind --main-stacksize=1000 ./a.out
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <time.h>
  11.  
  12. #define CMP_T(name, expr) \
  13.     int name(int a, int b){return (expr);}
  14.  
  15. typedef int (*cmp_t)(int,int);
  16.  
  17. struct list {
  18.     struct list *next;
  19.     struct list *prev;
  20.     // used to allow for both single-linked and double-linked implementations (for benchmarking purposes)
  21.     // every use of prev is marked with a comment saying "use of list.prev"
  22.     int data;
  23. };
  24.  
  25. struct list *
  26. list_new(int data)
  27. {
  28.     struct list *list = malloc(sizeof *list);
  29.  
  30.     list->data = data;
  31.     list->next = NULL;
  32.     list->prev = NULL; // use of list.prev
  33.     return list;
  34. }
  35.  
  36. struct list *
  37. list_addl(struct list *list, struct list *node)
  38. {
  39.     node->next = list;
  40.     list->prev = node; // use of list.prev
  41.     return node;
  42. }
  43.  
  44. struct list *
  45. list_get_prev(struct list *list, struct list *node)
  46. {
  47.     if(list == node)
  48.         return NULL;
  49.  
  50.     while(list->next != node)
  51.         list = list->next;
  52.  
  53.     return list;
  54. }
  55.  
  56. void
  57. list_swap_next(struct list *node)
  58. {
  59.     struct list *next = node->next;
  60.  
  61.     if(next == NULL)
  62.         return;
  63.  
  64.     node->data ^= next->data;
  65.     next->data ^= node->data;
  66.     node->data ^= next->data;
  67. }
  68.  
  69. struct list *
  70. list_random(int size)
  71. {
  72.     struct list *list = list_new(rand() % (size * 10));
  73.     struct list *new;
  74.  
  75.     for(int i = 0; i < size - 1; ++i){
  76.         new = list_new(rand() % (size * 10));
  77.         list = list_addl(list, new);
  78.     }
  79.  
  80.     return list;
  81. }
  82.  
  83. struct list *
  84. list_end(struct list *list)
  85. {
  86.     while(list->next != NULL)
  87.         list = list->next;
  88.  
  89.     return list;
  90. }
  91.  
  92. void
  93. list_print(struct list *list)
  94. {
  95.     while(list != NULL){
  96.         printf("%i -> ", list->data);
  97.         list = list->next;
  98.     }
  99.  
  100.     printf("(null)\n");
  101. }
  102.  
  103. void
  104. list_free(struct list *list)
  105. {
  106.     struct list *next;
  107.  
  108.     while(list != NULL){
  109.         next = list->next;
  110.         free(list);
  111.         list = next;
  112.     }
  113. }
  114.  
  115. void
  116. list_ins_sort_inner(struct list *sublist, cmp_t cmp)
  117. {
  118.     while(sublist->next != NULL && cmp(sublist->next->data, sublist->data) == -1){
  119.         list_swap_next(sublist);
  120.         sublist = sublist->next;
  121.     }
  122. }
  123.  
  124. // use of list.prev
  125. void
  126. list_ins_sort_double_inner(struct list *sublist, cmp_t cmp)
  127. {
  128.     while(sublist->prev != NULL && cmp(sublist->prev->data, sublist->data) == 1){
  129.         list_swap_next(sublist->prev);
  130.         sublist = sublist->prev;
  131.     }
  132. }
  133.  
  134. // implementation of ins_sort with singly-linked list
  135. void
  136. list_ins_sort(struct list *list, cmp_t cmp)
  137. {
  138.     for(struct list *selnode = list_end(list); selnode != NULL; selnode = list_get_prev(list, selnode))
  139.         list_ins_sort_inner(selnode, cmp);
  140. }
  141.  
  142. // implementation of ins_sort with singly-linked list. Recursive-optimized edition.
  143. void
  144. list_ins_sort_recursive(struct list *list, cmp_t cmp)
  145. {
  146.     if(list->next != NULL)
  147.         list_ins_sort_recursive(list->next, cmp);
  148.  
  149.     list_ins_sort_inner(list, cmp);
  150. }
  151.  
  152. // implementation of ins_sort with doubly-linked list.
  153. void
  154. list_ins_sort_double(struct list *list, cmp_t cmp)
  155. {
  156.     for(struct list *selnode = list; selnode != NULL; selnode = selnode->next)
  157.         list_ins_sort_double_inner(selnode, cmp);
  158. }
  159.  
  160. CMP_T(num_cmp, (a < b) ? (-1) : (a > b ? 1 : 0))
  161.  
  162. int
  163. main(void)
  164. {
  165.     struct list *list;
  166.     int list_size = 20000;
  167.  
  168.     srand(time(NULL));
  169.     list = list_random(list_size);
  170.     list_print(list);
  171.  
  172.     // Un-comment the function being benchmarked
  173.     //list_ins_sort(list, num_cmp); // avg 1.8s
  174.     //list_ins_sort_recursive(list, num_cmp); // avg 1.2s (note: stack overflow risk)
  175.     //list_ins_sort_double(list, num_cmp); // avg 1.3s
  176.  
  177.     list_print(list);
  178.     list_free(list);
  179.  
  180.     return 0;
  181. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement