打卡 DAY 9 设计链表

力扣原题链接

一、题目描述

二、 思路

  1. 因为题目描述提及:

    所以本题使用虚拟头节点(我感觉本质就是头指针)。

三、解题过程

  • 定义链表节点内元素:

typedef struct MyLinkedList{
    int val;
    struct MyLinkedList* next;
} MyLinkedList;
  • 初始化链表:

  1. 动态分配虚拟头节点的内存;
  2. 将虚拟头节点的next指针指向NULL;
  3. 返回虚拟头节点的地址。
MyLinkedList* myLinkedListCreate() {
    MyLinkedList* pHead = (MyLinkedList*)malloc(sizeof(MyLinkedList));
    pHead -> next = NULL;
    return pHead;
}
  •  获取下标为index的节点的值。若下标无效,则返回-1:

  1. 通过遍历来寻找下标为index的节点;
  2. 若找得到,则输出该节点的值;若找不到,则返回-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的节点插入到第一个链表元素之前:

  1. 定义一个值为val的新节点;
  2. 将新节点的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的节点追加到链表中,作为链表的最后一个元素:

  1. 定义一个值为val的新节点;
  2. 遍历链表到最后一个节点;
  3. 让最后一个节点的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比长度更大,该节点将不会插入到链表中:

  1. 先判断index是否为零,若为零,则作为新的链表第一个元素插入链表;
  2. 定义一个值为val的新节点;
  3. 定义temNode = obj;
  4. 遍历找到下标为index的节点(temNode储存着下标为index - 1的节点地址);
  5. 设置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的节点:

  1. 定义temNode = obj;
  2. 遍历找到下标为index的节点(temNode储存着下标为index - 1的节点地址);
  3. 设置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;
    }
}
  • 销毁链表

  1. 循环定义temNode = obj,同时obj不断往后移;
  2. 遍历链表去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。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值