反转单链表有三种方式,其中有两种很相似,属于就地反转,另外一种是插入反转。链表结点类为:
1 struct ListNode 2 { 3 int val; 4 ListNode *next; 5 ListNode(int x):val(x),next(NULL) {} 6 };
一、就地反转
就地反转要注意的是反转过程中链表容易出现断裂,这时我们要先保存端点之后的结点信息。
1 /*方法一*/ 2 ListNode *reversrList(ListNode *head) 3 { 4 if(head==NULL||head->next==NULL) return head; 5 ListNode *pCur=head; 6 ListNode *cur=pCur->next; 7 8 while(cur !=NULL) 9 { 10 ListNode *temp=cur->next; //端点之后结点 11 cur->next=pCur; 12 pCur=cur; 13 cur=temp; 14 } 15 head->next=NULL; 16 17 return pCur; 18 } 19 20 /*方法二*/ 21 ListNode *reversrList(ListNode *head) 22 { 23 if(head==NULL) return head; 24 ListNode *pNewList=NULL; 25 ListNode *pCur=NULL; 26 ListNode *cur=head; 27 28 while(cur !=NULL) 29 { 30 ListNode *curNext=cur->next; //端点之后结点 31 if(curNext==NULL) 32 pNewList=cur; 33 cur->next=pCur; 34 pCur=cur; 35 cur=curNext; 36 } 37 38 return pNewList; 39 }
二、插入反转
这时应该先构建一个新表头,作为反转之后新表头的前结点,不然开始对现链表就行反转的时候,没法插入。
1 ListNode *reversrList(ListNode * head) 2 { 3 if(head==NULL) return head; 4 ListNode *nextList=new ListNode(-1); 5 nextList->next=head; 6 ListNode *cur=head; 7 8 while(cur !=NULL&&cur->next !=NULL) 9 { 10 ListNode *curNext=cur->next; 11 cur->next=curNext->next; 12 curNext->next=nextList->next; 13 nextList->next=curNext; 14 } 15 16 return nextList->next; 17 }
另外,这两种方法,虽然循环中有检查链表是否为空或者为单结点的情况,但首先对以指针形式给出的结点进行是否为空的判断,还是很有必要的。