细说单链表反转(单链表逆向)

来源:互联网 发布:c语言标准库 编辑:程序博客网 时间:2024/06/03 23:21

单链表反转(逆向)据说时一道面试的老题,问题想来应该不难,但动手写来发现真是方法各异,繁简不一

在此把各种思想都实现了一边,大致如此:

  1. 用滑动的指针将链表中每一个指针反转
  2. 将链表一分为2,right链表依次在left链表的头部插入
  3. 对方法2的优化
  4. 递归实现,直接利用子问题是原问题的更小规模
  5. 对递归的优化,这个写的头有点大

1、

struct Node{int val;Node* next;Node(int i):val(i),next(NULL){}};//滑动法反转链表,调用方法:head=Reverse(&head);void Reverse(Node **head){if(*head==NULL||(*head)->next==NULL)return;Node *lef=*head;Node *rig=lef->next;bool isHead=true;while(rig->next!=NULL){lef=rig;rig=rig->next;if(isHead)//处理反转后第一个节点变为尾节点{(*head)->next=NULL;isHead=false;}lef->next=*head;*head=lef;}rig->next=lef;//处理最后一个节点*head=rig;}

2、

//逐次插入反转链表,调用方法:head=Reverse(head);可以避免二维指针参数//rig指向待排序的部分,rigHead指向将要移动的节点Node* Reverse2(Node* head){if(head==NULL||head->next==NULL)return NULL;Node* rig=head->next;head->next=NULL;Node* rigHead;while(rig!=NULL){rigHead=rig;rig=rig->next;rigHead->next=head;head=rigHead;}return rigHead;}

3、


//Reverse2的优化//pre指向完成逆序的前半部分,next指向待排序的后半部分Node* Reverse22(Node* head){Node *pre=NULL,*next;while(head!=0){next=head->next;head->next=pre;pre=head;head=next;}return pre;}

4、

//用递归解决,栈开销大,复杂度为O(n^2)//head为首节点,inorder为排好顺序的节点Node* Reverse_recur(Node* p){if(p==NULL||p->next==NULL)return p;Node* inorder=Reverse_recur(p->next);Node* res=inorder;while(res->next!=NULL)res=res->next;res->next=p;p->next=NULL;return inorder;}

5、

//优化的递归,线性复杂度//递找到尾节点tail,每次归将尾节点的前一个节点p移到最后Node* Reverse_recur2(Node* p){if(p==NULL||p->next==NULL)return p;Node *tail=Reverse_recur2(p->next);p->next->next=p;p->next=NULL;return tail;}


完整代码:

/*************************************************************************    > File Name: list.cpp    > Title:输入链表,将其反转后输出     > Description: 可以使用反转函数,但建议顺次遍历链表,每次从头部插入> Look out:普通指针形参无法修改指针实参    > Created Time: 2014年03月09日 星期日 09时27分04秒 ************************************************************************/#include<iostream>using namespace std;struct Node{int val;Node* next;Node(int i):val(i),next(NULL){}};//注意:要改变指针的值,需要使用指向指针的指针void Insert(Node** head,int val){Node* cur=new Node(val);cur->next=*head;*head=cur;}//滑动法反转链表,调用方法:head=Reverse(&head);void Reverse(Node **head){if(*head==NULL||(*head)->next==NULL)return;Node *lef=*head;Node *rig=lef->next;bool isHead=true;while(rig->next!=NULL){lef=rig;rig=rig->next;if(isHead)//处理反转后第一个节点变为尾节点{(*head)->next=NULL;isHead=false;}lef->next=*head;*head=lef;}rig->next=lef;//处理最后一个节点*head=rig;}//逐次插入反转链表,调用方法:head=Reverse(head);可以避免二维指针参数//rig指向待排序的部分,rigHead指向将要移动的节点Node* Reverse2(Node* head){if(head==NULL||head->next==NULL)return NULL;Node* rig=head->next;head->next=NULL;Node* rigHead;while(rig!=NULL){rigHead=rig;rig=rig->next;rigHead->next=head;head=rigHead;}return rigHead;}//Reverse2的优化//pre指向完成逆序的前半部分,next指向待排序的后半部分Node* Reverse22(Node* head){Node *pre=NULL,*next;while(head!=0){next=head->next;head->next=pre;pre=head;head=next;}return pre;}//用递归解决,栈开销大,复杂度为O(n^2)//head为首节点,inorder为排好顺序的节点Node* Reverse_recur(Node* p){if(p==NULL||p->next==NULL)return p;Node* inorder=Reverse_recur(p->next);Node* res=inorder;while(res->next!=NULL)res=res->next;res->next=p;p->next=NULL;return inorder;}//优化的递归,线性复杂度//递找到尾节点tail,每次归将尾节点的前一个节点p移到最后Node* Reverse_recur2(Node* p){if(p==NULL||p->next==NULL)return p;Node *tail=Reverse_recur2(p->next);p->next->next=p;p->next=NULL;return tail;}int main(){int n;while(cin>>n)//输入链表长度n{if(n==0){cout<<"NULL"<<endl;continue;}Node* head=NULL;while(n--)//按照输入顺序的逆序生成链表{int cur;cin>>cur;Insert(&head,cur);//欲改变head的值,要传递其地址}//对链表进行反转//Reverse(&head);//head=Reverse2(head);//head=Reverse22(head);//head=Reverse_recur(head);head=Reverse_recur2(head);//遍历输出后析构各节点while(head!=NULL){cout<<head->val;if(head->next!=NULL)cout<<" ";//head=head->next;直接移动头指针会发生内存泄漏Node* used=head;head=head->next;delete used;}cout<<endl;}}


0 0
原创粉丝点击