是很简单的一道题:反转链表
哈哈~反正想从最简单的做起,再复习一下基本概念。
链表
链表通过“链”建立起数据元素之间的逻辑关系,因此插入和删除操作不需要移动元素,指只需要修改指针,但也会失去顺序表可随机存取的优点。为了建立数据元素之间的数据关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。
data为数据域,存放数据元素;next为指针域,存放其后继结点的地址。
data | next |
---|
单链表附加指针域,对比顺序表,存在浪费存储空间的缺点。由于链表是非随机存储结构,查找表中某个点时,需要从表头开始遍历,依次查找。
通常单链表用一个头指针来标识。
可以在单链表第一个结点前附加一个结点,称为头结点,头结点的指针域可以线性表的第一个元素结点。
头指针和头结点:
头指针->头结点->第一个元素结点
头指针->第一个元素结点
即:无论有没有头结点,头指针都存在,并且指向链表的第一个结点,如果引入了头结点,链表的第一个结点就是头结点。
单链表建立的实现
用头插法建立单链表
从一个空表开始,生成新结点,并将读取到的数据存放到新结点的数据域,将新结点插入到当前链表的表头,即头结点之后。
LinkList List_HeadInsert(Linklist &L){
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode));//创建头结点
L->next=NULL; //最后表尾结点的next为空
scanf("%d,&x");
while(x!=888){
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d,&x");
}
return L;
}
用尾插法建立单链表
如果希望生成的链表中结点的次序和输入数据的顺序一致,可以用尾插法。
这种方法将新结点插到当前链表的表尾,为此,要增加一个尾指针,使其始终指向当前链表的尾结点。
Linklist List_TailInsert(Linklist &L){
int x;
L=(Linklist)malloc(sizeof(LNode)); //分配头结点位置并使L指向它
LNode *s,*r=L;
scanf("%d,&x");
while(x!=888){
s=(LNode *)malloc(sizeof(LNode));
r->next=s;
s->data=x;
r=s; //r指向新的表尾
scanf("%d,&x");
}
r->next=NULL
return L;
}
在上面,LinkList是一个指向结点的指针,只是它是指向头结点的,其实与LNode*是一个意思。
除了建立链表,链表的基本操作还包括:按序号查找结点值,按值查找表结点,插入结点、删除结点,求表长等操作。
解题
我想到的第一个方法就是递归,但是本身自己对递归理解困难,去找了别人的方法,得到答案:
struct ListNode* reverseList(struct ListNode* head){
//它的反转就是本身
if(!head || !head->next) return head;
//取出head节点,调用函数自身将head->next为头的链表反转,结果保存在new_head中
struct ListNode *new_head = reverseList(head->next);
//new_head的尾巴是head->next,所以需要将之前弹出的head接在此尾巴上
head->next->next = head;
head->next = NULL; //防止生成循环链表
return new_head;
}
另一种方法是用头插法,遍历链表进行反转:
//借助两个指针来将指向关系反转
struct ListNode* reverseList(struct ListNode* head){
struct ListNode *pre = NULL, *nex;//pre表示新表的首结点,初始化为NULL,使新表尾端指向空,nex记录顺序遍历的下一结点
while (head){
nex = head -> next;//记录下一结点
head -> next = pre;//当前遍历的结点连接pre
pre = head;//pre指向当前结点,当前结点成为新表的首结点
head = nex;//指向当前结点下一结点,所以nex的作用在于辅助遍历,防止断链
}
return pre;//返回新表首结点
}
同时还有另一种双指针做法:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == NULL) { return NULL; }
ListNode* cur = head;
while (head->next != NULL) {
ListNode* t = head->next->next;
head->next->next = cur;
cur = head->next;
head->next = t;
}
return cur;
}
};