链表逆序(反转)

注明,本博客均假设链表没有单独的头结点。

网上博客:http://blog.csdn.net/niuer09/article/details/5961004  一种有有单独头结点的一种实现,带有头结点的实现起来要简单一些的。

单向链表的逆序或是反转是经常会遇到的一个面试题,也是一个非常基础的问题,我自己的面试中就已经遇到的两次。

比如一个链表是这样的: 1->2->3->4->5 通过反转后成为5->4->3->2->1.

最容易想到的方法,其实也可说是最简单的办法就是遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。

分析:

  1). 若链表为空,则直接返回;

  2). 设置三个前后相邻的指针pre,粗人,next, 将pre所指向的节点作为cur指向节点的后继;

  3). 重复2)直到cur为空

  4). 调整链表头和链表尾

源代码如下:

   1: void reverse(linka** head) {
   2:     if(head ==NULL || *head ==NULL)
   3:         return;
   4:     linka *phead = *head;
   5:     linka *pre=phead;
   6:     linka *cur=phead->next;
   7:     linka *next =NULL;
   8:     while(cur)
   9:     {
  10:         next = cur->next;
  11:         cur->next = pre;
  12:         pre = cur;
  13:         cur = next;
  14:     }
  15:     phead->next = NULL;
  16:     phead = pre;
  17:  
  18:     *head = phead;
  19: }

 

还有一种利用递归的方法。这种方法的基本思想是在反转当前节点之前先调用递归函数反转后续节点。不过这个方法有一个缺点,可能使得就是在反转后的最后一个结点会形成一个环,所以必须想办法将链表第一节点的next置为NULL.算法的源代码如下:

   1: //使用递归
   2: linka* reverse1(linka*p,linka** head)
   3: {
   4:     if(p == NULL || p->next == NULL)
   5:     {
   6:         *head=p;
   7:         return p;
   8:     }else    if ( p == *head)
   9:     {
  10:         linka* tmp = p->next ;
  11:         p->next =NULL;
  12:         linka* tmp1 = reverse1(tmp,head);
  13:         tmp1->next = p;
  14:         return p;            
  15:     }else
  16:     {
  17:         linka* tmp = reverse1(p->next,head);
  18:         tmp->next = p;
  19:         return p;
  20:     }
  21: } 

 

两个算法因为都需要改变链表头,我们传递的都是链表头的指针,即双重指针。 如果完全采用c++,可以使用引用替代。

还有另一种思路,就是利用C++语言的容器栈,只是空间复杂度和事件复杂度都较大,源码如下:

   1: linka* reverse2(linka** head)
   2: {
   3:     if(head ==NULL || *head ==NULL)
   4:         return *head;
   5:  
   6:     stack<linka*>  stk_link;
   7:  
   8:     linka *phead = *head;
   9:     linka *cur= NULL;
  10:     while(phead != NULL)
  11:     {        
  12:         cur = phead->next;
  13:         stk_link.push(phead);
  14:         phead =cur;
  15:     }
  16:     
  17:     *head = stk_link.top();
  18:     stk_link.pop();
  19:     phead =*head;
  20:     
  21:     while (stk_link.empty() == false)
  22:     {
  23:         cur = stk_link.top();
  24:         phead->next = cur;
  25:         phead= cur ;
  26:         stk_link.pop();
  27:     }    
  28:     phead ->next =NULL;
  29:     return *head;
  30: }

如果有这种思路,当然可以另外一种方法,其空间复杂度为O(1),就是新建一个节点作为临时头结点。循环,一一般简历链表的方式重新建立链表,可以很容易的反向实现, 与第一种在实现上应该是一样的吧。

本程序所有源代码(VS2010编译通过):

   1: // code-summary.cpp : 定义控制台应用程序的入口点。
   2:  
   3: /**************************************************************************
   4:     * Copyright (c) 2013,  All rights reserved.
   5:     * 文件名称    : code-summary.cpp
   6:     * 文件标识    :
   7:     * 摘    要    : 
   8:     * 
   9:     * 当前版本    : Ver 1.0
  10:     * 作者        : 徐冬冬
  11:     * 完成日期    : 2013/05/10
  12:     *
  13:     * 取代版本    : 
  14:     * 原作者    :
  15:     * 完成日期    :  
  16:     * 开放版权  : GNU General Public License GPLv3
  17: *************************************************************************/
  18: #include "stdafx.h"
  19:  
  20: #include <iostream>
  21: #include <random>
  22: #include <stack>
  23: using namespace std;
  24: //链表逆序
  25:  
  26:  
  27:  
  28: struct linka {
  29:     int data;
  30:     linka* next;
  31: };
  32: void print(linka *head);
  33: typedef linka link;
  34:  
  35: void init(link **head)
  36: {
  37:     int i= 0;
  38:     link *phead = *head;
  39:     link *cur = NULL;
  40:     for (i= 0 ;i< 10;i++)
  41:     {
  42:         cur = new link ;
  43:         cur ->data  =rand();
  44:         cur->next = phead;
  45:         phead =cur ;
  46:     }
  47:     *head = phead;
  48:     return ;
  49: }
  50:  
  51: void print(link *head)
  52: {
  53:     int i=0;
  54:     link *cur=head;
  55:     for ( ; cur != NULL ; cur= cur->next)
  56:     {
  57:         cout<< cur ->data <<'\t' ;
  58:     }
  59:     cout<<endl;
  60: }
  61:  
  62: void reverse(linka** head) {
  63:     if(head ==NULL || *head ==NULL)
  64:         return;
  65:     linka *phead = *head;
  66:     linka *pre=phead;
  67:     linka *cur=phead->next;
  68:     linka *next =NULL;
  69:     while(cur)
  70:     {
  71:         next = cur->next;
  72:         cur->next = pre;
  73:         pre = cur;
  74:         cur = next;
  75:     }
  76:     phead->next = NULL;
  77:     phead = pre;
  78:  
  79:     *head = phead;
  80: }
  81: //使用递归
  82: linka* reverse1(linka*p,linka** head)
  83: {
  84:     if(p == NULL || p->next == NULL)
  85:     {
  86:         *head=p;
  87:         return p;
  88:     }else    if ( p == *head)
  89:     {
  90:         linka* tmp = p->next ;
  91:         p->next =NULL;
  92:         linka* tmp1 = reverse1(tmp,head);
  93:         tmp1->next = p;
  94:         return p;            
  95:     }else
  96:     {
  97:         linka* tmp = reverse1(p->next,head);
  98:         tmp->next = p;
  99:         return p;
 100:     }
 101: } 
 102:  
 103: linka* reverse2(linka** head)
 104: {
 105:     if(head ==NULL || *head ==NULL)
 106:         return *head;
 107:  
 108:     stack<linka*>  stk_link;
 109:  
 110:     linka *phead = *head;
 111:     linka *cur= NULL;
 112:     while(phead != NULL)
 113:     {        
 114:         cur = phead->next;
 115:         stk_link.push(phead);
 116:         phead =cur;
 117:     }
 118:     
 119:     *head = stk_link.top();
 120:     stk_link.pop();
 121:     phead =*head;
 122:     
 123:     while (stk_link.empty() == false)
 124:     {
 125:         cur = stk_link.top();
 126:         phead->next = cur;
 127:         phead= cur ;
 128:         stk_link.pop();
 129:     }    
 130:     phead ->next =NULL;
 131:     return *head;
 132: }
 133:  
 134: int _tmain(int argc, _TCHAR* argv[])
 135: {
 136:     linka *head =NULL ;
 137:     init(&head);
 138:     print(head);
 139:     reverse(&head);
 140:     print(head);
 141:  
 142:     reverse1(head,&head);
 143:     print(head);
 144:  
 145:     reverse2(&head);
 146:     print(head);
 147:  
 148:     system("pause");
 149:     return 0;
 150: }
 151:  
posted @ 2013-05-10 16:27  远东悟语  阅读(1000)  评论(0编辑  收藏  举报

我是徐冬冬