链表上的合并排序
MergeSort on Linked List
我的编码相当糟糕,所以我真的需要一些帮助,因为这个作业要在星期三之前交。我见过 mergesort 通常分为三个函数:(mergesort、sortedmerge、frontbacksplit 等)。但是我的教授基于数组的合并排序是在一个函数中完成的,所以我假设他希望我们也只对这个链表使用一个函数……(除非可以在一个函数中实现一个函数?)我们必须写好函数"struct listnode * mergesort(struct listnode *data)"提交给他。到目前为止我所做的(我认为)是将链表拆分为 2 个子链表,但现在我不知道如何 "recursively" 对它们进行排序。教授告诉我们用 C 或 C++ 编写函数,但是他在下面提供给我们的测试代码是用C语言编写的。
#include <stdio.h>
#include <stdlib.h>
struct listnode { struct listnode * next;
long value; } ;
//This is the function I need to write:
struct listnode * mergesort(struct listnode *data)
{ int temp, finished = 0;
struct listnode *i, *j, *tail, *head, *ahead, *bhead, *atail, *btail;
if ( a == NULL )
return;
head = data;
tail = head->next;
ahead = head;
bhead = tail;
i = ahead;
j = bhead;
tail = tail->next;
while ( tail !=NULL ) {
atail = tail;
i->next = atail;
i = i->next;
tail = tail->next;
btail = tail;
j->next = btail;
j = j->next;
tail = tail->next;
}
};
//Testing code provided by professor:
int main(void)
{
long i;
struct listnode *node, *tmpnode, *space;
space = (struct listnode *) malloc( 500000*sizeof(struct listnode));
for( i=0; i< 500000; i++ )
{ (space + i)->value = 2*((17*i)%500000);
(space + i)->next = space + (i+1);
}
(space+499999)->next = NULL;
node = space;
printf("\n prepared list, now starting sort\n");
node = mergesort(node);
printf("\n checking sorted list\n");
for( i=0; i < 500000; i++)
{ if( node == NULL )
{ printf("List ended early\n"); exit(0);
}
if( node->value != 2*i )
{ printf("Node contains wrong value\n"); exit(0);
}
node = node->next;
}
printf("Sort successful\n");
exit(0);
}
一般做法:
if( list contains 0 or 1 item)
return the list; // it is already sorted
split the list into halves;
mergesort( first part);
mergesort( second part);
merge sorted parts;
return the merged list;
列表包含 0 或 1 项条件:
head == NULL || head->next == NULL
要拆分列表,您需要找到它的中间部分:
ahead = atail = head; // first item
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
atail = atail->next;
btail = btail->next;
if( btail->next)
btail = btail->next;
}
bhead = atail->next; // disconnect the parts
atail->next = NULL;
合并两个排序列表:
if(ahead->value <= bhead->value) // set the head of resulting list
head = tail = ahead, ahead = ahead->next;
else
head = tail = bhead, bhead = bhead->next;
while(ahead && bhead)
if(ahead->value <= bhead->value) // append the next item
tail = tail->next = ahead, ahead = ahead->next;
else
tail = tail->next = bhead, bhead = bhead->next;
if(ahead) // once one part got exhausted append the remaining other part
tail->next = ahead;
else
tail->next = bhead;
我的编码相当糟糕,所以我真的需要一些帮助,因为这个作业要在星期三之前交。我见过 mergesort 通常分为三个函数:(mergesort、sortedmerge、frontbacksplit 等)。但是我的教授基于数组的合并排序是在一个函数中完成的,所以我假设他希望我们也只对这个链表使用一个函数……(除非可以在一个函数中实现一个函数?)我们必须写好函数"struct listnode * mergesort(struct listnode *data)"提交给他。到目前为止我所做的(我认为)是将链表拆分为 2 个子链表,但现在我不知道如何 "recursively" 对它们进行排序。教授告诉我们用 C 或 C++ 编写函数,但是他在下面提供给我们的测试代码是用C语言编写的。
#include <stdio.h>
#include <stdlib.h>
struct listnode { struct listnode * next;
long value; } ;
//This is the function I need to write:
struct listnode * mergesort(struct listnode *data)
{ int temp, finished = 0;
struct listnode *i, *j, *tail, *head, *ahead, *bhead, *atail, *btail;
if ( a == NULL )
return;
head = data;
tail = head->next;
ahead = head;
bhead = tail;
i = ahead;
j = bhead;
tail = tail->next;
while ( tail !=NULL ) {
atail = tail;
i->next = atail;
i = i->next;
tail = tail->next;
btail = tail;
j->next = btail;
j = j->next;
tail = tail->next;
}
};
//Testing code provided by professor:
int main(void)
{
long i;
struct listnode *node, *tmpnode, *space;
space = (struct listnode *) malloc( 500000*sizeof(struct listnode));
for( i=0; i< 500000; i++ )
{ (space + i)->value = 2*((17*i)%500000);
(space + i)->next = space + (i+1);
}
(space+499999)->next = NULL;
node = space;
printf("\n prepared list, now starting sort\n");
node = mergesort(node);
printf("\n checking sorted list\n");
for( i=0; i < 500000; i++)
{ if( node == NULL )
{ printf("List ended early\n"); exit(0);
}
if( node->value != 2*i )
{ printf("Node contains wrong value\n"); exit(0);
}
node = node->next;
}
printf("Sort successful\n");
exit(0);
}
一般做法:
if( list contains 0 or 1 item)
return the list; // it is already sorted
split the list into halves;
mergesort( first part);
mergesort( second part);
merge sorted parts;
return the merged list;
列表包含 0 或 1 项条件:
head == NULL || head->next == NULL
要拆分列表,您需要找到它的中间部分:
ahead = atail = head; // first item
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
atail = atail->next;
btail = btail->next;
if( btail->next)
btail = btail->next;
}
bhead = atail->next; // disconnect the parts
atail->next = NULL;
合并两个排序列表:
if(ahead->value <= bhead->value) // set the head of resulting list
head = tail = ahead, ahead = ahead->next;
else
head = tail = bhead, bhead = bhead->next;
while(ahead && bhead)
if(ahead->value <= bhead->value) // append the next item
tail = tail->next = ahead, ahead = ahead->next;
else
tail = tail->next = bhead, bhead = bhead->next;
if(ahead) // once one part got exhausted append the remaining other part
tail->next = ahead;
else
tail->next = bhead;