尝试对链接列表进行排序

问题描述

网络上有很多可用的实现,但是我想自己做。

谁能告诉我我犯了什么错误

当我创建链接列表时,我的输入为3、12、5、2。所以排序后应该是2,3,5,12,但是它给我的输出是3,2,12。

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

struct node
{
    int data;
    struct node *next;      
};
struct node *start=NULL;

void sort()
{
    struct node *preptr,*ptr,*temp;
    temp = (struct node *)malloc(sizeof(struct node));
    ptr=start;
    while(ptr->next != NULL)
    {
        preptr=ptr;
        ptr=ptr->next;
        if (preptr->data > ptr->data )
        {
            temp->data=ptr->data;
            ptr->data=preptr->data;
            preptr->data=temp->data;
            ptr=start;
        }
    }
}

解决方法

您似乎已尝试实现冒泡排序,但是一般情况下需要多次遍历数据,并且只执行一次。在那一遍上,输入3、12、5、2是你的代码

  1. 将3与12进行比较,并且保持不变;
  2. 将12与5进行比较,并交换它们;
  3. 将12与2进行比较,并交换它们。

然后它停止,剩下3、5、2、12作为最终结果。

n 元素列表上进行冒泡排序必须使 n -1通常通过该列表,并且您的特定输入碰巧需要该最大数字的通行证。解决该问题的一种方法是只在运行{em> n 的for循环内运行现有代码一次,进行一次排序,但是当然您需要计算 n 首先。更好的方法(无需完全转换为更好的算法)将是通过外部循环运行不确定的遍数,并跟踪遍历过程中是否执行了任何交换。完成通行证而不进行任何交换后,您就完成了。

其他说明:

  • 您不需要struct node来交换两个节点的int数据。

  • 如果要使用struct node作为本地临时文件,则不需要动态分配它。只需声明一下即可:

     struct node temp_node;
    
  • 如果您想要struct node *作为本地临时文件,则(可能)不需要分配任何内存来指向它。

  • 如果您想要一个struct node作为本地临时 的指针,则 still 无需动态分配任何内容。只需声明该结构并获取其地址即可:

     struct node temp_node;
     struct node *temp = &temp_node;
    

    动态分配的主要原因是您事先不知道将需要多少内存,或者分配的对象需要比创建该对象的函数的执行寿命更长。

  • 对链接列表进行排序通常是通过更改节点的链接来重新排列节点来完成的,而不是像函数那样通过交换节点有效负载来完成的。交换有效负载不一定错误,但这并没有利用链表结构的任何优势。

,

正如您在注释中所写,实际上您需要移动节点而不是值,您将需要重新分配next指针。

出于相同的原因,start必须有可能引用其他节点。因此,我建议sortstart作为参数并返回它的新值。

要实现冒泡排序,您需要一个额外的外部循环,该循环可重新启动列表中的迭代。此操作最多应重复 n 次,其中 n 是列表中节点的数量。您也可以只检查是否有必要进行交换,在这种情况下,决定对列表进行另一次扫描...直到不再发生交换。

我在这里实现了第二个想法:

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

struct node {
    int data;
    struct node *next;      
};

// A function to create a new node. 
// This allows for easy initialisation of a linked list
struct node *newNode(int data,struct node *next) {
    struct node *temp = (struct node *)malloc(sizeof(struct node));
    temp->data = data;
    temp->next = next;
    return temp;
}

// Useful to see what is in the list...
void printList(struct node *cur) {
    while (cur != NULL) {
        printf("%i ",cur->data);
        cur = cur->next;
    }
    printf("\n");
}

// Let the sort function
struct node * sort(struct node *start) {
    struct node *prev,*cur,*next;
    // flag indicating we are not sure yet that 
    //    the list is sorted
    int mutation = 1;
    // extra dummy node that precedes the start node
    struct node sentinel; 
    sentinel.next = start;

    while (mutation) {
        mutation = 0;
        prev = &sentinel;
        cur = sentinel.next;
        next = start->next;
        while (next != NULL) {
            if (cur->data > next->data ) {
                // swap cur and next
                prev->next = next;
                cur->next = next->next;
                next->next = cur;
                // flag that we need more iterations
                mutation = 1;
                // prepare for next iteration
                prev = next;
            } else {
                prev = cur;
                cur = next;
            }
            next = cur->next;
        }
    }
    return sentinel.next;
}

// demo:
int main(void) {
  // Create list that was given as example
  struct node *start = newNode(3,newNode(12,newNode(5,newNode(2,NULL))));

  printf("Input:\n");
  printList(start);
  start = sort(start);
  printf("Sorted:\n");
  printList(start);
  return 0;
}