题目链接:203.移除链表元素
视频链接:手把手带你学会操作链表 | LeetCode:203.移除链表元素_哔哩哔哩_bilibili
题解:
// 用原来的链表操作:
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* temp;
// 当头结点存在并且头结点的值等于val时
while(head && head->val == val) {
temp = head;
// 将新的头结点设置为head->next并删除原来的头结点
head = head->next;
free(temp);
}
struct ListNode *cur = head;
// 当cur存在并且cur->next存在时
// 此解法需要判断cur存在因为cur指向head。若head本身为NULL或者原链表中元素都为val的话,cur也会为NULL
while(cur && (temp = cur->next)) {
// 若cur->next的值等于val
if(temp->val == val) {
// 将cur->next设置为cur->next->next并删除cur->next
cur->next = temp->next;
free(temp);
}
// 若cur->next不等于val,则将cur后移一位
else
cur = cur->next;
}
// 返回头结点
return head;
}
设置一个虚拟头结点:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
typedef struct ListNode ListNode;
ListNode *shead;//设置虚拟头结点
shead = (ListNode *)malloc(sizeof(ListNode));
shead->next = head;
ListNode *cur = shead;
//设置临时指针指向虚拟头结点。因为如果要删头结点的话必须知道头结点的上一个结点
while(cur->next != NULL){
if (cur->next->val == val){
ListNode *tmp = cur->next;
cur->next = cur->next->next;
free(tmp);
}
else{
cur = cur->next;//继续往下遍历
}
}
head = shead->next;
free(shead);
return head;//返回虚拟头结点的下一个结点(因为头结点可能已经被删了)
}
题目链接:707.设计链表
视频链接:帮你把链表操作学个通透!LeetCode:707.设计链表_哔哩哔哩_bilibili
题解:
typedef struct MyLinkedList{
int val;
struct MyLinkedList* next;
}MyLinkedList;
//创建一个新链表
MyLinkedList* myLinkedListCreate(){
MyLinkedList* head = (MyLinkedList *)malloc(sizeof (MyLinkedList));
head->next = NULL;
return head;
}
//获取第index个结点的值
int myLinkedListGet(MyLinkedLiat* obj, int index){
MyLinkedList *cur = obj->next;
for(i=0;cur != NULL;i++){
if(i==index){
return cur->val;
}
else{
cur=cur->next;
}
}
return -1;
}
//头插
void myLinkedListAddAtHead(MyLinkedList* obj,int val){
MyLinkedList* nhead=(MyLinkedList*)malloc(sizeof(MyLinkedList));
nhead->val=val;
nhead->next=obj->next;
obj->next=nhead;
} //先将新头指向头结点,再把虚拟头结点指向新头
//尾插
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList *cur = obj;
while(cur->next != NULL){
cur = cur->next;
}
MyLinkedList *ntail = (MyLinkedList *)malloc(sizeof (MyLinkedList));
ntail->val = val;
ntail->next = NULL;
cur->next = ntail;
}
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
if (index == 0){
myLinkedListAddAtHead(obj, val);
return;
}
MyLinkedList *cur = obj->next;
for (int i = 1 ;cur != NULL; i++){
if (i == index){
MyLinkedList* newnode = (MyLinkedList *)malloc(sizeof (MyLinkedList));
newnode->val = val;
newnode->next = cur->next;
cur->next = newnode;//顺序不能反
return;
}
else{
cur = cur->next;
}
}
}
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
if (index == 0){
MyLinkedList *tmp = obj->next;
if (tmp != NULL){
obj->next = tmp->next;
free(tmp);
}
return;
}//删除头结点
MyLinkedList *cur = obj->next;
for (int i = 1 ;cur != NULL && cur->next != NULL; i++){
if (i == index){
MyLinkedList *tmp = cur->next;
if (tmp != NULL) {
cur->next = tmp->next;
free(tmp);
}
return;
}
else{
cur = cur->next;
}
}
}
void myLinkedListFree(MyLinkedList* obj) {
while(obj != NULL){
MyLinkedList *tmp = obj;
obj = obj->next;
free(tmp);
}
}
总结:链表的相关操作(n从0开始,虚拟头结点法)
第n个结点是cur->next!!!
1、获取第n个结点的值
2、头插
3、尾插
4、第n结点前插入节点
5、删第n个结点
题目链接:206.反转链表
视频链接:帮你拿下反转链表 | LeetCode:206.反转链表 | 双指针法 | 递归法_哔哩哔哩_bilibili
题解:
// 双指针法:
struct ListNode* reverseList(struct ListNode* head){
//保存cur的下一个结点
struct ListNode* temp;
//pre指针指向前一个当前结点的前一个结点
struct ListNode* pre = NULL;
//用head代替cur,也可以再定义一个cur结点指向head。
while(head) {
//保存下一个结点的位置
temp = head->next;
//翻转操作
head->next = pre;
//更新结点
pre = head;
head = temp;
}
return pre;
}
//递归法
struct ListNode* reverse(struct ListNode* pre, struct ListNode* cur) {
if(!cur)
return pre;
struct ListNode* temp = cur->next;
cur->next = pre;
//将cur作为pre传入下一层
//将temp作为cur传入下一层,改变其指针指向当前cur
return reverse(cur, temp);
}
struct ListNode* reverseList(struct ListNode* head){
return reverse(NULL, head);
}