# 题目地址 https://leetcode-cn.com/problems/design-linked-list/ > 听说这道题目把链表常见的五个操作都覆盖了? # 第707题:设计链表 题意: 在链表类中实现这些功能: * get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。 * addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。 * addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。 * addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。 * deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。 ![707示例](https://img-blog.csdnimg.cn/20200814200558953.png) # 思路 如果对链表的基础知识还不太懂,可以看这篇文章:[关于链表,你该了解这些!](https://mp.weixin.qq.com/s/ntlZbEdKgnFQKZkSUAOSpQ) 如果对链表的虚拟头结点不清楚,可以看这篇文章:[链表:听说用虚拟头节点会方便很多?](https://mp.weixin.qq.com/s/slM1CH5Ew9XzK93YOQYSjA) 删除链表节点: ![链表-删除节点](https://img-blog.csdnimg.cn/20200806195114541.png) 添加链表节点: ![链表-添加节点](https://img-blog.csdnimg.cn/20200806195134331.png) 这道题目设计链表的五个接口: * 获取链表第index个节点的数值 * 在链表的最前面插入一个节点 * 在链表的最后面插入一个节点 * 在链表第index个节点前面插入一个节点 * 删除链表的第index个节点 可以说这五个接口,已经覆盖了链表的常见操作,是练习链表操作非常好的一道题目 **链表操作的两种方式:** 1. 直接使用原来的链表来进行操作。 2. 设置一个虚拟头结点在进行操作。 下面采用的设置一个虚拟头结点(这样更方便一些,大家看代码就会感受出来)。 ## 代码 ``` class MyLinkedList { public: // 定义链表节点结构体 struct LinkedNode { int val; LinkedNode* next; LinkedNode(int val):val(val), next(nullptr){} }; // 初始化链表 MyLinkedList() { _dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点 _size = 0; } // 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 int get(int index) { if (index > (_size - 1) || index < 0) { return -1; } LinkedNode* cur = _dummyHead->next; while(index--){ // 如果--index 就会陷入死循环 cur = cur->next; } return cur->val; } // 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点 void addAtHead(int val) { LinkedNode* newNode = new LinkedNode(val); newNode->next = _dummyHead->next; _dummyHead->next = newNode; _size++; } // 在链表最后面添加一个节点 void addAtTail(int val) { LinkedNode* newNode = new LinkedNode(val); LinkedNode* cur = _dummyHead; while(cur->next != nullptr){ cur = cur->next; } cur->next = newNode; _size++; } // 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。 // 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点 // 如果index大于链表的长度,则返回空 void addAtIndex(int index, int val) { if (index > _size) { return; } LinkedNode* newNode = new LinkedNode(val); LinkedNode* cur = _dummyHead; while(index--) { cur = cur->next; } newNode->next = cur->next; cur->next = newNode; _size++; } // 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的 void deleteAtIndex(int index) { if (index >= _size || index < 0) { return; } LinkedNode* cur = _dummyHead; while(index--) { cur = cur ->next; } LinkedNode* tmp = cur->next; cur->next = cur->next->next; delete tmp; _size--; } // 打印链表 void printLinkedList() { LinkedNode* cur = _dummyHead; while (cur->next != nullptr) { cout << cur->next->val << " "; cur = cur->next; } cout << endl; } private: int _size; LinkedNode* _dummyHead; }; ``` > 更过算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。