插入排序双向链表

时间:2018-05-25 14:06:24

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

我试图在这个状态下对C中的双向链表进行插入排序,我的代码让我陷入了一个非结束循环,吐出8s和9s。

有人可以请他们解释一下" insertSort"方法应该被设计?

我的链接列表设计包含head,previous,next和一些数据。

到目前为止,这是我的代码

我的希望是NULL。请帮忙。

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

1 个答案:

答案 0 :(得分:0)

  

有人可以请他们解释一下&#34; insertSort&#34;   方法应该被设计?

首先,我建议删除length变量,或至少不在排序例程中使用它。它不是必需的,依赖它可能会过多地转向数组式实现。当您发现next指针为NULL的节点时,您知道已经到达列表的末尾。

其次,我重申我的评论,即你没有正确地为双向链表执行节点交换。任何链表上的节点交换,无论是单链还是双链,都等同于从列表中提取第二个节点,然后在第一个节点之前重新插入。在一个单链表中,一般会影响三个节点:除了两个被交换之外,还有第一个节点的前身。在双向链表中,它也会影响第二个的继承者。在双重关联的案例中,这很麻烦,我建议将其明确地构造为切除后插入。

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

对于链表,特别是双链表,我建议将一个实现更直接地解析为算法的抽象描述:

  1. 将指针S维护到已排序的前导子列表的最后一个节点。最初,这将指向列表头。
  2. 如果S指向最后一个节点(您可以通过S->next判断),请停止。
  3. 否则,请检查*N*S的后继者是否相对于* S正确排序。
    • 如果是,则将S(指针,而不是其引用)设置为N
    • 如果没有,那么
      • 从列表中删除*N(适当更新其前任及其后续版本,如果有的话),
      • 向后退步到已排序的子列表,直到您到达第一个节点或其前任节点应位于*N之前的节点,以先到者为准。
      • 在您发现的节点前插入*N
      • 如果这使*N列表头(您可以通过其previous指针的新值判断),则将头指针(而不是其引用)设置为N
  4. 从第2点重复
  5. 实际代码保留为预期的练习。