简体   繁体   English

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

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

I am trying to perform an insertion-sort function on a doubly linked list in the C programming language.我正在尝试在 C 编程语言的双向链表上执行插入排序 function。 When I run the code with this function on a doubly linked list of 1<-->3<-->7<-->4<-->9 I get a sorted output.当我在1<-->3<-->7<-->4<-->9的双向链表上运行带有此 function 的代码时,我得到一个排序的 output。 However, When I run this code on a doubly linked list of 5<-->3<-->7<-->4<-->9 I get a blank output (and yes it still compiles and runs).但是,当我在5<-->3<-->7<-->4<-->9的双向链表上运行此代码时,我得到一个空白 output (是的,它仍然可以编译和运行)。

I cannot figure out why it is returning a blank output when the first node has greater value than the second.当第一个节点的值大于第二个节点时,我无法弄清楚为什么它返回一个空白 output 。 I would guess it has something to do with my if statement?我猜这与我的 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;
        }
    }
}

There are multiple problems in your code:您的代码中有多个问题:

  • you perform a single scan through the list, swapping adjacent nodes that are out of order.您对列表执行单次扫描,交换无序的相邻节点。 This loop does not handle the case of a node that should move left by more than one position.此循环不处理应向左移动多个 position 的节点的情况。
  • the code crashes if tempB is null, ie: if the 2 initial nodes of the list should be swapped.如果tempB是 null,则代码崩溃,即:如果应该交换列表的 2 个初始节点。
  • list->head should be updated if the first node changes.如果第一个节点发生变化,则应该更新list->head
  • the temporary variable names are confusing, esp tempC that is equal to tempA , and the initial order is not tempA -> tempB -> tempC -> tempD .临时变量名称令人困惑,尤其是tempC等于tempA ,并且初始顺序不是tempA -> tempB -> tempC -> tempD
  • for insertion sort, you should move the current node to its position among the nodes sorted so far and skip to the next node until you reach the end of the list.对于插入排序,您应该将当前节点移动到到目前为止已排序的节点中的 position 并跳到下一个节点,直到到达列表的末尾。

Here is a modified version:这是修改后的版本:

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;
    }
}

You need to learn to separate concerns in your code.您需要学习在代码中分离关注点。 An insertion sort takes an input list or array and returns an output list or array.插入排序接受输入列表或数组并返回 output 列表或数组。 So to start with, you need a function that either takes a List** and returns void , or it takes a List* and returns a List* .因此,首先,您需要一个 function ,它要么接受List**并返回void ,要么接受List*并返回List* Logically you need to do three things correctly, 1) iterate over the input list, 2) Remove a node from the input list without breaking 1, 3) insert into the output list at the correct position for the sort order.从逻辑上讲,您需要正确地做三件事,1)遍历输入列表,2)从输入列表中删除一个节点而不破坏 1、3)在正确的 position 列表中插入 output 列表以进行排序。 That amounts to three functions.这相当于三个功能。

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

InsertionSort just loops over the it's input, calling Remove , without loosing track of the head or tail pointer, depending on which way you're moving through the list, and then calls SortedInsert with the node it just removed from the head or tail of the pList. InsertionSort只是循环它的输入,调用Remove ,而不会丢失头或尾指针的轨道,具体取决于您在列表中移动的方式,然后使用刚刚从头或尾删除的节点调用SortedInsert列表。 SortedInsert then iterates through pList looking for the correct place to insert pNode and then returns the new head of the list, which might just be pNode . SortedInsert然后遍历pList寻找插入pNode的正确位置,然后返回列表的新头部,它可能只是pNode

It's just easier to think about one operation at a time, and the code you write will be simpler and easier to understand and debug.一次只考虑一项操作更容易,您编写的代码将更简单,更易于理解和调试。 In fact, you can test SortedInsert first, to make sure it's working, then test Remove , and then move on to to InsertionSort .事实上,您可以先测试SortedInsert以确保它正常工作,然后测试Remove ,然后继续进行InsertionSort You'll need to learn how to use your debugger and make yourself familiar with stepping through your code and checking the state of your variables.您需要学习如何使用调试器并熟悉如何逐步执行代码并检查变量的 state。 A fourth function, PrintList is probably on order here as well.第四个 function, PrintList也可能在这里订购。

I am not going to write a bunch of code or be really explicit about the algorithm details, because you can get that with an SO or Google search, and this seems like an obvious homework assignment.我不打算写一堆代码或对算法细节非常明确,因为你可以通过 SO 或谷歌搜索得到,这似乎是一个明显的家庭作业。

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

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