剑指offer面试题16 反转链表(递归和非递归,主要还是看代码的鲁棒性)
来源:互联网 发布:禁止电脑安装软件 编辑:程序博客网 时间:2024/06/06 03:01
/*这题早就做过了,但是当时看的书上的代码真的很差,比其这本书差的不少。。剑指offer真是我大学看过的最好的书之一了反转链表 需要对链表进行遍历 每次对于遍历到的节点,先记录next,再next指向前一个,然后继续遍历 注意不要把链表弄段还有注意输入 最主要的是输入头节点NULL 的处理 测试数据要想到 只有一个节点怎么办 两个,多个怎么办 输入NULL 怎么办只要自己想到测试数据都过了 代码才可以提交*/#include<iostream>#include<cstdio>using namespace std;struct Node{ int data; Node * next;};void PrintList(Node * head){ if(head==NULL) printf("empty List\n"); Node * p=head; while(p!=NULL) { printf("%d ",p->data); p=p->next; } cout<<endl;}Node * ReverseList(Node * head){ Node * pre=NULL;//因为头节点的前一个是空的 Node * p=head; Node * newhead=NULL;//如果输入空指针 不进入循环 返回newhead 所以赋初值NULL while(p!=NULL) { Node * p_next=p->next;//先记录下一个 if(!p_next) newhead=p; p->next=pre;//再把next指向前一个 pre=p; p=p_next; } return newhead;}// 单链表反序的递归算法,这个相对好理解 想起以前看那本CC++程序员面试宝典,也是在那看的//递归算法,太尼馬坑了 那本书我还通透的看完了。那个代码本来就有错 还不好理解,看来选经典好书真的太重要了//这个算法就相对好理解了 一直递归执行这个函数 知道最后一个节点的时候 因为head->next是空了 返回了head//因为是最后一个节点 这个head就是反转后的头节点 在倒数第二个里面newhead就是新的头节点//接下来两句很经典 head->next->next=head 这句话把链表的指针到过来了//这个时候 这个head就是目前链表的末尾 所以next赋值NULL 太经典了 这个算法真好Node * ReverseListRecursively(Node * head)//递归方法 相对好理解{ if(head==NULL || head->next==NULL) return head; Node * newhead=ReverseListRecursively(head->next); head->next->next=head; head->next=NULL; return newhead;}int main(){ //freopen("/home/gl/in","r",stdin); int n; while(scanf("%d",&n)!=EOF) { Node * head; if(!n) head=NULL; else head=new Node(); Node * p=head; for(int i=0;i<n;++i) { scanf("%d",&p->data); if(i==n-1) { p->next=NULL; break; } p->next=new Node(); p=p->next; } PrintList(head); // Node * newhead = ReverseList(head); Node * newhead=ReverseListRecursively(head); PrintList(newhead); } return 0;}