【问题标题】:insertion sort doubly linked list插入排序双向链表
【发布时间】:2018-11-04 23:04:36
【问题描述】:

我正在尝试对 C 中的双向链表进行插入排序。在这种状态下,我的代码让我陷入了一个无休止的循环,吐出 8 和 9。

有人可以解释一下“insertionSort”方法应该如何设计吗?

我的链表被设计成包含头、上一个、下一个和一些数据。

这是我目前的代码

我的希望是空的。请帮忙。

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

typedef struct Node {

int data;
struct Node* next;
struct Node* previous;

}Node;

struct Node* head = NULL;
struct Node* current = NULL;
struct Node* headsorted = NULL;
int l = 0;
int empty = 1;
int length = 0;
int change = 0;

void InsertSort(){

Node* temp = (Node*)malloc(sizeof(struct Node));

temp = head;
current = head->next;

printf("\nInsert Sort begins...\n");

if (head != NULL && head->next != NULL)
{
   for (int i = 1; i < length; i++)
   {
        while(current->data > current->next->data && current->next != NULL && current != NULL)
        {
            temp = current;
            current = current->next;
            current->next = temp;
        }
   }
}
else
{
printf("\nList Error!\n");
}

temp = NULL;

}

void Insert(int x)
{
    Node* temp = (Node*)malloc(sizeof(struct Node));

    temp->data = x;
    temp->next = head;
    temp->previous = NULL;

   if (head != NULL)
   {
       head->previous = temp;
   }
    head = temp;
}

void Print(){

    struct Node* temp = head;
    printf("List is: ");
    while(temp != NULL)
    {
        printf(" %d", temp->data);
        temp = temp->next;
    }
}

int main()
{
    head = NULL;
    FILE * file = fopen("List.txt", "r");

    fscanf(file, "%d", &l);
    while (!feof (file))
    {
        Insert(l);
        fscanf(file, "%d", &l);
        length++;
    }
    fclose(file);

    Print();

    printf("\n\n\n");

    printf("data: %d next: %d   " , head->data, head->next->data);

    InsertSort();

    Print();

    return 0;
}

【问题讨论】:

  • temp = head;//???????空?
  • In InsertSort() 也许你需要 head = tmp ?
  • 我不这么认为,@purec。看起来InsertionSort() 中的malloc() 是一个红鲱鱼。该函数只是泄漏内存。
  • 奇怪的是,@TuğberkKaanDuman,while (!feof (file)) 的使用是个例外。或者至少,它不匹配总是错误的模式。这是因为文件的第一次读取被提升到循环之前,导致循环条件中的feof() 测试实际上是明智的。不过,为了清楚起见,我会将循环内的 fscanf() 调用移动到循环的最后一条语句。

标签: c doubly-linked-list insertion-sort


【解决方案1】:

有人可以解释一下“insertionSort”是如何 方法应该被设计?

首先,我建议去掉length 变量,或者至少不要在你的排序例程中使用它。它不是必需的,并且依赖它可能会过多地将您的思维转移到数组样式的实现上。当您发现 next 指针为 NULL 的节点时,您就知道您已到达列表的末尾。

其次,我重申我的评论,即您没有为双向链表正确执行节点交换。任何链表上的节点交换,无论是单链表还是双链表,都相当于从链表中完全提取第二个节点,然后将其重新插入到第一个节点之前。在通常影响三个节点的单链表中:除了两个被交换的节点外,第一个节点的前身。在双向链表中,它也会影响第二个的后继者。这在双向链接的情况下已经够混乱了,我建议将其明确地构建为先删除后插入。

但我也建议你退后一步,从高层次上看算法。它的工作原理是依次考虑每个节点,从第二个开始,如有必要,将其删除并重新插入到它之前的(排序的)子列表中的正确位置。那么,成对交换与它有什么关系呢? 什么都没有。在数组上实现这种排序时,这是一个方便的细节,但是在对链表进行排序时,它会做一些不必要的工作。

对于链表,尤其是双链表,我建议实现更直接地切入算法的抽象描述:

  1. 维护一个指针S,指向已排序的前导子列表的最后一个节点。最初,这将指向列表头。
  2. 如果S指向最后一个节点(可以通过S-&gt;next判断)则停止。
  3. 否则,检查*N*S 的后继)相对于 *S 的顺序是否正确。
    • 如果是这样,则将S(指针,而不是其引用)设置为等于N
    • 如果不是,那么
      • 从列表中删除*N(适当更新其前任和继任者,如果有的话),并且
      • 后退遍历已排序的子列表,直到到达第一个节点或其前任应位于 *N 之前的节点,以先遇到者为准。
      • 在您发现的节点之前插入*N
      • 如果这使*N 成为列表头(您可以通过它的previous 指针的新值来判断),那么将头指针(不是它的引用)设置为等于N
  4. 从第 2 点开始重复

实际代码保留为预期的练习。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    相关资源
    最近更新 更多