单双链表逆序

单链表逆序
一、节点结构
单链表的数据结构 定义如下:
        
  1. typedef struct node  
  2. {  
  3.       ElemType data;  
  4.       struct node *next;  
  5. }list;  
typedef struct node
{
      ElemType data;
      struct node *next;
}list;


        其中,ElemType可以是任意数据类型如int、float或者char等,在算法中,规定其默认为int类型。

二、带头结点
        本文描述的是单链表逆序,链表逆序需要维护3个指针,分别指向前一个节点、当前节点和下一个节点,具体代码如下:
       
  1. list *reverselist(list *head)  
  2.   
  3.     if ((NULL == head) || (NULL == head->next))  
  4.     {  
  5.          return head;  
  6.     }  
  7.     list *p1=head->next, *p2=p1->next, *p3=NULL;  
  8.     p1->next = NULL;  
  9.     while (p2)  
  10.     {  
  11.          p3 = p2->next;           // 保存当前结点的下一结点  
  12.          p2->next = p1;           // 改变当前结点的next域,指向它的前一个结点  
  13.          p1 = p2;                 // 指针移到下一个结点  
  14.          p2 = p3;  
  15.      }  
  16.      head->next = p1;             // 恢复头结点  
  17.       return head;  
  18. }  
 list *reverselist(list *head)
{
     if ((NULL == head) || (NULL == head->next))
     {
          return head;
     }
     list *p1=head->next, *p2=p1->next, *p3=NULL;
     p1->next = NULL;
     while (p2)
     {
          p3 = p2->next;           // 保存当前结点的下一结点
          p2->next = p1;           // 改变当前结点的next域,指向它的前一个结点
          p1 = p2;                 // 指针移到下一个结点
          p2 = p3;
      }
      head->next = p1;             // 恢复头结点
       return head;
 }


        在链表逆序过程中,非常重要的一点是要防止断链问题,因此,在移动指针逆序某个结点时,需要用一个指针指向该结点的下一结点,防止下一结点丢失。

三、不带头结点
       
  1. list *reverselist(list *head)  
  2. {  
  3.      if ((NULL == head) || (NULL == head->next))  
  4.     {  
  5.           return head;  
  6.      }  
  7.     list *p1=head, *p2=p1->next, *p3=NULL;  
  8.     p1->next = NULL;  
  9.     while (p2)  
  10.    {  
  11.          p3 = p2->next;  
  12.          p2->next = p1;  
  13.          p1 = p2;  
  14.          p2 = p3;  
  15.     }  
  16.     head = p1;  
  17.     return head;  
 list *reverselist(list *head)
 {
      if ((NULL == head) || (NULL == head->next))
     {
           return head;
      }
     list *p1=head, *p2=p1->next, *p3=NULL;
     p1->next = NULL;
     while (p2)
    {
          p3 = p2->next;
          p2->next = p1;
          p1 = p2;
          p2 = p3;
     }
     head = p1;
     return head;
}


        不带头结点的链表逆序与带头结点的区别在于红色部分代码,即初始p1指向的是第一个结点而不是头结点,最后head直接指向p1而不是用其next来指向p1。

双链表逆序
一、结点结构
        双向链表的数据结构 定义如下:
       
  1. typedef struct node  
  2.   
  3.      ElemType data;  
  4.      struct node *prior  
  5.      struct node *next;  
  6. list;  
 typedef struct node
{
      ElemType data;
      struct node *prior
      struct node *next;
}list;


        其中,ElemType可以是任意数据类型如int、float或者char等,在算法中,规定其默认为int类型。

二、带头结点
        本文描述的是双向链表逆序,链表逆序需要维护3个指针,分别指向前一个节点、当前节点和下一个节点,具体代码如下:
        
  1. list *reverselist(list *head)  
  2. {  
  3.      if ((NULL == head) || (NULL == head->next))  
  4.      {  
  5.           return head;  
  6.       }  
  7.       list *p1=head->next, *p2=p1->next, *p3=NULL;  
  8.       p1->next = NULL;  
  9.       while (p2)  
  10.       {  
  11.            p3 = p2->next;           // 保存当前结点的下一结点  
  12.            p2->next = p1;           // 改变当前结点的next域,指向它的前一个结点  
  13.            p1->prior = p2;          // 改变前一个结点的prior域,指向它的后一个结点  
  14.            p1 = p2;                 // 指针移到下一个结点  
  15.            p2 = p3;  
  16.        }  
  17.        head->next = p1;             // 恢复头结点  
  18.        p1->prior = head;  
  19.        return head;  
  20. }  
list *reverselist(list *head)
{
     if ((NULL == head) || (NULL == head->next))
     {
          return head;
      }
      list *p1=head->next, *p2=p1->next, *p3=NULL;
      p1->next = NULL;
      while (p2)
      {
           p3 = p2->next;           // 保存当前结点的下一结点
           p2->next = p1;           // 改变当前结点的next域,指向它的前一个结点
           p1->prior = p2;          // 改变前一个结点的prior域,指向它的后一个结点
           p1 = p2;                 // 指针移到下一个结点
           p2 = p3;
       }
       head->next = p1;             // 恢复头结点
       p1->prior = head;
       return head;
}


        在链表逆序过程中,非常重要的一点是要防止断链问题,因此,在移动指针逆序某个结点时,需要用一个指针指向该结点的下一结点,防止下一结点丢失。

三、不带头结点
       
  1.  list *reverselist(list *head)  
  2.  {  
  3.       if ((NULL == head) || (NULL == head->next))  
  4.       {  
  5.            return head;  
  6.       }  
  7.       list *p1=head, *p2=p1->next, *p3=NULL;  
  8.       p1->next = NULL;  
  9.       while (p2)  
  10.       {  
  11.           p3 = p2->next;  
  12.           p2->next = p1;  
  13.           p1->prior = p2;  
  14.           p1 = p2;  
  15.           p2 = p3;  
  16.        }  
  17.       head = p1;  
  18.       return head;  
  19. }  
 list *reverselist(list *head)
 {
      if ((NULL == head) || (NULL == head->next))
      {
           return head;
      }
      list *p1=head, *p2=p1->next, *p3=NULL;
      p1->next = NULL;
      while (p2)
      {
          p3 = p2->next;
          p2->next = p1;
          p1->prior = p2;
          p1 = p2;
          p2 = p3;
       }
      head = p1;
      return head;
}


        不带头结点的链表逆序与带头结点的区别在于红色部分代码,即初始p1指向的是第一个结点而不是头结点,最后head直接指向p1而不是用其next来指向p1。
参照 http://blog.chinaunix.net/uid-22312037-id-3624264.html

猜你喜欢

转载自blog.csdn.net/qinglongzhan/article/details/80668271