简体   繁体   English

C中的双向链表排序问题

[英]doubly linked list in C sorting problems

I am trying to write a method that sorts the elements in a doubly linked list.我正在尝试编写一种对双向链表中的元素进行排序的方法。 The list is made up of structs with a forward and backward pointer (flink, blink) to the next element.该列表由具有指向下一个元素的前向和后向指针(flink、blink)的结构组成。 head->blink should be null, tail->flink should be null (aka not circular). head->blink 应该是 null,tail->flink 应该是 null(又名不是圆形)。 I tried a selection sort approach but I keep getting a segmentation fault.我尝试了一种选择排序方法,但我一直遇到分段错误。 I have isolated the problem into the commented lines.我已将问题隔离到注释行中。 However I included all of my code, the sort method is at the bottom.但是我包含了我的所有代码,排序方法在底部。

//header (dblLinkList.h)

#include <stdio.h>
#include <stdlib.h>

typedef struct _DblLinkList {
    struct _DblLinkList *flink;
    struct _DblLinkList *blink;
    int num;
} DblLinkList;

struct _DblLinkList *head, *tail;

struct _DblLinkList *init(int nElements);
void sort(struct _DblLinkList *listNode);
void print(struct _DblLinkList *listNode);

//implementation

#include <stdio.h>
#include <stdlib.h>
#include "dblLinkList.h"

int main() {
    struct _DblLinkList *list1 = init(2);
    printf("-----Head to Tail------\n");
    print(list1);
    printf("Sorting...\n");
    sort(list1);
    printf("-----Head to Tail------\n");
    print(list1);
}

struct _DblLinkList *init(int nElements) {
    struct _DblLinkList *listNode;
    int i = 0;

    for(i = 0; i < nElements; i++) {
        listNode = (struct _DblLinkList *)malloc(sizeof(struct _DblLinkList));
        listNode->num = random();

        if(head == NULL) {
            head = listNode;
            listNode->blink = NULL;
        } else {
            tail->flink = listNode;
            listNode->blink = tail;
        }
        tail = listNode;
        listNode->flink = NULL;
    }
    return listNode;
}

void print(struct _DblLinkList *listNode) {
    for(listNode = head; listNode != NULL; listNode = listNode->flink) {
        printf("%d\n", listNode->num);
    }
}

void sort(struct _DblLinkList *listNode) {
    //Not working properly
    struct _DblLinkList *listNode2;
    struct _DblLinkList *minNode;
    struct _DblLinkList *temp = (struct _DblLinkList *)malloc(sizeof(struct _DblLinkList));

    //start from the head and traverse the list
    for(listNode = head; listNode != NULL; listNode = listNode->flink) {
        minNode = listNode;
        listNode2 = listNode->flink;
        for(;listNode2 != NULL;  listNode2 = listNode2->flink) {
            if (listNode2->num < minNode->num) {
                minNode = listNode2;
            }
        }
//Problem Lies here vvvvvvvvvvvv
            temp->flink = listNode->flink;
            temp->blink = listNode->blink;  
            listNode->blink = listNode2;
            listNode->flink = listNode2->flink;
            listNode2->flink = temp;
            listNode2->blink = temp->blink; 
        printf("min: %d\n", minNode->num);
        }
    }
for(;listNode2 != NULL;  listNode2 = listNode2->flink)

This loop only exits when listNode2 is NULL .此循环仅在 listNode2 为NULL时退出 So we've established that at this point listNode2 == NULL .所以我们已经确定此时listNode2 == NULL

Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.你不应该跟随 NULL 指针,因为混乱和疯狂在它的尽头等待着你。

And here is what you're doing, breaking the second commandment这就是你正在做的,违反第二条诫命

listNode2->flink = temp;

Looks like listNode2 can be NULL after that for loop.看起来listNode2for循环之后可以是NULL You should check that before you try to access listNode2->flink .在尝试访问listNode2->flink之前,您应该检查一下。

I can see a few problems in the code:我可以在代码中看到一些问题:

  1. You keep inserting the same chunk of memory, temp when you are moving nodes around.当您移动节点时,您不断插入相同的 memory, temp块。
  2. When you are moving listnode away, listnode->flink->blink (before the move) still points to listnode .当您将listnode移开时, listnode->flink->blink (在移动之前)仍然指向listnode
  3. Same as #2, but for listnode->blink->flink与 #2 相同,但对于listnode->blink->flink
  4. When you move listnode, you potentially skip all the nodes between old position and listnode2 , as linstnode->flink is now listnode2->flink , which is not necessarily the old value.当您移动 listnode 时,您可能会跳过旧 position 和listnode2之间的所有节点,因为linstnode->flink现在是listnode2->flink ,这不一定是旧值。 This won't cause a crash, but it will leave some nodes unsorted.这不会导致崩溃,但会使某些节点未排序。
  5. When moving nodes around, I didn't see any special handling of head an tail , so they will probably point to weird nodes when you are done.在移动节点时,我没有看到任何对headtail的特殊处理,所以当你完成时它们可能会指向奇怪的节点。 One trick to handle this seamlessly is to make them into concrete _DblLinkList structures, so that the code is not riddled with if statements.无缝处理这个问题的一个技巧是将它们变成具体的_DblLinkList结构,这样代码就不会充满if语句。

There may be other problems.可能还有其他问题。

FTFY: still pretty ugly hack but should work

--- 2.c 2011-06-07 13:03:48.000000000 -0700
+++ 1.c 2011-06-07 13:49:18.000000000 -0700
@@ -7,7 +7,8 @@
     int num;
 } DblLinkList;

-struct _DblLinkList *head, *tail;
+struct _DblLinkList *head = NULL;
+struct _DblLinkList *tail = NULL;

 struct _DblLinkList *init(int nElements);
 void sort(struct _DblLinkList *listNode);
@@ -35,16 +36,16 @@
     for(i = 0; i < nElements; i++) {
         listNode = (struct _DblLinkList *)malloc(sizeof(struct _DblLinkList));
         listNode->num = random();
+               listNode->flink = NULL;
+               listNode->blink = NULL;

         if(head == NULL) {
             head = listNode;
-            listNode->blink = NULL;
         } else {
             tail->flink = listNode;
             listNode->blink = tail;
         }
         tail = listNode;
-        listNode->flink = NULL;
     }
     return listNode;
 }
@@ -55,29 +56,33 @@
     }
 }

-void sort(struct _DblLinkList *listNode) {
+void sort(struct _DblLinkList *_listNode) {
     //Not working properly
-    struct _DblLinkList *listNode2;
-    struct _DblLinkList *minNode;
-    struct _DblLinkList *temp = (struct _DblLinkList *)malloc(sizeof(struct _DblLinkList));
+       struct _DblLinkList* listNode = head;
+    struct _DblLinkList *listNode2 = NULL;
+    struct _DblLinkList *minNode = head;
+    struct _DblLinkList *temp = NULL;

     //start from the head and traverse the list
-    for(listNode = head; listNode != NULL; listNode = listNode->flink) {
-        minNode = listNode;
+    for(; listNode != NULL; listNode = listNode->flink) {
         listNode2 = listNode->flink;
         for(;listNode2 != NULL;  listNode2 = listNode2->flink) {
             if (listNode2->num < minNode->num) {
                 minNode = listNode2;
             }
-        }
-//Problem Lies here vvvvvvvvvvvv
-            temp->flink = listNode->flink;
-            temp->blink = listNode->blink;
-            listNode->blink = listNode2;
-            listNode->flink = listNode2->flink;
-            listNode2->flink = temp;
-            listNode2->blink = temp->blink;
+                       if (listNode->num > listNode2->num) {
+                               temp = listNode;
+                               listNode = listNode2;
+                               temp->flink = listNode2->flink;
+                               listNode->flink = temp;
+                               listNode->blink = temp->blink;
+                               listNode2 = temp;
+                               listNode2->blink = listNode;
+                               if (head == listNode2)
+                                       head = listNode;
+                       }
         printf("min: %d\n", minNode->num);
         }
     }
+}

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

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