剑指Offer(反转链表)
2018-06-27 10:51
148 查看
链表一般我们建立的时候都会有一个头结点和一个尾节点,头结点没有存储值,只是起到指向下一个的作用,尾节点有数值,但是指向的下一个尾NULL,这个概念需要弄明白了才能去操作链表。那么如何构建一个标准的链表呢?
首先我们定义一个结构体:
struct ListNode { int val; struct ListNode* next; };然后我们来创建链表:
ListNode *L; ListNode *r,*p; L=new ListNode; r=L; for(int i=0;i<5;i++) { p=new ListNode; p->val=i; r->next=p; r=p; } r->next=NULL;这是一种尾插法的方法来创建链表,L提供的便是链表的头结点,所以没有对它进行赋值,而是将直接指向了新节点p,再看看结尾,最后一个节点p加进去之后,r转移到链表的尾部,这个时候的链表并没有结束符,所以我们需要在最后加上r->next=NULL,来保证链表的完整性。
对于标准的链表,我们打印链表时自然不需要打印第一个头结点,后面所有的节点都需要被打印,因此我们可以很容易的想到通过判断节点的next来判断链表的走势。
r=L->next; while(r!=NULL) { cout<<r->val<<" "; r=r->next; } cout<<endl;r的初始位置必须从头结点的下一个开始,这样便不会打印头结点的内容,而且头结点也不是我们想要的内容。
结果展示:
搞清楚链表的概念之后,我们再来看看链表的反转就容易多了。
反转链表便是将原来指向的后一个节点的方向改为指向前一个节点,那么对于原来的头结点,肯定是要抛弃的,而对于尾节点,则需要重新新建一个节点,我们大可不必这么麻烦,因为由于链表的特殊性,我们完全可以将原来的头结点重新指向链表的尾节点,让原本头结点的下一个节点指向NULL,毕竟总共的节点数没有变化。
class solution { public: ListNode* ReverseList(ListNode* pHead) { if(pHead==NULL) return NULL; ListNode* pCurent,*pPrev,*pNext; pCurent=pHead->next; pPrev=NULL; while(pCurent!=NULL) { pNext=pCurent->next; if(pNext==NULL) { pCurent->next=pPrev; pHead->next=pCurent; return pHead; } pCurent->next=pPrev; pPrev=pCurent; pCurent=pNext; } } };
好,我们来分析一下这个过程:首先,如果这个头结点是空的肯定返回错误。我们创建三个关键的节点pCurent代表当前的节点位置,pPrev代表前一个节点,pNext代表后一个节点。由于头结点的下一个节点才是真的节点,所以pCurent的初始值肯定为头结点的下一个,而第一次循环pCurent需要指向pPrev,这个时候的pCurent定然是尾节点了,所以pPrev肯定要初始为NULL,那么下一个节点pNext也当然是pCurent的下一个了。链表的第一次反转,即pCurent的第一次反转,pCurent指向了pPrev,pPrev需要向后移动一位(pPrev=pCurent),pCurent也需要向后移动一位(pCurent=pNext)。到了第二次循环的时候,pNext也重新跟新了。
那么何时结束循环呢,我们看到循环里的判断是:pCurent!=NULL,那就是说需要等到pCurent移动到原来链表的最后一位的下一个,那当然是一个NULL了,也就是说这个时候的pNext=NULL。所以我们在循环里加入了一个if判断,如果pNEXT==NULL了,那就说明链表到结尾了,这个时候被闲置的pHead便可以作为新的头结点并指向pCurent。
这里值得注意的是,if执行的时候不能直接返回中断函数,因为链表的最后阶段还没有完成,pCurent还需要指向前一个节点。
运行结果:
然而有的时候笔试给的链表不带有头结点,那么这个时候的变化是什么呢,因为没有头结点,所以翻转式pCurent的初始值变为pHead。
代码:class solution { public: ListNode* ReverseList(ListNode* pHead) { if(pHead==NULL) return NULL; ListNode* pCurent,*pPrev,*pNext; pCurent=pHead; pPrev=NULL; while(pCurent!=NULL) { pNext=pCurent->next; if(pNext==NULL) { pCurent->next=pPrev; return pCurent; } pCurent->next=pPrev; pPrev=pCurent; pCurent=pNext; } } };
阅读更多
相关文章推荐
- 反转链表 --剑指offer
- 剑指offer(15)—反转链表
- 《剑指Offer》面试题:反转链表
- 《剑指offer》编程题java实现(十三):反转链表
- 剑指offer系列之十四:反转链表
- 剑指offer(十五)反转链表
- 剑指offer面试题16-反转链表
- 《剑指Offer》学习笔记——反转链表
- 剑指offer面试题16:反转链表
- 《剑指Offer》面试题16:反转链表
- 剑指offer——链表的递归反转打印
- 剑指Offer----反转链表
- 剑指offer-第三章高质量代码(反转链表)
- 《剑指offer》——反转链表
- 剑指offer----反转链表
- 剑指offer——面试题16:反转链表
- 剑指Offer(24)反转链表
- 剑指Offer系列-面试题16:反转链表
- 反转链表(剑指offer)
- 《剑指offer》-反转链表