【问题标题】:Sorting a linked list by finding the largest and placing it at the head通过找到最大的并将其放在头部来对链表进行排序
【发布时间】:2021-03-19 05:12:51
【问题描述】:

试图找出如何对链表进行排序,方法是找到最大的整数,删除它并将其放在开头。所以我写了一个函数来找到最大的并将它放在列表的开头。我测试了它并且它有效。就是这样。

NodePtr
getBiggest(NodePtr top)
{
    int big;
    NodePtr max, prev, before, head = top;

    big = head->num;

    while (head->next != NULL) {
        prev = head;
        head = head->next;
        if (big < head->num) {
            big = head->num;
            max = head;
            before = prev;
        }
    }

    before->next = max->next;
    max->next = top;
    top = max;

    return top;
}

然后我编写了一个函数来对列表进行排序。这个没有按预期工作。我是编码新手,我只需要一些灵感。我正在尝试,但没有成功。

NodePtr
sortList(NodePtr top)
{
    NodePtr getBiggest(NodePtr);
    NodePtr head = top, prev, rp, curr;

    rp = getBiggest(head);
    prev = rp;
    curr = rp->next;

    while (curr != NULL) {
        prev->next = getBiggest(curr);
        prev = curr;
        curr = curr->next;
    }

    return rp;
}

【问题讨论】:

    标签: c sorting singly-linked-list selection-sort function-definition


    【解决方案1】:
        curr = curr->next;
    

    那是你的问题。

    每次找到下一个最大的项目时,列表中未排序的部分就会缩小一个。在第一次迭代中,您找到最大的项目,然后搜索下一个最大的项目。但是,不是从第 2 项开始第二次搜索,而是从插入的节点指向的下一个节点开始。

    您希望插入成为删除的镜像。每当你从链 A → B → C 中删除 B 时,你必须以 A → C 结束。同样,当你将 B 插入 A → C 时,你必须改变 A → next 指向 B,并且 B →next 指向 A 的旧下一个:C。

    在您的代码中,

    prev->next = getBiggest(curr);
    

    curr 被修改,prev-&gt;next 被销毁。相反,将getBiggest 更改为不修改其参数,并且只返回从起点开始的最大节点。那么,

    while ((curr = getBiggest(curr->next)) != NULL) {
        NodePtr next = prev->next;
        prev->next = curr;
        curr->next = next;
    }
    

    我建议编写 insertdelete 函数,它们将先前和当前节点作为参数。这应该有助于弄清楚你的循环应该是什么样子。

    【讨论】:

      【解决方案2】:

      函数getBiggest

      NodePtr getBiggest(NodePtr top){
      int big;
      NodePtr max,prev,before,head=top;
      big=head->num;
      while(head->next!=NULL){
      prev=head;
      head=head->next;
      if(big<head->num){big=head->num;max=head;before=prev;}
      }
      before->next=max->next;
      max->next=top;
      top=max;
      return top;
      }
      

      可以调用未定义的行为,因为指针before 未初始化。所以在没有节点值大于指针top指向的节点中的值的情况下,指针before将保持未初始化状态。

      在函数 sortList 的 while 循环中,此语句中错误地使用了指针 curr 的旧值

      curr=curr->next;
      

      这是一个带有更新函数定义的演示程序。

      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      
      typedef struct List
      {
          int num;
          struct List *next; 
      } *NodePtr;
      
      NodePtr getBiggest( NodePtr head )
      {
          if ( head )
          {
              NodePtr max  = head;
              NodePtr before_max = NULL;
              for ( NodePtr current = head->next, prev = head; 
                    current != NULL; 
                    prev = current, current = current->next )
              {
                  if ( max->num < current->num )
                  {
                      max = current;;
                      before_max = prev;
                  }
              }
              
              if ( max != head )
              {
                  before_max->next = max->next;
                  max->next = head;
                  head = max;
              }
          }
          
          return head;
      }   
      
      int push_front( NodePtr *head, int num )
      {
          NodePtr new_node = malloc( sizeof( *new_node ) );
          int success = new_node != NULL;
          
          if ( success )
          {
              new_node->num  = num;
              new_node->next = *head;
              *head = new_node;
          }
          
          return success;
      }
      
      FILE * display( NodePtr head, FILE *fp )
      {
          for ( ; head != NULL; head = head->next )
          {
              fprintf( fp, "%d -> ", head->num );
          }
          
          fputs( "null", fp );
          
          return fp;
      }
      
      NodePtr sortList( NodePtr head )
      {
          if ( head )
          {
              head = getBiggest( head );
              
              NodePtr prev = head;
              
              while ( ( prev->next = getBiggest( prev->next ) ) != NULL ) 
              {
                  prev = prev->next;
              }
          }
          
          return head;
      }
      
      
      int main(void) 
      {
          NodePtr head = NULL;
          const int N = 10;
          
          srand( ( unsigned int )time( NULL ) );
          
          for ( int i = 0; i < N; i++ )
          {
              push_front( &head, rand() % N );
          }
          
          fputc( '\n', display( head, stdout ) );
          
          head =  sortList( head );
          
          fputc( '\n', display( head, stdout ) );
      
          return 0;
      }
      

      程序输出可能看起来像

      7 -> 3 -> 9 -> 1 -> 8 -> 0 -> 7 -> 0 -> 3 -> 5 -> null
      9 -> 8 -> 7 -> 7 -> 5 -> 3 -> 3 -> 1 -> 0 -> 0 -> null
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-02
        • 2012-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多