glib中单双向链表的归并排序

来源:互联网 发布:怎么修改jenkins端口 编辑:程序博客网 时间:2024/05/21 11:24
在glib库中,双向链表的排序是采用归并排序的方法

代码如下:

GList *g_list_sort (GList        *list,     GCompareFunc  compare_func){  return g_list_sort_real (list, (GFunc) compare_func, NULL);    }static GList* g_list_sort_real (GList    *list,  GFunc     compare_func,  gpointer  user_data){  GList *l1, *l2;    if (!list)     return NULL;  if (!list->next)     return list;    l1 = list;   l2 = list->next;  while ((l2 = l2->next) != NULL)    {      if ((l2 = l2->next) == NULL) break;      l1 = l1->next;    }  l2 = l1->next;   // 指向链表中间节点  l1->next = NULL;   return g_list_sort_merge (g_list_sort_real (list, compare_func, user_data),    g_list_sort_real (l2, compare_func, user_data),    compare_func,    user_data);}

主要函数g_list_sort_real中,while循环表示l1每前进一步,l2就前进2步,故最终得到l2指向链表中间的节点。之后调用g_list_sort_merge去合并排序这两个子链表。如果两个子链表点已经排好序,那么直接合并排序。

最核心的合并排序过程代码如下:
static GList *g_list_sort_merge (GList     *l1,    GList     *l2,   GFunc     compare_func,   gpointer  user_data){  GList list, *l, *lprev;  gint cmp;  l = &list;   lprev = NULL;  while (l1 && l2)    {      cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);      if (cmp <= 0)        {  l->next = l1;  l1 = l1->next;        }       else {  l->next = l2;  l2 = l2->next;        }      l = l->next;      l->prev = lprev;       lprev = l;    }  l->next = l1 ? l1 : l2;  l->next->prev = l;  return list.next;}

此排序过程有点类似于STL中的set容器的set_*算法,所以说,这个过程有个前提就是2个链表l1和l2必须是已经排序的。

细看整个排序过程的代码,其实此算法也可以用于单链表的排序过程(因为它并没有利用prev域)。

如果你阅读过STL源代码的话,STL的std::list用的也是归并排序。它开辟了16个list内存空间,不过采用的是迭代的解法。



原创粉丝点击