仅使用一个函数分段错误对链表进行合并排序
Mergesort on a linked-list using only one function, segmentation fault
我需要实现的功能:struct listnode * mergesort(struct listnode *data)
我的教授提供了 main() 函数测试代码。我只需要提交 mergesort 功能。他告诉我们用 C 或 C++ 来做,但他给我们的测试代码 main() 是用 C 写的。
这是我现在的代码:
我可以编译它,但是当我 运行 它时,它崩溃了。我检查了调试器,它给了我分段错误。我也不太确定这个函数是否正确,因为我无法通过 main() 中的测试点。
#include <stdio.h>
#include <stdlib.h>
struct listnode { struct listnode * next;
long value; } ;
struct listnode * mergesort(struct listnode *data)
{ int temp, finished = 0;
struct listnode *tail, *head, *ahead, *bhead, *atail, *btail;
if ( data == NULL )
return;
//Split
ahead = atail = head = data; // first item
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
atail = atail->next;
btail = btail->next;
if( btail->next != NULL)
btail = btail->next;
}
bhead = atail->next; // disconnect the parts
atail->next = NULL;
//sort
mergesort(ahead);
mergesort(bhead);
//merge
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 != NULL)
tail->next = ahead;
else
tail->next = bhead;
return(head);
}
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 ( data == NULL )
return;
你应该return NULL。
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
如果btail设置为head->next。如果 head->next 为 NULL,则您正在尝试检查循环 NULL->next != NULL,这不是问题。
if( btail->next != NULL)
btail = btail->next;
}
检查->next前需要检查btail是否为NULL。就在上面,你正在设置 btail = btail->next;所以它可以设置为 NULL。
上面的循环也有同样的问题,你需要在 next 做之前检查 null。
下面的代码可能有问题,但是上面的代码需要更多的错误检查。
使用指向指针的指针合并两个已排序列表的示例函数。由于您只允许一个函数,因此您必须将此逻辑合并到您的 mergesort() 函数中。如果这是家庭作业,那么您似乎得到了太多帮助,但我不确定如何解释此示例中显示的想法。
NODE * MergeLists(NODE *pSrc1, NODE *pSrc2)
{
NODE *pDst = NULL; /* destination head ptr */
NODE **ppDst = &pDst; /* ptr to head or prev->next */
while(1){
if(pSrc1 == NULL){
*ppDst = pSrc2;
break;
}
if(pSrc2 == NULL){
*ppDst = pSrc1;
break;
}
if(pSrc2->data < pSrc1->data){ /* if src2 < src1 */
*ppDst = pSrc2;
pSrc2 = *(ppDst = &(pSrc2->next));
continue;
} else { /* src1 <= src2 */
*ppDst = pSrc1;
pSrc1 = *(ppDst = &(pSrc1->next));
continue;
}
}
return pDst;
}
我需要实现的功能:struct listnode * mergesort(struct listnode *data)
我的教授提供了 main() 函数测试代码。我只需要提交 mergesort 功能。他告诉我们用 C 或 C++ 来做,但他给我们的测试代码 main() 是用 C 写的。
这是我现在的代码: 我可以编译它,但是当我 运行 它时,它崩溃了。我检查了调试器,它给了我分段错误。我也不太确定这个函数是否正确,因为我无法通过 main() 中的测试点。
#include <stdio.h>
#include <stdlib.h>
struct listnode { struct listnode * next;
long value; } ;
struct listnode * mergesort(struct listnode *data)
{ int temp, finished = 0;
struct listnode *tail, *head, *ahead, *bhead, *atail, *btail;
if ( data == NULL )
return;
//Split
ahead = atail = head = data; // first item
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
atail = atail->next;
btail = btail->next;
if( btail->next != NULL)
btail = btail->next;
}
bhead = atail->next; // disconnect the parts
atail->next = NULL;
//sort
mergesort(ahead);
mergesort(bhead);
//merge
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 != NULL)
tail->next = ahead;
else
tail->next = bhead;
return(head);
}
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 ( data == NULL )
return;
你应该return NULL。
btail = head->next; // second item
while(btail->next != NULL) // anything left
{
如果btail设置为head->next。如果 head->next 为 NULL,则您正在尝试检查循环 NULL->next != NULL,这不是问题。
if( btail->next != NULL)
btail = btail->next;
}
检查->next前需要检查btail是否为NULL。就在上面,你正在设置 btail = btail->next;所以它可以设置为 NULL。
上面的循环也有同样的问题,你需要在 next 做之前检查 null。
下面的代码可能有问题,但是上面的代码需要更多的错误检查。
使用指向指针的指针合并两个已排序列表的示例函数。由于您只允许一个函数,因此您必须将此逻辑合并到您的 mergesort() 函数中。如果这是家庭作业,那么您似乎得到了太多帮助,但我不确定如何解释此示例中显示的想法。
NODE * MergeLists(NODE *pSrc1, NODE *pSrc2)
{
NODE *pDst = NULL; /* destination head ptr */
NODE **ppDst = &pDst; /* ptr to head or prev->next */
while(1){
if(pSrc1 == NULL){
*ppDst = pSrc2;
break;
}
if(pSrc2 == NULL){
*ppDst = pSrc1;
break;
}
if(pSrc2->data < pSrc1->data){ /* if src2 < src1 */
*ppDst = pSrc2;
pSrc2 = *(ppDst = &(pSrc2->next));
continue;
} else { /* src1 <= src2 */
*ppDst = pSrc1;
pSrc1 = *(ppDst = &(pSrc1->next));
continue;
}
}
return pDst;
}