链表相关基础知识
此部分来自代码随想录
题目讲解
一. 力扣203——移除链表元素
注意:
1.删除元素时添加一个头节点,这样就不用再写一个当删除节点时原头结点时的代码了。
2.当前节点不要设置为与val进行比较的节点,设置成上一个节点更方便循环条件的判断
3.注意需要手动管理内存,delete删除的节点(Java,python不用)
4.当p节点的下一个节点满足删除条件并且被删除后,不需要进行p = p->next操作,因为我们是对p->next节点进行判断的。
5.最后需要更新head节点!!(我总是忘记)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* Head = new ListNode(0);
Head->next = head;
ListNode *p = Head;//设置当前节点的上一个节点方便设置循环条件
while(p->next != NULL)
{
if(p->next->val == val)//结束后p不需要换到下一个节点,因为我们查看的就是p的下一个节点
{
ListNode* q = p->next;
p->next = q->next;
delete q;
}
else
{
p = p->next;
}
}
head = Head->next;//当原head被删除时,head节点需要改变
delete Head;
return head;
}
};
二.力扣707——设计链表
需要注意的都在代码里备注了,主要是删除指针之后要记得指向NULL
class MyLinkedList {
public:
struct LinkNode
{
int val;
LinkNode* next;
LinkNode(int x):val(x),next(nullptr){}
};
MyLinkedList() //初始化一个链表
{
Head = new LinkNode(0);
sizee = 0;
}
int get(int index) //若index有效返回下标为index的值
{
if(index < 0 || index >= sizee)
return -1;
LinkNode *p = Head->next;
while(index--)
{
p = p->next;
}
return p->val;
}
void addAtHead(int val) //在链表的最前端建立数值为val的新节点
{
LinkNode *q = new LinkNode(val);
q->next = Head->next;
Head->next = q;
sizee++;
}
void addAtTail(int val) //在链表末端建立数值为val的新节点
{
LinkNode *p = Head;
while(p->next != nullptr)
{
p = p->next;
}
LinkNode *q = new LinkNode(val);
p->next = q;
q->next = nullptr;
sizee++;
}
void addAtIndex(int index, int val) //在index结点之前插入数值为val的节点
{
if(index >= 0 && index <= sizee)
{
LinkNode *p = Head;
while(index--)
{
p = p->next;
}
LinkNode *q = new LinkNode(val);
q->next = p->next;
p->next = q;
sizee++;
}
}
void deleteAtIndex(int index) {
if(index >= 0 && index < sizee)
{
LinkNode *p = Head;
while(index--)
{
p = p->next;
}
LinkNode *tmp = p->next;
p->next = tmp->next;
sizee--;
delete tmp;
//delete命令指示释放了tmp指针原本所指的那部分内存,
//被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,
//如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针
//如果之后的程序不小心使用了tmp,会指向难以预想的内存空间
tmp = nullptr;
}
}
private:
LinkNode *Head;
int sizee;
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/
其中addatindex函数我一开始写的是这样的(如下)
也就是把index等于链表长度的情况分出来写的(其实没有必要),我这里就是复制的在尾部添加节点的代码,但一直跑不对,不知道哪里有问题,有大佬可以帮忙解答一下吗?
void addAtIndex(int index, int val) //在index结点之前插入数值为val的节点
{
if(index == sizee)
{
LinkNode *p = Head;
while(p->next != nullptr)
{
p = p->next;
}
LinkNode *q = new LinkNode(val);
p->next = q;
q->next = nullptr;
sizee++;
}
if(index >= 0 && index < sizee)
{
LinkNode *p = Head;
while(index--)
{
p = p->next;
}
LinkNode *q = new LinkNode(val);
q->next = p->next;
p->next = q;
sizee++;
}
}
三.力扣206——反转链表
注意:
我一开始用的是三个指针分别指向第0,1,2个节点,后来发现访问内存出现了问题,因为链表可能是一两个节点,甚至没有结点,所以错误。
正确代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *pre = NULL;
ListNode *q = head;
ListNode *k;
while(q)
{
k = q->next;
q->next = pre;
pre = q;
q = k;
}
return pre;
}
};