一、题目描述
二、 思路
-
因为题目描述提及:
所以本题使用虚拟头节点(我感觉本质就是头指针)。
三、解题过程
-
定义链表节点内元素:
typedef struct MyLinkedList{
int val;
struct MyLinkedList* next;
} MyLinkedList;
-
初始化链表:
- 动态分配虚拟头节点的内存;
- 将虚拟头节点的next指针指向NULL;
- 返回虚拟头节点的地址。
MyLinkedList* myLinkedListCreate() {
MyLinkedList* pHead = (MyLinkedList*)malloc(sizeof(MyLinkedList));
pHead -> next = NULL;
return pHead;
}
-
获取下标为index的节点的值。若下标无效,则返回-1:
- 通过遍历来寻找下标为index的节点;
- 若找得到,则输出该节点的值;若找不到,则返回-1。
int myLinkedListGet(MyLinkedList* obj, int index) {
MyLinkedList* tem = obj -> next;
for(int i = 0; tem; i ++){
if(i == index) return tem -> val;
tem = tem -> next;
}
return -1;
}
-
将一个值为val的节点插入到第一个链表元素之前:
- 定义一个值为val的新节点;
- 将新节点的next指向原第一个链表节点,然后将虚拟头节点的next指针指向新节点。
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
MyLinkedList* newNode = (MyLinkedList*)malloc(sizeof(MyLinkedList));
newNode -> val = val;
newNode -> next = obj -> next;
obj -> next = newNode;
}
-
将一个值为val的节点追加到链表中,作为链表的最后一个元素:
- 定义一个值为val的新节点;
- 遍历链表到最后一个节点;
- 让最后一个节点的next指针指向新节点。
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList* temNode = obj;
MyLinkedList* newNode = (MyLinkedList*)malloc(sizeof(MyLinkedList));
newNode -> val = val;
newNode -> next = NULL;
while(temNode -> next) temNode = temNode -> next;
temNode -> next = newNode;
}
-
将一个值为val的节点插入到链表中下标为index的节点之前。如果index等于链表长度,那么该节点会被追加到链表末尾。如果index比长度更大,该节点将不会插入到链表中:
- 先判断index是否为零,若为零,则作为新的链表第一个元素插入链表;
- 定义一个值为val的新节点;
- 定义temNode = obj;
- 遍历找到下标为index的节点(temNode储存着下标为index - 1的节点地址);
- 设置for(i = 0; temNode -> next; i ++)去判断链表长度,若index小于链表长度(没跳出for循环),则正常接上新节点;若跳出了for循环,则要分两种情况讨论:当i == index
- 1时(index等于链表长度),新节点追加到链表末尾;若i < index- 1(index大于链表长度),则不插入新节点,且free掉新节点!
注意!i 跳出循环后的值为链表长度!!!所以是判断i == index,而不是判断i == index - 1!!
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
if(index == 0) {
myLinkedListAddAtHead(obj, val);
return ;
}
MyLinkedList* temNode = obj;
MyLinkedList* newNode = (MyLinkedList*)malloc(sizeof(MyLinkedList));
newNode -> val = val;
int i = 0;
for(; temNode -> next; i++) {
if(i == index){
newNode -> next = temNode -> next;
temNode -> next = newNode;
return ;
}
temNode = temNode -> next;
}
if(i == index) {
temNode -> next = newNode;
newNode -> next = NULL;
return ;
}
free(newNode);
}
-
如果传入的下标有效,则删除链表中下标为index的节点:
- 定义temNode = obj;
- 遍历找到下标为index的节点(temNode储存着下标为index - 1的节点地址);
- 设置for(int i = 0; temNode -> next; i ++)去找到下标为index的节点:若存在,则删除(free)该节点。
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
MyLinkedList* temNode = obj;
for(int i = 0; temNode -> next; i ++){
if(i == index){
MyLinkedList* freeNode = temNode -> next;
temNode -> next = temNode -> next -> next;
free(freeNode);
return ;
}
temNode = temNode -> next;
}
}
-
销毁链表
- 循环定义temNode = obj,同时obj不断往后移;
- 遍历链表去free掉各个节点。
void myLinkedListFree(MyLinkedList* obj) {
while(obj){
MyLinkedList* freeNode = obj;
obj = obj -> next;
free(freeNode);
}
}
四、遇到的问题
- 在编写myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val)函数时,将 i 跳出循环后该有的值判断错误,导致一直代码通不过!下次应该仔细点,不然写代码5min,找错5h。。。