对链表进行归并排序
2014-03-09 23:24
363 查看
C作业留了一个对链表进行排序的作业。手头会写的排序没几个。。。又不想用最简单的泡排,,,就尝试了用归并排序。
对链表进行归并排序的有点麻烦的地方在于怎么找到链表的中间节点,由于链表不支持随机访问,所以这里是个比较蛋疼的地方。 最普通的方法就是先遍历一遍,测出链表的长度,然后再根据长度遍历到那个中间的位置。 后来围观同学的代码发现了个好方法。
定义两个指针,开始时都指向表头(是指存有数据的表头,不是那个不存数据只指向下一个位置的表头),然后两个都开始向表尾移动,不过两者的速度不一样,一个每次只走一步,另一个一次走两步。当有一个走到NULL时停止(其实除了一般都是指快指针走到NULL)。这样那个慢的指针很明显这时就走到了链表的中间。那么这时,我们就完成了归并排序唯一一个麻烦的地方,将大问题分治为两个小问题。那么剩下的就是一般归并排序的思路了,将一个大问题分治为小问题解决。
那么下面就放出代码,写的不好还请轻喷
对链表进行归并排序的有点麻烦的地方在于怎么找到链表的中间节点,由于链表不支持随机访问,所以这里是个比较蛋疼的地方。 最普通的方法就是先遍历一遍,测出链表的长度,然后再根据长度遍历到那个中间的位置。 后来围观同学的代码发现了个好方法。
定义两个指针,开始时都指向表头(是指存有数据的表头,不是那个不存数据只指向下一个位置的表头),然后两个都开始向表尾移动,不过两者的速度不一样,一个每次只走一步,另一个一次走两步。当有一个走到NULL时停止(其实除了一般都是指快指针走到NULL)。这样那个慢的指针很明显这时就走到了链表的中间。那么这时,我们就完成了归并排序唯一一个麻烦的地方,将大问题分治为两个小问题。那么剩下的就是一般归并排序的思路了,将一个大问题分治为小问题解决。
那么下面就放出代码,写的不好还请轻喷
#include <stdio.h> typedef struct list { int num; struct list *next; }list; list *list_generate(); list *list_scan(); void list_clear(list *head); void list_push_back(list *head, int val); void list_print(list *head); list *list_merge(list *head1, list *head2); list *list_sort(list *head); int main() { list *a_head; printf("Please input a list(end by -1):"); a_head = list_scan(); a_head->next = list_sort(a_head->next); list_print(a_head); list_clear(a_head); return 0; } list *list_generate() { list *head = (list*)malloc(sizeof(list)); head->next = NULL; return head; } list *list_scan() { int tmp; list *head = list_generate(); while (scanf("%d", &tmp) && tmp != -1) list_push_back(head, tmp); return head; } void list_clear(list *head) { list *tmp; while (head != NULL) { tmp = head->next; free(head); head = tmp; } } void list_push_back(list *head, int val) { list *to_insert = (list*)malloc(sizeof(list)), *tmp = head; to_insert->next = NULL, to_insert->num = val; while (tmp->next != NULL) tmp = tmp->next; tmp->next = to_insert; } void list_print(list *head) { list *cur = head->next; if (cur == NULL) { puts("There is no element in this list"); return; } puts("The new list is:"); while (cur != NULL) { printf("%d", cur->num); if (cur->next != NULL) putchar(' '); else puts(""); cur = cur->next; } } list *list_merge(list *head1, list *head2) { list *tmp; if (head1 == NULL) return head2; if (head2 == NULL) return head1; if (head1->num < head2->num) { tmp = head1; head1 = head1->next; } else { tmp = head2; head2 = head2->next; } tmp->next = list_merge(head1, head2); return tmp; } list *list_sort(list *head) { if (head == NULL) return 0; list *new_head = head; list *head1 = head; list *head2 = head; while (head2->next != NULL && head2->next->next != NULL) { head1 = head1->next; head2 = head2->next->next; } if (head1->next == NULL) return new_head; head2 = head1->next; head1->next = NULL; head1 = head; new_head = list_merge(list_sort(head1), list_sort(head2)); return new_head; }
相关文章推荐
- [C/C++]反转链表
- 关于指针的一些事情
- 动易2006序列号破解算法公布
- C#数据结构与算法揭秘二
- 浅析STL中的常用算法
- 关于c语言指针的两处小tip分享
- 浅析iterator与指针的区别
- 探讨C++中数组名与指针的用法比较分析
- C++中指向对象的常指针与指向常对象的指针详解
- 指向变量的常指针与指向常变量的指针详细解析
- php中将指针移动到数据集初始位置的实现代码[mysql_data_seek]
- C语言指针学习经验总结浅谈
- JavaScript 组件之旅(二)编码实现和算法
- Linux内核链表实现过程
- C/C++中指针和引用之相关问题深入研究
- 指针与const限定符的使用分析
- c++ 指针与引用的区别介绍及使用说明
- 找出链表倒数第n个节点元素的二个方法
- c++函数中的指针参数与地址参数区别介绍
- javascript function、指针及内置对象