探究单向链表逆置转向及检查成环的问题

假设链表节点的数据结构为:

typedef struct node 
{
  int data;
  struct node* next;
}ListNode,*pListNode;

要求实现将一个单向链表逆置并检测如果链表成环返回FALSE,从参数返回新的链表头。

BOOL Reverse(pListNode& head);

这个问题看似简单,实际上太能发挥了。首先因为是单向链表,next不能简单的改变方向,要记录下即将被断开的节点,而即将被断开的节点它的next也是同样的问题。再者就是要如何检测有环。

单看逆置问题,通常的方法应该要用到3个指针:当前的p,下一个q,下一个的下一个head。 记下第三个指针,用第二个指向第一个,然后后移一步重复动作直到q没有下一个,再封口。

{
  if (head != NULL && head->next != NULL)
  {
    pListNode p = head;
    pListNode q = head->next;
    p->next = NULL;
    while (q->next != NULL)
    {
      head = q->next;
      q->next = p;
      p = q;
      q = head;
    }
    head->next = p;
  }
  return;   //此法未处理成环问题
}

单看检测成环问题,需要两个指针,一个向后一次移动一步,一个向后一次移动两步。假如他们能够相遇就是成环,他们任意一个走完链表都不成环。

{
  if( head==NULL)return;
  pListNode step1 = head;
  pListNode step2 = head;
  while(step1->next)
  {
    step1 = step1->next;
    if(step2->next)step2 = step2->next;
    else return TRUE;  //不成环
    if(step2->next)step2 = step2->next;
    else return TRUE;  //不成环
    if(step1==step2)return FALSE;
  }
  return TRUE; //不成环
}

以上两种方法都单独解决了部分问题,能不能同时解决两个问题呢?
于是我想到了递归。且不说它的弊端,单就解决问题而言是可行的。

BOOL Reverse(pListNode& head)  //不能处理成环检测
{
    pListNode p = head;
    if(p->next)
    {
      head = p->next;
      Reverse(head);
      p->next->next = p;
    }
    else
    {
      return FALSE;
    }
    return FALSE;
}

这个方法的问题是没法处理成环的问题。 在递归的背景下,解决成环的思路就想到如何标记一下处理过的node。于是我想到一个另类的做法。使用一个辅助结构体记录前后两个节点,把节点本身的next标为’1’,如果处理过程中发现next为1就是成环啦。

struct aid
{
  struct node* left;
  struct node* next;
};
BOOL Reverse(pListNode& head) //同时处理逆置和环检测
{
    if(!head)return FALSE;
    pListNode p = head;
    if(p->next)
    {
      if(p->next==1)return TRUE;  //成环
      aid *a = new aid;
      a->left = p;
      a->right = p->next;
      head = p->next;
      p->next = 1;
      if(Reverse(head)==TRUE)
      {
        delete a;
        return TRUE;
      }
      a->right->next = a->left;
      a->left->next = 0;
      delete a;
    }
    else
    {
      return FALSE;
    }
    return FALSE;
}

注意,以上代码都没有实测!请以思路为主自行参考尝试实现。

发布了24 篇原创文章 · 获赞 7 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章