C作业留了一个对链表进行排序的作业。手头会写的排序没几个。。。又不想用最简单的泡排,,,就尝试了用归并排序。
对链表进行归并排序的有点麻烦的地方在于怎么找到链表的中间节点,由于链表不支持随机访问,所以这里是个比较蛋疼的地方。 最普通的方法就是先遍历一遍,测出链表的长度,然后再根据长度遍历到那个中间的位置。 后来围观同学的代码发现了个好方法。
定义两个指针,开始时都指向表头(是指存有数据的表头,不是那个不存数据只指向下一个位置的表头),然后两个都开始向表尾移动,不过两者的速度不一样,一个每次只走一步,另一个一次走两步。当有一个走到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;
}