【问题标题】:fix for a reversed link修复反向链接
【发布时间】:2020-07-21 19:17:33
【问题描述】:

嘿,由于某种原因,我的链接列表以相反的顺序打印,例如,如果我的输入是 2->4->6 我的输出是 6->4->2

list* add_int_list(list* a,int b)
{
    list *temp;
    temp = (list*)malloc(sizeof(list*));
    temp->next = NULL;
    if (a->next == NULL)//insert to the first node
    {
        temp->data = b;
        temp->next = a;
        a = temp;

    }
    else 
    {
        temp->data = b;
        temp->next = a;
        a = temp;//I think the problem is here, couldnt find how to fix 
}

【问题讨论】:

  • 嘿!由于某种原因,您插入第一个和后续节点的代码是相同的。这意味着您总是在前面插入新节点,这将以相反的插入顺序创建一个列表。 (这也不是您显示的全部代码。您肯定会返回新的列表头,不是吗?)
  • 如果你想在列表末尾追加一些东西,你需要遍历列表,然后将其添加为最后一个节点。 (遍历->next 指针直到NULL。然后在列表末尾插入temp 节点。)
  • if 声明的目的是什么?两个分支都有相同的代码。要么使它们不同,要么删除if
  • 另外我相信如果你将NULL 传递给a,你的代码会崩溃。在尝试使用第 6 行的箭头语句取消引用之前,您应该处理这种情况。
  • 我可以在同一个函数中添加到头部和末尾吗?

标签: c linked-list insert singly-linked-list


【解决方案1】:

问题在于您的代码在这两种情况下都将节点附加到列表的前面。如果您想始终追加到列表的末尾,则需要遍历列表直到末尾,然后在此处添加 temp

这段代码我是即兴写的,所以把它当作伪代码:

// Assuming this function returns the front (head) of the list.
list* append_element_to_list(list* a, int b)
{
    list *newNode;
    newNode = (list*)malloc(sizeof(list*));
    newNode->data = b;

    // Handle the case where `a` is NULL. This means
    // no list was passed in, so the newly created node
    // will be returned to start the list.
    if (a == NULL)
    {
      return newNode;
    }

    // If we get this far, it means `a` contains at least
    // one node. So walk the list until the end.
    list *currentNode = a;
    while (currentNode->next != NULL)
    {
      currentNode = currentNode->next;
    }

    // Once you reach the end of the list, set
    // `newNode` as the last node.
    currentNode->next = newNode;

    // The front of the list hasn't changed, so return that.
    return a;
}

【讨论】:

    【解决方案2】:

    您的代码中有一些错误,我正在对您的代码进行更正,只是更改了所需的内容。 首先我想关注主要问题,在最后插入任何列表之前,您应该迭代完整列表。

      i = a; // to iterate
      while(i->next != NULL)
      {
       i = i->next;
      }
      // Now i is last node of list a
      i->next = temp;
    

    现在下面的代码,我只是在 TurboC 上检查它,我正在使用你的函数并插入三个值,然后打印列表。 请查看所有行 cmets:

    #include <stdio.h>
    #include <malloc.h>
    typedef struct node{
     int data;
     struct node *next;
    
    }list;
    
    list* add_int_list(list* a,int b)
    {
        list *temp;
        list *i;
    
        temp = (list*)malloc(sizeof(list*));
        temp->next = NULL;
        temp->data = b;
    
        if (a == NULL)//insert to the first node
        {
           //temp->data = b; -  done above
        //temp->next = a; no reason for this line
            a = temp;
        }
        else
        {
           // temp->data = b; - done above
           //temp->next = a; wrong logic
           // a = temp;//I think the problem is here, couldnt find how to fix : Yes it is also wrong
    
          //Here it required to iterate complete list and go to end
    
          i = a; // to iterate
          while(i->next != NULL)
          {
           i = i->next;
          }
          // Now i is last node of list a
          i->next = temp;
        }
    
        return a;
    }
    void printList(list *root)
    {
       list *i;
    
       if(root == NULL)
       {
        printf("List is empty");
       }
       else
       {
        i = root;
        while(i != NULL){
          printf("%d,",i->data);
          i = i->next;
        }
       }
    }
    int main()
    {
      list *root = NULL;
      clrscr();
      root =  add_int_list(root, 3);
      root =  add_int_list(root, 4);
      root =  add_int_list(root, 5);
      printList(root);
        return 0;
    }
    

    【讨论】:

    • 我相信printList有一些错误。 if(root-&gt;data == NULL) 行正在检查 intNULL。应该是if(root == NULL)。同样的方法,while(i-&gt;data != NULL){ 行也会犯同样的错误。应该是while(i-&gt;next != NULL){。最后,列表的打印似乎不会打印最终值。在 while 循环之后,您可能需要一个最终的 printf("%d\n",i-&gt;data);
    • void printList(list *root) { list *i; if( !root ) { printf("List is empty"); } else { i = root; while( i ){ printf("%d,",i-&gt;data); i = i-&gt;next; } } }
    • @MrHappyAsthma,感谢您的建议,我编辑了它。
    【解决方案3】:

    对于本声明中的初学者

    temp = (list*)malloc(sizeof(list*));
                                ^^^^^
    

    分配的内存大小等于指针的大小,而不是节点的大小。你必须写任何一个

    temp = (list*)malloc(sizeof(list));
    

    temp = (list*)malloc(sizeof( *temp));
    

    这个 if 语句

    if (a->next == NULL)
    

    可以调用未定义的行为,因为最初列表可以为空。所以指针a 可以等于NULL。那就是使用空指针来访问内存。

    if-else 语句的 if 和 else 部分之后的这两个代码块没有区别

    if (a->next == NULL)//insert to the first node
    {
        temp->data = b;
        temp->next = a;
        a = temp;
    }
    else 
    {
        temp->data = b;
        temp->next = a;
        a = temp;//
    }
    

    这两个代码都是sn-p尝试在列表的开头插入一个新节点。

    在单向单向列表的开头插入新节点是一种通用方法。将一个节点附加到这样一个列表的末尾是低效的,因为必须遍历整个列表。

    如果你想将一个节点附加到一个单链表的末尾,那么让它成为双面的。

    这是一个演示程序。

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Node
    {
        int data;
        struct Node *next;
    } Node;
    
    typedef struct List
    {
        Node *head;
        Node *tail;
    } List;
    
    int push_front( List *list, int data )
    {
        Node *new_node = malloc( sizeof( Node ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->data = data;
            new_node->next = list->head;
    
            list->head = new_node;
    
            if ( list->tail == NULL ) list->tail = list->head;
        }
    
        return success;
    }
    
    int push_back( List *list, int data )
    {
        Node *new_node = malloc( sizeof( Node ) );
        int success = new_node != NULL;
    
        if ( success )
        {
            new_node->data = data;
            new_node->next = NULL;
    
            if ( list->tail == NULL )
            {
                list->head = list->tail = new_node;
            }
            else
            {
                list->tail = list->tail->next = new_node;
            }
        }   
    
        return success;
    }
    
    void output( const List *list )
    {
        for ( const Node *current = list->head; current != NULL; current = current->next )
        {
            printf( "%d -> ", current->data );
        }
    
        puts( "null" );
    }
    
    int main(void) 
    {
        List list = { .head = NULL, .tail = NULL };
    
        const int N = 10;
    
        for ( int i = 0; i < N; i++ )
        {
            if ( i % 2 != 0 )
            {
                push_front( &list, i );
            }
            else
            {
                push_back( &list, i );
            }
    
            output( &list );
        }
    
        return 0;
    }
    

    它的输出是

    0 -> null
    1 -> 0 -> null
    1 -> 0 -> 2 -> null
    3 -> 1 -> 0 -> 2 -> null
    3 -> 1 -> 0 -> 2 -> 4 -> null
    5 -> 3 -> 1 -> 0 -> 2 -> 4 -> null
    5 -> 3 -> 1 -> 0 -> 2 -> 4 -> 6 -> null
    7 -> 5 -> 3 -> 1 -> 0 -> 2 -> 4 -> 6 -> null
    7 -> 5 -> 3 -> 1 -> 0 -> 2 -> 4 -> 6 -> 8 -> null
    9 -> 7 -> 5 -> 3 -> 1 -> 0 -> 2 -> 4 -> 6 -> 8 -> null
    

    在这个演示程序中,使用函数push_back 将偶数插入到列表的末尾,使用函数push_front 将奇数插入到列表的开头。

    如果你的 C 编译器不支持指定的初始化器,那么这个声明

    List list = { .head = NULL, .tail = NULL };
    

    可以通过以下方式更改

    List list = { NULL, NULL };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 2015-08-31
      • 1970-01-01
      • 2015-07-06
      • 2015-08-25
      相关资源
      最近更新 更多