Advertisement
avp210159

list2.h

Dec 24th, 2013
957
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.05 KB | None | 0 0
  1. #ifndef _LIST2_H
  2. #define _LIST2_H
  3. // avp 2012, 2013 Более привычный (чем циклический в list.h) 2-напрвленный список.
  4.  
  5. #include <stddef.h>
  6.  
  7. // list2 item. Embed it in data structure. Поля связи во всех элементах списка.
  8. typedef struct l2item {
  9.   struct l2item *next,
  10.     *prev;
  11. } List2;
  12.  
  13. // list2 head (представляет список в программе)
  14. typedef struct l2header {
  15.   struct l2item *head,
  16.     *tail;
  17.   size_t size;
  18. } List2head;
  19.  
  20. #define LIST2_HEAD(name) \
  21.   List2head name = {0,0,0}
  22.  
  23. #define INIT_LIST2_HEAD(ptr) ({List2head *_p = (ptr);   \
  24.       _p->head = 0; _p->tail = 0; _p->size = 0; })
  25.  
  26. #define list2_power(ptr) ((ptr)->size)
  27.  
  28. /*
  29.  * Добавляем новую голову
  30.  * returns предыдущую голову
  31.  */
  32. static inline List2 *
  33. list2_add (List2 *_new, List2head *head)
  34. {
  35.   List2 *ret = head->head;
  36.  
  37.   _new->prev = NULL;
  38.   if (!ret)
  39.     head->tail = _new;
  40.   head->head = _new;
  41.   head->size++;
  42.   return _new->next = ret;
  43. }
  44.  
  45. /*
  46.  * Добавляем новый хвост
  47.  * returns предыдущий хвост
  48.  */
  49. static inline List2 *
  50. list2_add_tail (List2 *_new, List2head *head)
  51. {
  52.   List2 *ret = head->tail;
  53.  
  54.   _new->next = NULL;
  55.   if (!ret)
  56.     head->head = _new;
  57.   else
  58.     ret->next = _new;
  59.   head->tail = _new;
  60.   head->size++;
  61.   return _new->prev = ret;
  62. }
  63.  
  64. /*
  65.  * Удаляем голову и
  66.  * returns ee
  67.  */
  68. static inline List2 *
  69. list2_del_head (List2head *head)
  70. {
  71.   List2 *ret = head->head;
  72.  
  73.   if (ret) {
  74.     if (!(head->head = ret->next)) // empty
  75.       head->tail = 0;
  76.     else
  77.       head->head->prev = 0;
  78.  
  79.     head->size--;
  80.     ret->next = ret->prev = 0;
  81.   }
  82.   return ret;
  83. }
  84.  
  85. /*
  86.  * Удаляем  хвост и
  87.  * returns его
  88.  */
  89. static inline List2 *
  90. list2_del_tail (List2head *head)
  91. {
  92.   List2 *ret = head->tail;
  93.  
  94.   if (ret) {
  95.     if (!(head->tail = ret->prev)) // empty
  96.       head->head = 0;
  97.     else
  98.       head->tail->next = 0;
  99.  
  100.     head->size--;
  101.     ret->next = ret->prev = 0;
  102.   }
  103.   return ret;
  104. }
  105.  
  106. /*
  107.  * Удаляем  элемент списка
  108.  * returns голову списка
  109.  */
  110. static inline List2 *
  111. list2_del_item (List2 *item, List2head *head)
  112. {
  113.   if (item->next)
  114.     item->next->prev = item->prev;
  115.   else // correct tail
  116.     head->tail = item->prev;
  117.   if (item->prev)
  118.     item->prev->next = item->next;
  119.   else // correct head
  120.     head->head = item->next;
  121.  
  122.   head->size--;
  123.   item->next = item->prev = 0;
  124.   return head->head;
  125. }
  126.  
  127. /**
  128.  ** from include/linux/list.h **
  129.  * list_entry - get the struct for this entry
  130.  * @ptr:    the &struct l2item pointer.
  131.  * @type:   the type of the struct this is embedded in.
  132.  * @member: the name of the l2item_struct within the struct.
  133.  */
  134. #define list_entry(ptr, type, member) \
  135.     ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
  136.  
  137. /*
  138.  * Записывем первый список в хвост второго списка
  139.  * первый обнуляется
  140.  */
  141. static inline void
  142. list2_append (List2head *list1, List2head *list2)
  143. {
  144.   if (list1->size) {
  145.     if (list2->size) {
  146.       list2->tail->next = list1->head;
  147.       list1->head->prev = list2->tail;
  148.     } else {
  149.       list2->head = list1->head;
  150.     }
  151.     list2->tail = list1->tail;
  152.     list2->size += list1->size;
  153.     list1->head = list1->tail = 0;
  154.     list1->size = 0;
  155.   }
  156. }
  157.  
  158. /*
  159.  * Вставим первый список перед заданным элементом второго
  160.  * (если item == NULL, то в начало)
  161.  * первый список обнуляется
  162.  */
  163. static inline void
  164. list2_insert (List2head *list1, List2head *list2, List2 *item)
  165. {
  166.   if (list1->size) {
  167.     if (list2->size) {
  168.       if (item && item->prev) {
  169.     item->prev->next = list1->head;
  170.     list1->head->prev = item->prev;
  171.     list1->tail->next = item;
  172.     item->prev = list1->tail;
  173.       } else { // вставим list1 перед list2
  174.     list2->head->prev = list1->tail;
  175.     list1->tail->next = list2->head;
  176.     list2->head = list1->head;
  177.       }
  178.     } else {
  179.       list2->head = list1->head;
  180.       list2->tail = list1->tail;
  181.     }
  182.     list2->size += list1->size;
  183.     list1->head = list1->tail = 0;
  184.     list1->size = 0;
  185.   }
  186. }
  187.  
  188. // pos указатель на List2 в элементе списка
  189. #define list2_for_each(pos, _head) \
  190.   for (pos = (_head)->head; pos; pos = pos->next)
  191. // _head указатель на список (заголовок списка)
  192. #define list2_for_each_prev(pos, _head) \
  193.   for (pos = (_head)->tail; pos; pos = pos->prev)
  194. // tmp переменная типа List2 *
  195. // в этом цикле можно удалять pos
  196. #define list2_for_each_safe(pos,tmp,_head)       \
  197.   for (pos = (_head)->head, tmp = pos? pos->next: 0; pos; \
  198.        pos = tmp, tmp = pos? pos->next: 0)
  199.  
  200. /************  list mergesort avp 2013
  201.   http://www.williamspublishing.com/PDF/978-5-8459-1650-1/part.pdf
  202. *************/
  203.  
  204. /*
  205.  * Слияние списков, завершающихся next == 0,
  206.  * в соответствии с fcmp(elem1, elem2) (returns N < 0, 0 for EQUAL or N > 0)
  207.  * l1, l2 указатели на первые элементы списков
  208.  * указатели prev становятся неактуальными
  209.  */
  210. static List2 *
  211. merge2lists (List2 *l1, List2 *l2, int (*fcmp)(List2 *e1, List2 *e2))
  212. {
  213.   List2 result = {0, 0}, *cur = &result;
  214.  
  215.   while (l1 && l2)
  216.     if (fcmp(l1, l2) <= 0) {
  217.       cur->next = l1; cur = l1; l1 = l1->next;
  218.     } else {
  219.       cur->next = l2; cur = l2; l2 = l2->next;
  220.     }
  221.   cur->next = (l1 ? l1 : l2); // оставшиеся элементы запишем в хвост result
  222.   return result.next;
  223. }
  224.  
  225. /*
  226.  * Сортировка списка по указателю на его первый элемент
  227.  * в соответствии с fcmp(elem1, elem2) (returns N < 0, 0 for EQUAL or N > 0)
  228.  * указатели prev становятся неактуальными
  229.  */
  230. static List2 *
  231. l_mergesort (List2 *list, int (*fcmp)(List2 *e1, List2 *e2))
  232. {
  233.   if (list == 0 || list->next == 0) return list;
  234.   List2 *a = list, *b = list->next;
  235.   // хитро делим список пополам. b бежит через элемент
  236.   while (b && b->next) {
  237.     list = list->next; b = b->next->next;
  238.   }
  239.   b = list->next;
  240.   list->next = 0; // разделим, terminate первую половину
  241.  
  242.   return merge2lists(l_mergesort(a, fcmp), l_mergesort(b, fcmp), fcmp);
  243. }
  244.  
  245. /*
  246.  * mergesort двусвязного списка
  247.  * в соответствии с fcmp(elem1, elem2) (returns N < 0, 0 for EQUAL or N > 0)
  248.  */
  249. static void
  250. list2_sort (List2head *list, int (*fcmp)(List2 *e1, List2 *e2))
  251. {
  252.   if (list->size < 2)
  253.     return;
  254.   List2 *slist = l_mergesort(list->head, fcmp), *p = 0;
  255.  
  256.   list->head = slist;
  257.   // восстановим указатели prev
  258.   while (slist) {
  259.     slist->prev = p;
  260.     p = slist;
  261.     slist = slist->next;
  262.   }
  263.   list->tail = p;
  264. }
  265.  
  266. // up_mergesort (UNSTABLE!!!) and not faster...
  267.  
  268. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement