今天听说同学面试问了链表逆置,于是久违地敲了下代码。。。
这里逆置用的是插头法,网上资料也很多,大家可以去找找有图解的。
算法思想
将需要逆置的链表的头去掉!
也就是说,我们可以用一个辅助链表(p)去指向当前head->next节点。于是我们暂时保存了除head以外的链表,然后将表头割裂!
head->next = NULL;
并且将其赋值给另一个辅助链表(q)。
做完这些初始化操作之后,我们进入循环部分:
循环部分很重要的是理解指针赋值这件事情!
一个指针对象指向的是一个地址!而链表可以说一连串内存分散的单元,比如说表头指针,实际上存储的是一个Node节点信息的地址,所以我们不能直接将指针赋值认为是复制!
参考代码如下:(欢迎各位批评指正)
#include<iostream>
using namespace std;
struct Node{
int val;
Node *next = NULL;
};
Node *create(Node* head,int len)
{
Node *L = new Node();
for(int i = 0; i<len; i++)
{
L = head;
int t;
cout<<"pls input the data!"<<endl;
cin>>t;
if(L == NULL)
{
L->val=t;continue;
}
if(t < L->val){
Node *temp = new Node();
temp->val = t;
temp->next = L;
head = temp ;
delete temp;
continue;
}
else
{
while(L->next!=NULL&&t > L->next->val)
{
L=L->next;
}
Node *temp = new Node();
temp->val = t;
temp->next=NULL;
temp->next = L->next;
L->next = temp;
cout<<"head->next->value: "<<L->next->val<<endl;
delete temp;
}
}
delete L;
return head;
}
Node *reverse(Node*& L) //注意此处定义的是 '指针的引用'
{//头插法
Node *p = new Node(),*q = new Node();
p = L->next;
L->next = NULL; //将头结点之后置空
while(p!=NULL)
{
q = p->next; //一定要保存当前头结点之后的序列
p->next = NULL; //写出来赋值为NULL,是明确将p与之后的链表断开
p->next = L; //将断开的头结点指向之前存下的逆序链表
L = p; //将L再次更新为当前头结点的地址
p = q; //将p赋值为q准备下一轮循环
}
return L;
}
int main()
{
Node *head = new Node();
head->val = 0;
head = create(head,5);
while(head!=NULL)
{
cout<<head->val<<endl;
head = head->next;
}
Node *result = new Node();
reverse(head);
result = head;
while(result!=NULL)
{
cout<<result->val<<endl;
result = result->next;
}
return 0;
}