繁体   English   中英

如何按升序对双向链表进行排序?

[英]How do I sort a doubly-linked list in ascending order?

我正在尝试在 C 编程语言的双向链表上执行插入排序 function。 当我在1<-->3<-->7<-->4<-->9的双向链表上运行带有此 function 的代码时,我得到一个排序的 output。 但是,当我在5<-->3<-->7<-->4<-->9的双向链表上运行此代码时,我得到一个空白 output (是的,它仍然可以编译和运行)。

当第一个节点的值大于第二个节点时,我无法弄清楚为什么它返回一个空白 output 。 我猜这与我的 if 语句有关?

void insertion_sort_increasing(struct List *list)
{
    struct Node *current_node = list->head; //initialize current_node
    struct Node *tempA;
    struct Node *tempB;
    struct Node *tempC;
    struct Node *tempD;

    if (current_node == NULL) {
        printf("Empty List.");
    } else {
        current_node = current_node->next;
        while (current_node != NULL) { //iterates doubly linked list
            if (current_node->prev->StudentID > current_node->StudentID) {
                tempA = current_node; //(3 in this case)
                tempB = current_node->prev->prev; //(NULL in this case)
                tempC = tempA->next->prev;
                tempD = tempB->next;

                tempA->next->prev = tempA->prev; // 5<--7
                tempB->next->prev = tempC;       // 3<--5
                tempB->next = tempA->prev->next; // NULL-->3
                tempA->prev->next = tempA->next; // 5-->7
                tempA->next = tempD;             // 3-->5
                tempA->prev = tempD->prev;       // NULL<--3
                if (tempB == NULL) {
                    list->head = tempB->next;    // 3 = head
                }
            }
            current_node = current_node->next;
        }
    }
}

您的代码中有多个问题:

  • 您对列表执行单次扫描,交换无序的相邻节点。 此循环不处理应向左移动多个 position 的节点的情况。
  • 如果tempB是 null,则代码崩溃,即:如果应该交换列表的 2 个初始节点。
  • 如果第一个节点发生变化,则应该更新list->head
  • 临时变量名称令人困惑,尤其是tempC等于tempA ,并且初始顺序不是tempA -> tempB -> tempC -> tempD
  • 对于插入排序,您应该将当前节点移动到到目前为止已排序的节点中的 position 并跳到下一个节点,直到到达列表的末尾。

这是修改后的版本:

void insertion_sort_increasing(struct List *list)
{
    struct Node *current_node = list->head;

    while (current_node != NULL) {
        struct Node *next = current_node->next;
        while (current_node->prev && current_node->prev->StudentID > current_node->StudentID) {
            // swap current_node and its predecessor (tempC and tempB)
            struct Node *tempA = current_node->prev->prev;
            struct Node *tempB = current_node->prev;
            struct Node *tempC = current_node;
            struct Node *tempD = current_node->next;

            if (tempA) {
                tempA->next = tempC;
            } else {
                list->head = tempC;
            }
            tempC->prev = tempA;
            tempC->next = tempB;
            tempB->prev = tempC;
            tempB->next = tempD;
            if (tempD) {
                tempD->prev = tempB;
            } else {
                list->tail = tempB;
            }
        }
        current_node = next;
    }
}

您需要学习在代码中分离关注点。 插入排序接受输入列表或数组并返回 output 列表或数组。 因此,首先,您需要一个 function ,它要么接受List**并返回void ,要么接受List*并返回List* 从逻辑上讲,您需要正确地做三件事,1)遍历输入列表,2)从输入列表中删除一个节点而不破坏 1、3)在正确的 position 列表中插入 output 列表以进行排序。 这相当于三个功能。

List *InsertionSort(List * pList) {...}
List *SortedInsert(List *pList, List *pNode) {...}
List *Remove(List *pNode) {...}

InsertionSort只是循环它的输入,调用Remove ,而不会丢失头或尾指针的轨道,具体取决于您在列表中移动的方式,然后使用刚刚从头或尾删除的节点调用SortedInsert列表。 SortedInsert然后遍历pList寻找插入pNode的正确位置,然后返回列表的新头部,它可能只是pNode

一次只考虑一项操作更容易,您编写的代码将更简单,更易于理解和调试。 事实上,您可以先测试SortedInsert以确保它正常工作,然后测试Remove ,然后继续进行InsertionSort 您需要学习如何使用调试器并熟悉如何逐步执行代码并检查变量的 state。 第四个 function, PrintList也可能在这里订购。

我不打算写一堆代码或对算法细节非常明确,因为你可以通过 SO 或谷歌搜索得到,这似乎是一个明显的家庭作业。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM