单链表归并排序-O(nlogn)
由 王宇 原创并发布:
- 代码采用Doxygen注释
- 在以下环境中编译运行通过:Linux Puppy Tahr 6.0.5 kernel 3.14.56 gcc 4.8.4
/** * @file link_list_sort.c * * @brief 单链表的归并排序,需要保证O(nlgn) * * 思路:采用二分法,和归并操作, * 及将单链平分成两组,归并操作后合并成一个链。采用递归,重复以上操作。 * * @author WangYu <wangyuxxx@163.com> * @data 2016-09-27 * @version 1.0 */ #include<stdio.h> #include<stdlib.h> typedef struct LinkList_s { int value; /// 值 struct LinkList_s *next; /// 单链的下一个节点 }LinkList_t; /** * @brief 从单链表的中间分成 a, b 两组 * * 思路:分别采用快慢步长,快步长是慢的两倍,当快步长到达链表尾部时,慢步长刚好在链表中间 * * @param [in] head 单链头 * @param [out] a组 b组 * @retval 空 */ void getMiddle(LinkList_t *head, LinkList_t **a, LinkList_t **b) { LinkList_t *fast = NULL; LinkList_t *slow = NULL; LinkList_t *previous; if (head != NULL && head->next != NULL) { fast = head; slow = head; while (slow != NULL && fast != NULL) { if (slow->next == NULL) { break; } previous = slow; slow = slow->next; if (fast->next != NULL) { fast = fast->next->next; } else { break; } } previous->next = NULL; // a组的最后一个节点的Next 为NULL; *a = head; *b = slow; } } /** * @breif 归并操作,并合并两组 * * 将单链表在中间分成a b两组, 归并操作并合并后的链表:sortList * * 归并操作: * * 对比两个分组,将较小的先放入sortList * 将第一组剩余的放入sortList * 将第二组剩余的放入sortList * * @param [in] a组 b组 * @retval 返回合并后的链 */ LinkList_t *mergeLinkList(LinkList_t *a, LinkList_t *b) { LinkList_t *sortList = NULL, *sortListHead = NULL; if ( a == NULL && b != NULL ) { return b; } else if (a != NULL && b == NULL) { return a; } else if (a == NULL && b == NULL){ return NULL; } // 准备并备份排序好的链表头 if ( a->value < b->value ) { sortListHead = a; a = a->next; } else { sortListHead = b; b = b->next; } sortList = sortListHead ; // 对比两组,将较小的先插入到sortList尾部 while (a != NULL && b!= NULL) { if ( a->value < b->value ) { sortList->next = a; a = a->next; } else { sortList->next = b; b = b->next; } sortList = sortList->next; } // 将a组中剩余部分插入到sortList尾部 while (a != NULL) { sortList->next = a; a = a->next; sortList = sortList->next; } // 将b组中剩余部分插入到sortList尾部 while (b != NULL) { sortList->next = b; b = b->next; sortList = sortList->next; } return sortListHead; } /** * @breif 递归二分链表并排序 * @param [in] head 单链头 * @retval 返回排序后的链 */ LinkList_t *sortLinkList(LinkList_t *head) { LinkList_t *leftLinkList, *rightLinkList; if (head == NULL) { return NULL; } else if (head->next == NULL) { return head; } getMiddle(head, &leftLinkList, &rightLinkList); leftLinkList = sortLinkList(leftLinkList); rightLinkList = sortLinkList(rightLinkList); return mergeLinkList(leftLinkList, rightLinkList); } /** * @breif 建立一个简单的单链表,用于测试排序 * @retval 返回单链表 */ LinkList_t *createLinkList() { int i; LinkList_t *head = NULL, *current = NULL, *previous = NULL; // 10 个元素,从大到小 for (i = 10; i > 0; i--) { current = (LinkList_t*)malloc(sizeof(LinkList_t)); if (current == NULL) { perror("Error: malloc \n"); } current->value = i; current->next = NULL; if (head == NULL) { head = current; previous = current; } else { previous->next = current; previous = current; } } return head; } int main(){ LinkList_t *head = NULL; head = createLinkList(); head = sortLinkList(head); while (head != NULL) { printf("%d\n", head->value); head = head->next; } exit(0); }
相关推荐
用链表和队列实现了归并排序,用MinGW实现,进行了大量数据实验,和通过数组实现相比比较省空间但是不省时间。
用分而治之思想对单链表进行归并排序,程序中用到类模版和面向对象思想.
用C语言编写的有关,两个单链表的归并排序操作.
以单链表为存储结构, 实现二路归并排序的算法, 要求链表不另外占用存储空间, 排序过程中不移动结点中的元素, 只改各链结点中的指针
主要介绍了C语言数据结构 链表与归并排序实例详解的相关资料,需要的朋友可以参考下
[算法]快速排序,归并排序,堆排序的数组和单链表实现 数组和链表.pdf
[算法]快速排序,归并排序,堆排序的数组和单链表实现 (1) 数组和链表.pdf
C语言中数据结构之链表归并排序实例代码 问题 设有两个无头结点的单链表,头指针分别为ha,hb,链中有数据域data,链域next,两链表的数据都按递增排序存放,现要求将hb表归到ha表中,且归并后ha仍递增序,归并中...
c++描述归并排序,vs2005环境下,单链表
单链表的创建,排序,归并,插入删除定位和获得元素,计算元素个数,打印链表
单链表的归并排序,你可以用它来实现一个单链表的归并排序。
单链表归并排序 双向链表 循环链表 链表中查找元素、添加元素的时间复杂度分析 数组和链表的不同区别在哪里 使用链表实现LRU 3. 栈 栈的基本概念 链式栈 栈是否为空 括号匹配 如何实现浏览器的前进和后退 4. 队列 ...
C#,双向链表(Doubly Linked List)归并排序(Merge Sort)算法与源代码 1 双向链表 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一...
1、链表排序 [问题描述] 建立一个...设计要求:利用随机函数产生10个样本,每个样本有20000随机整数,利用直接插入排序、希尔排序,冒泡排序、快速排序、选择排序、堆排序,归并排序,基数排序八种排序方法进行排序
冒泡排序、快速排序、归并排序,向链表中添加和删除数据
代码如下:/* 对单链表进行排序处理*/struct LNode *sort(struct LNode *head){ LinkList *p; int n,i,j; int temp; n = ListLength(head); if(head == NULL || head->next == NULL) return head; p = head->...
5-14 归并排序时间复杂度及排序算法复杂度对比 5-15 二分查找 5-16 二分查找时间复杂度 六、树和树的算法 6-01 树的概念 6-02 二叉树的概念 6-03 二叉树的广度优先遍历 6-04 二叉树的实现 6-05 二叉树的先序...
包括了:串的顺序存储、单链表结点的插入、单链表结点的删除、堆排序、二叉排序树的删除、二叉排序树的生成、二叉树的建立、二分查找、归并排序、基数排序、快速排序、邻接表表示的图的广度优先遍历、邻接表表示的图...