C++算法练习-day7——707.设计链表

题目来源:. - 力扣(LeetCode)

题目思路分析

在编程中,链表是一种常见的数据结构,用于存储一系列元素,但与数组不同,链表中的元素在内存中不必连续存储。每个元素(称为节点)包含数据部分和一个指向下一个节点的指针。本题要求我们实现一个自定义的链表类MyLinkedList,支持以下操作:

  1. 获取指定位置的元素 :get(int index)方法,根据索引返回链表中的元素值,索引无效时返回-1。
  2. 在头部添加元素 :addAtHead(int val)方法,在链表头部插入一个新节点。
  3. 在尾部添加元素 :addAtTail(int val)方法,在链表尾部插入一个新节点。
  4. 在指定位置添加元素 :addAtIndex(int index, int val)方法,在链表的指定位置插入一个新节点。
  5. 删除指定位置的元素 :deleteAtIndex(int index)方法,删除链表中指定位置的节点。

为了高效实现这些操作,我们需要维护一个指向链表头部的指针(head),以及一个记录链表大小的变量(size)。使用虚拟头节点(dummy node)可以简化边界情况的处理,例如当index为0时,我们不需要特殊处理头部插入的情况。

代码实现与注解

实例:

复制代码
#include <algorithm> // 为了使用std::max  
  
struct ListNode {  
    int val;  
    ListNode *next;  
    ListNode(int x) : val(x), next(nullptr) {}  
};  
  
class MyLinkedList {  
public:  
    MyLinkedList() {  
        this->size = 0;  
        // 使用虚拟头节点简化操作  
        this->head = new ListNode(0);  
    }  
      
    // 获取指定位置的元素值  
    int get(int index) {  
        if (index < 0 || index >= size) {  
            return -1; // 索引无效,返回-1  
        }  
        ListNode *cur = head;  
        for (int i = 0; i <= index; i++) { // 循环到目标位置的后一个节点  
            cur = cur->next;  
        }  
        return cur->val; // 返回目标节点的值  
    }  
      
    // 在头部添加元素  
    void addAtHead(int val) {  
        addAtIndex(0, val);  
    }  
      
    // 在尾部添加元素  
    void addAtTail(int val) {  
        addAtIndex(size, val);  
    }  
      
    // 在指定位置添加元素  
    void addAtIndex(int index, int val) {  
        if (index > size) {  
            return; // 索引超出链表长度,不执行任何操作  
        }  
        index = max(0, index); // 确保索引不小于0  
        size++; // 链表长度加1  
        ListNode *pred = head;  
        for (int i = 0; i < index; i++) {  
            pred = pred->next;  
        }  
        ListNode *add = new ListNode(val);  
        add->next = pred->next; // 新节点的next指向原位置的下一个节点  
        pred->next = add; // 原位置的节点指向新节点  
    }  
      
    // 删除指定位置的元素  
    void deleteAtIndex(int index) {  
        if (index < 0 || index >= size) {  
            return; // 索引无效,不执行任何操作  
        }  
        size--; // 链表长度减1  
        ListNode *pred = head;  
        for (int i = 0; i < index; i++) {  
            pred = pred->next;  
        }  
        ListNode *p = pred->next; // 待删除节点  
        pred->next = pred->next->next; // 跳过待删除节点  
        delete p; // 释放待删除节点的内存  
    }  
  
private:  
    int size; // 链表长度  
    ListNode *head; // 链表头部指针(虚拟头节点)  
};

主函数部分:

复制代码
int main() {  
    MyLinkedList* obj = new MyLinkedList();  
    obj->addAtHead(1);  
    obj->addAtTail(3);  
    obj->addAtIndex(1, 2); // 链表现在是1->2->3  
    cout << obj->get(1) << endl; // 输出2  
    obj->deleteAtIndex(1); // 删除索引1处的节点,链表现在是1->3  
    cout << obj->get(1) << endl; // 输出3  
    delete obj;  
    return 0;  
}

知识点摘要

  1. 链表的基本概念:链表是一种链式存储结构,由一系列节点组成,每个节点包含数据部分和一个指向下一个节点的指针。
  2. 虚拟头节点:在链表头部添加一个不存储实际数据的虚拟节点,可以简化边界情况的处理。
  3. 动态内存管理 :使用new和delete关键字在C++中管理动态内存,确保在不再需要时释放内存,防止内存泄漏。
  4. 时间复杂度分析 :get、addAtHead、addAtTail、addAtIndex和deleteAtIndex方法的时间复杂度均为O(n),其中n为链表长度。这是因为这些方法在最坏情况下都需要遍历链表的一部分或全部节点。

通过实现自定义链表,我们不仅加深了对链表的理解,还学会了如何在实际编程中运用这些概念。

相关推荐
kimnoic6 小时前
Python数据库学习心得:SQLite、MySQL、PostgreSQL优缺点
开发语言·python
别动我齐刘海6 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
程序员老陆7 小时前
C++ std::promise深度解析
c++·程序设计
必须得开心呀7 小时前
python编写带界面的软件,需要安装哪些插件
开发语言·python
青少儿编程课堂7 小时前
迪杰斯特拉(Dijkstra)算法:单源最短路与赛场路线规划
c++·python·算法·bfs·信息学竞赛
沫璃染墨9 小时前
《Qt从零入门系列(十三):QSS样式表详解——从选择器与层叠规则到控件美化实战》
开发语言·css·c++·qt·ui·qt6.3·qss
达子6669 小时前
RUST 图解 第 3 章:通用编程概念(Common Programming Concepts)
开发语言·算法·rust
道尔柯南10 小时前
C++ 面向对象编程入门:类和对象(上)
开发语言·c++·算法
楠楠子呀10 小时前
英语、西语、阿语客户各开一个口:多语言获客的分流方案
开发语言·javascript·ecmascript·跨境电商·whatsapp·营销工具
tachibana210 小时前
使用for range 的时候,它的地址会发生变化吗?
开发语言·后端·golang·go·语法