每日一题——设计单链表

简介: 每日一题——设计单链表

设计单链表

题目链接

要求

题目要我们实现有关单链表的基本操作,即以下几个函数:

MyLinkedList* myLinkedListCreate()    //创建单链表
int myLinkedListGet(MyLinkedList* obj, int index)   //得到下标为index的节点的值,如果index无效则返回-1
void myLinkedListAddAtHead(MyLinkedList* obj, int val)    //链表头插
void myLinkedListAddAtTail(MyLinkedList* obj, int val)    //链表尾插
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val)    //在下标index处插入值为val的节点,如果index等于链表长度,则相当于尾插
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index)  //删除下标为index的节点,如果index无效,则不操作
void myLinkedListFree(MyLinkedList* obj)    //删除链表

解析函数形参

  • 我们知道,单链表有带哨兵位(头一个节点为无效节点)和不带哨兵位(第一个节点就存储有效数据)两种形式,而二者在用法上的主要区别,就是在对头结点的处理上
  • 例如,如果我们要删除链表第一个有效节点,若我们的链表有哨兵位,那就好办,直接让哨兵位链接到第二个节点即可,但如果我们的链表没有哨兵位呢?那操作就不是删除第一个节点然后返回第二个节点这么简单了,因为我们知道,函数的形参只是实参的一份临时拷贝,对形参的修改不会影响实参,也就是说,在函数中删除我们的第一个节点,实际上实参的头节点仍然存在,因此如果想要对无哨兵位的链表进行头删操作,就要传入头节点的二级指针,这样才能达到要求。
  • 我们看到题目所给的函数形参传入的是一级指针,因此显然,我们要使用带哨兵位的链表。

实现代码

typedef struct List {
    int val;
    struct List *next;
} MyLinkedList;
//初始化单链表
MyLinkedList* myLinkedListCreate() {
    MyLinkedList *head = (MyLinkedList *)malloc(sizeof(MyLinkedList));
    head->next = NULL;
    return head;   
}
//得到下标为index的节点的值,如果index无效则返回-1
int myLinkedListGet(MyLinkedList* obj, int index) {
    MyLinkedList *cur = obj->next;  //第一个节点不存储有效数据,因此从后一个节点开始计数
    int count = 0;
    while(cur)
    {
        if(count == index)
            return cur->val;
        cur = cur->next;
        count++;
    }
    return -1;
}
//头插
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
    //创建新节点
    MyLinkedList *newHead = (MyLinkedList*)malloc(sizeof(MyLinkedList));
    newHead->val = val;
    newHead->next = NULL;
    //如果链表为空
    if(obj->next == NULL)
        obj->next = newHead;
    //如果链表不为空
    else
    {
        newHead->next = obj->next;
        obj->next = newHead;
    }
}
//尾插
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
    //创建尾节点
    MyLinkedList *newHead = (MyLinkedList*)malloc(sizeof(MyLinkedList));
    newHead->val = val;
    newHead->next = NULL;
    //找到链表的尾
    MyLinkedList *cur = obj;
    while(cur->next)
        cur = cur->next;
    //实现插入
    cur->next = newHead;
}
//在下标index处插入值为val的节点,如果index等于链表长度,则相当于尾插
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
    //如果index为0,相当于头插
    if(index == 0)
    {
        myLinkedListAddAtHead(obj,val);
        return;
    }
    MyLinkedList *newHead = (MyLinkedList*)malloc(sizeof(MyLinkedList));  //新建节点
    //第一个节点不存储有效数据,因此从后一个节点开始计数,同时定义一个指针记录cur的前一个节点便于插入
    MyLinkedList *cur = obj->next, *pre = obj;
    newHead->val = val;
    int count = 0;
    while(cur)
    {
        //如果index大于0小于链表长度
        if(count == index && cur != NULL)
        {
            pre->next = newHead;
            newHead->next = cur;
            return;
        }
        pre = cur;
        cur = cur->next;
        count++;
    }
    //如果index等于链表长度,直接尾插
    if(count == index && cur == NULL)
    {
        myLinkedListAddAtTail(obj,val);
        return;
    }
    //index不合法,直接return
    return;
}
//删除下标为index的节点,如果index无效,则不操作
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
    //第一个节点不存储有效数据,因此从后一个节点开始计数,同时定义一个指针记录cur的前一个节点便于删除
    MyLinkedList *cur = obj->next, *pre = obj;
    int count = 0;
    while(cur)
    {
        if(count == index)
        {
            pre->next = cur->next;
            free(cur);
            return;
        }
        pre = cur;
        cur = cur->next;
        count++;
    }
    return;
}
//销毁链表
void myLinkedListFree(MyLinkedList* obj) {
    MyLinkedList *cur = obj->next;
    while(cur)
    {
        MyLinkedList *temp = cur->next; //定义temp记录cur的下一个位置
        free(cur);
        cur = temp;
    }
}


相关文章
|
算法 Python
【Leetcode刷题Python】122.买卖股票的最佳时机 II
LeetCode "买卖股票的最佳时机 II" 问题的Python代码实现,采用贪心算法在股票价格上升的每一天买入并卖出,以获得最大利润。
163 0
|
自然语言处理 算法 API
阿里云百炼产品初体验评测
从小白入门到操作体验,带领大家一起探索阿里云百炼大模型平台的奥秘。
18639 9
阿里云百炼产品初体验评测
|
设计模式 前端开发 算法
QT5——模版库、工具类及控件(下)
QT5——模版库、工具类及控件
501 0
QT5——模版库、工具类及控件(下)
|
存储 关系型数据库 MySQL
如何在网站上安装 WordPress?
如何在网站上安装 WordPress?
217 0
|
数据挖掘 测试技术 数据库
APP内测分发平台功能开发部署规则设计说明
APP内测分发平台功能开发部署规则设计说明
|
应用服务中间件 网络安全 nginx
nginx应用
nginx应用
159 0
|
Shell 开发工具 开发者
Windows 11和vscode终端美化
允许powershell执行脚本,如果不允许的话,后续执行安装命令会报错 设置->隐私和安全性->开发者选项->powershell,点击应用 一款 Nerd Font,Nerd Font字体中包含了很多特殊的图标,如果不使用Nerd Font的话,后面设置了终端的主题后会乱码 这里我以Hasklig字体为例,下载链接。下载后会得到个Hasklig.zip的文件,解压后可以看到里面包含了很多字体。直接ctrl + A,然后右键选择安装全部字体
1100 0
|
人工智能 自动驾驶 新能源
再获逾40亿美元融资,滴滴要这么多钱干什么?
再获逾40亿美元融资,滴滴要这么多钱干什么?
398 0
再获逾40亿美元融资,滴滴要这么多钱干什么?
|
Java
JavaWeb - 一篇带你序列化 & 反序列化之性能对比分析(一)
JavaWeb - 一篇带你序列化 & 反序列化之性能对比分析(一)
264 0