C++:Leetcode-链表-707设计链表
熟悉巩固链表的各种操作
题目
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。
在链表类中实现这些功能:
get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
思路分析
1、创建节点
2、索引获取节点值
3、添加头结点
4、添加尾节点
5、插入节点
6、删除节点
此题注意index是从0开始,linkedSize是实际长度,插入节点别漏情况,记得更新linkedSize即可
代码
/*
Leetcode-707设计链表
自行设计链表的一些功能,加强对链表的理解与运用能力
1、创建节点
2、索引获取节点值
3、添加头结点
4、添加尾节点
5、插入节点
6、删除节点
此题注意index是从0开始,linkedSize是实际长度,插入节点别漏情况,记得更新linkedSize即可
*/
#include "iostream"
#include "vector"
using namespace std;
class MyLinkedList
{
private:
/* data */
public:
//创建节点
class linkedNode
{
public:
int val;
linkedNode *next;
linkedNode() : val(0), next(nullptr) {}
linkedNode(int x) : val(x), next(nullptr) {}
linkedNode(int x, linkedNode *l_next) : val(x), next(l_next) {}
};
linkedNode *dummyHead; //虚拟头结点
int linkedSize;
//初始化虚拟头结点
MyLinkedList()
{
dummyHead = new linkedNode(0);
linkedSize = 0;
}
//初始化链表
linkedNode *createList(vector<int> &nums)
{
linkedNode *head = new linkedNode(nums[0]);
linkedNode *p = head;
for (int i = 1; i < nums.size(); i++)
{
p->next = new linkedNode(nums[i]);
p = p->next;
}
// delete p; //不能delete,有bug,当没有进入for,p的内存空间可能跟head一样,也会把head空间删除掉,return head出错!!!!!
linkedSize += nums.size();
dummyHead->next = head;
return head; //返回头节点
}
//索引获取节点值
//获取链表中第 index 个节点的值
//注意:index是从0开始,linkedSize就是实际长度
int get(int index)
{
if (index > (linkedSize - 1) || index < 0)
{
return -1;
}
linkedNode *current = dummyHead->next; //指向头节点
while (index--)
{
current = current->next;
}
return current->val;
}
//添加头结点
void addAtHead(int val)
{
linkedNode *newHead = new linkedNode(val);
newHead->next = dummyHead->next; //新头结点指向老头结点
dummyHead->next = newHead; //虚拟头结点指向新头结点
linkedSize++;
}
//添加尾节点
void addAtTail(int val)
{
linkedNode *newTail = new linkedNode(val);
linkedNode *current = dummyHead;
while (current->next != nullptr)
{
current = current->next;
}
current->next = newTail;
linkedSize++;
}
//插入节点
//在链表中的第 index 个节点之前添加值为 val 的节点
void addAtIndex(int index, int val)
{
linkedNode *newNoed = new linkedNode(val);
if (index == linkedSize) //节点插入末尾
{
addAtTail(val);
}
else if (index > linkedSize) //不插入节点
{
return;
}
else if (index == 0) //插入头部
{
addAtHead(val);
}
else //插入中间节点
{
linkedNode *current = dummyHead;
while (index--)
{
current = current->next;
}
newNoed->next = current->next;
current->next = newNoed;
linkedSize++;
}
}
//删除节点
//删除链表中的第 index 个节点。
//index从0开始,第0节点为头结点
//linkedSize为实际长度
void deleteAtIndex(int index)
{
//索引无效或没有节点
if (index < 0 || index >= linkedSize)
{
return;
}
else
{
linkedNode *current = dummyHead; // 现节点为虚拟节点,即头结点的上一个节点,方便后续寻找index的上一个节点
//遍历寻找第index个节点的上一个节点
while (index--)
{
current = current->next;
}
linkedNode *temp = current->next; //赋值给temp,方便delete
current->next = current->next->next;
delete temp;
linkedSize--;
}
}
//打印链表
void printlist()
{
linkedNode *current = dummyHead->next; //现节点为头结点
while (current != nullptr) //注意不是current->next!=nullptr ,因为尾节点的指针指向nullptr
{
cout << current->val << "\t";
current = current->next;
}
cout << endl;
}
};
int main(int argc, const char **argv)
{
vector<int> nums = {1};
MyLinkedList mylist;
mylist.createList(nums);
mylist.printlist();
mylist.addAtTail(3);
mylist.printlist();
mylist.addAtIndex(1, 2); //有问题
mylist.printlist();
cout << mylist.get(1) << endl; //有问题
mylist.deleteAtIndex(1);
mylist.printlist();
cout << mylist.get(1) << endl;
return 0;
}
总结
刷题巩固对链表的掌握,进一步加强对指针的运用和理解
参考代码随想录
https://www.programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html#%E4%BB%A3%E7%A0%81