【问题标题】:C++ LinkedList Swap Nodes [duplicate]C ++链表交换节点[重复]
【发布时间】:2012-03-04 16:06:48
【问题描述】:

可能重复:
debug help - swap 2 nodes of double link list

我正在尝试编写一种算法,该算法可以在 C++ 中交换一个单链表中的两个节点。这是我目前所拥有的:

void swap(ListNode *node1, ListNode *node2)
{
    ListNode *prev1 = head;
    ListNode *prev2 = head;

    //Search previous node for node1:
    while(prev1->next!=node1 || prev1 != node1)
        prev1 = prev1->getNext();

    //Search previous node for node2:
    while(prev2->next!=node2 || prev2 != node2)
        prev2 = prev2->getNext();


    if(node1->next==node2)
    {  //This means node1 == prev2?
        tail = node1;
        node1->next = NULL;
        head = node2;
        node2->next = node1;
    }
    else if(node2->next==node1)
    {  // node2 == prev1
        tail = node2; 
        node2->next = NULL;
        head = node1;
        node1->next = node2;
    }
    if(node1->next == NULL)
    {   //node1 is last
        node1->next = node2->next;
        tail = node2;
        node2->next = NULL;
        prev1->next = node2;
        prev2->next = node1;
    }
} 

但是我意识到我可以得到的不同情况的数量,比如如果 LL 只有两个元素,或者如果他们在节点 1 之前给了我们节点 2,等等。我意识到它不可能这么复杂和丑陋。那么如何编写交换两个节点的算法呢?

【问题讨论】:

  • 具体问题是什么?
  • 我们不会在 Stack Overflow(不是网络论坛或留言板)上“提供一些提示”。我们回答有关编程语言的具体问题。
  • “如何交换链表中的两个节点”对我来说听起来是一个非常合理和具体的问题,尽管是重复的。
  • 我不能说这不是重复的,但它不是链接问题的重复。这个问题是关于单链表,而不是双链表
  • 对于单个链接列表,我的建议是使用额外的间接级别来查找交换的位置(指向要交换的节点的指针),该额外级别简化了案件数量很大。获得这两个位置后,您可以交换指向节点的指针和指向下一个节点的指针。不应该超过 10-15 行,只有两个循环和几个 if。

标签: c++ algorithm linked-list swap


【解决方案1】:

在一个例程中完成整个任务是错误的。将其分解为两个更简单的问题:

1) 从列表中删除一个节点,包括所有特殊情况。 2) 在列表中插入一个节点,包括所有特殊情况。

从那里开始,整体问题很简单,但由于这显然是家庭作业,所以你只能靠自己了。

【讨论】:

    【解决方案2】:

    这对我来说似乎更干净:

    //Maybe this function should go instide ListNode itself...
    
    ListNode *prev(ListNode *node) {
    
        if (node == head)
            return null;
    
        ListNode *search = head;
    
        while (search != node)
           search = search->getNext();
    
        return search;
    }
    
    void swap(ListNode *node1, ListNode *node2)
    {
        ListNode *prev1 = prev(node1), 
                 *prev2 = prev(node2),
                 *next1 = node1->getNext(),
                 *next2 = node2->getNext();
    
        if (prev1)
            prev1->next = node2;
        else
            head = node2;
    
        if (prev2)
            prev2->next = node1;
        else
            head = node1;
    
        if (!next1)
            tail = node2;
        else if (!next2)
            tail = node1;
    
        node1->next = next2;
        node2->next = next1;
    } 
    

    还没有测试过这个...

    【讨论】:

      【解决方案3】:
      #include <stdio.h>
      
      struct llist {
              struct llist *next;
              char *payload;
              } llists[]=
      {{ llists+1, "one"}
      ,{ llists+2, "two"}
      ,{ llists+3, "three"}
      ,{ llists+4, "four"}
      ,{ llists+5, "five"}
      ,{ llists+6, "six"}
      ,{ llists+7, "seven"}
      ,{ llists+8, "eight"}
      ,{ llists+9, "nine"}
      ,{ NULL, "ten"}
       };
      
      struct llist *head = llists;
      
      void llistswap(struct llist *one, struct llist * two)
      {
      struct llist **hnd, **h1, **h2;
      
      h1 = h2 = NULL;
      
      for (hnd= &head; *hnd; hnd = &(*hnd)->next) {
          struct llist *tmp;
          if ((*hnd) == one) h1 = hnd;
          else if ((*hnd) == two) h2 = hnd;
          else continue;
          if (!h1 || !h2) continue;
      
          tmp =  *h1;
          *h1 = *h2;
          *h2 = tmp;
      
          tmp = (*h1)->next;
          (*h1)->next = (*h2)->next;
          (*h2)->next =  tmp;
          break;
          }
      }
      
      void do_print(struct llist *lp)
      {
      for ( ; lp; lp = lp->next) {
          printf("%s%c", lp->payload, (lp->next) ?',' : '\n' );
          }   
      }
      
      int main(void)
      {
      do_print (head);
      llistswap ( llists+4, llists+7);
      do_print (head);
      
      return 0;
      }
      

      【讨论】:

      • OP 询问的是双向链表,而不是单链表。而且这段代码不言自明,不能保证没有任何描述。
      • 好吧,反正这是家庭作业,所以将更新添加到反向指针(当我们在它的时候)似乎微不足道。
      • 顺便说一句:标题和问题都没有提到双链表,也没有 ->prev 指针。 (有一些变量称为 prev[12],但这些似乎有另一个目的)
      • @tenfour 问题在哪里提到 doubleprev?实际问题的第一行确实提到了 single 。也许你冲进评论和投票结束......
      • 真;我似乎是盲人或对另一个问题感到困惑。我的错。
      猜你喜欢
      • 2014-04-17
      • 1970-01-01
      • 1970-01-01
      • 2017-12-07
      • 2018-11-05
      • 2015-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多