c - C中链表的合并排序代码仅对一半元素进行排序

标签 c sorting mergesort

我有一些代码对包含字符串作为数据值的链接列表进行合并排序。我的目标是按字母顺序对链表中的节点进行排序。

这是我定义节点的方式:

struct Node { 
    void *data; 
    struct Node* next; 
}; 

这是我对主列表中的列表进行排序的调用:

int main() 
{ 

    struct Node* a = NULL; 
    struct Node* sorted = NULL;

    push(&a, "orange"); 
    push(&a, "banana"); 
    push(&a, "strawberry"); 
    push(&a, "apple"); 
    push(&a, "kiwi"); 
    push(&a, "grapes"); 

    sorted = MergeSort(a); 

    printf("Sorted Linked List is: \n"); 
    printList(sorted); 

    return 0; 
} 

push函数将一个元素插入到链表的开头,而 printList函数将打印列表中的每个元素,后跟换行符。

我可以确认pushprintList函数正常工作,因为列表中的所有元素 a当我测试时,它们按预期打印。

这是我用来按字母顺序对列表进行排序的代码:

/* sorts the linked list by changing next pointers (not data) */
struct Node* MergeSort(struct Node* headRef) 
{ 
    struct Node* head = headRef; 
    struct Node* a; 
    struct Node* b; 

    /* Base case -- length 0 or 1 */
    if ((head == NULL) || (head->next == NULL)) { 
        return headRef; 
    } 

    /* Split head into 'a' and 'b' sublists */
    FrontBackSplit(head, &a, &b); 

    /* Recursively sort the sublists */
    MergeSort(a); 
    MergeSort(b); 

    /* answer = merge the two sorted lists together */
    headRef = SortedMerge(a, b); 
    return headRef;
} 


struct Node* SortedMerge(struct Node* a, struct Node* b) 
{ 
    struct Node* result = NULL; 

    /* Base cases */
    if (a == NULL) 
        return (b); 
    else if (b == NULL) 
        return (a); 

    /* Pick either a or b, and recur */
    if (strcmp(a->data, b->data) <= 0) { 
        result = a; 
        result->next = SortedMerge(a->next, b); 
    } 
    else { 
        result = b; 
        result->next = SortedMerge(a, b->next); 
    } 
    return (result); 
} 

/* UTILITY FUNCTIONS */
/* Split the nodes of the given list into front and back halves, 
    and return the two lists using the reference parameters. 
    If the length is odd, the extra node should go in the front list. 
    Uses the fast/slow pointer strategy. */
void FrontBackSplit(struct Node* source, 
                    struct Node** frontRef, struct Node** backRef) 
{ 
    struct Node* fast; 
    struct Node* slow; 
    slow = source; 
    fast = source->next; 

    /* Advance 'fast' two nodes, and advance 'slow' one node */
    while (fast != NULL) { 
        fast = fast->next; 
        if (fast != NULL) { 
            slow = slow->next; 
            fast = fast->next; 
        } 
    } 

    /* 'slow' is before the midpoint in the list, so split it in two 
    at that point. */
    *frontRef = source; 
    *backRef = slow->next; 
    slow->next = NULL; 
} 

当我打印列表时sorted排序过程之后,我的输出如下所示:

Sorted Linked List is: 
grapes
kiwi
strawberry

这表明排序工作正常,但并非所有元素都被输出。我想知道为什么会出现这种情况?

最佳答案

/* Recursively sort the sublists */
MergeSort(a); 
MergeSort(b); 

这是有问题的部分。您正在对子列表进行排序,但在对它们进行排序后,您没有更新 ab 以指向列表相应的新头。

更改为

/* Recursively sort the sublists */
a = MergeSort(a); 
b = MergeSort(b); 

它的行为符合预期。

关于c - C中链表的合并排序代码仅对一半元素进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58466127/

相关文章:

收集值并将其存储在单独的变量中

c - 我怎样才能为 Windows 制作一个二进制文件,使非编码人员能够只获得一个可以提供给 gdb 的故障转储?

javascript - 在javascript中撤消对排序数组的排序

c++ - 合并排序算法。合并功能不起作用

algorithm - 如何更改合并排序以计算数组与排序数组的距离?

c - Toupper 不适用于 char 数组

c - 处理多种结构类型的队列 [C]

c - 如何使用 qsort 对结构进行排序?

c++ - 为什么我的选择排序返回的值不在原始 vector 中?

c++ - 归并排序的实现