我试图在这个状态下对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;
}
答案 0 :(得分:0)
有人可以请他们解释一下&#34; insertSort&#34; 方法应该被设计?
首先,我建议删除length
变量,或至少不在排序例程中使用它。它不是必需的,依赖它可能会过多地转向数组式实现。当您发现next
指针为NULL的节点时,您知道已经到达列表的末尾。
其次,我重申我的评论,即你没有正确地为双向链表执行节点交换。任何链表上的节点交换,无论是单链还是双链,都等同于从列表中提取第二个节点,然后在第一个节点之前重新插入。在一个单链表中,一般会影响三个节点:除了两个被交换之外,还有第一个节点的前身。在双向链表中,它也会影响第二个的继承者。在双重关联的案例中,这很麻烦,我建议将其明确地构造为切除后插入。
但我也建议您退后一步,从高层次看算法。它的工作原理是依次考虑每个节点,从第二个节点开始,如果需要,将其移除并重新插入其前面的(已排序)子列表中的正确位置。那么,成对交换甚至与它有什么关系呢? 没有。这是在数组上实现这种排序的一个方便的细节,但是在对链表进行排序时会做出不必要的工作。
对于链表,特别是双链表,我建议将一个实现更直接地解析为算法的抽象描述:
S
维护到已排序的前导子列表的最后一个节点。最初,这将指向列表头。S
指向最后一个节点(您可以通过S->next
判断),请停止。*N
是*S
的后继者是否相对于* S正确排序。
S
(指针,而不是其引用)设置为N
。*N
(适当更新其前任及其后续版本,如果有的话),*N
之前的节点,以先到者为准。*N
。*N
列表头(您可以通过其previous
指针的新值判断),则将头指针(而不是其引用)设置为N
实际代码保留为预期的练习。