链表相关知识:
单链表:通过指针串联在一起的线性结构,由两部分组成,一部分数据域,一部分指针域,通过结构体来对其进行创建,其包含一个数值,一个指针(指向下一个链表),还有一个构造函数
双链表:包含两个指针,一个指向前面一个指向后面
存储结构:链表的内存是不连续的,而是散乱分布,每次定义链表的时候都需要new一块内存
链表定义:
Struct ListNode
{
int val;
ListNode *next;
ListNode(int x):val(x),next(NULL){}
}
链表的基础操作:删除,增加
为了方便链表的操作,通常设置头结点,头结点的数值域为空(也可以存储线性表长度等附加信息)
但指针指向头链表的第一个节点
L203.移除链表元素https://leetcode.cn/problems/remove-linked-list-elements/
#include<iostream>
using namespace std;
//定义链表
struct ListNode {
int val;
ListNode* next;
//构造函数
ListNode():val(0),next(NULL){}
ListNode(int val) :val(val), next(NULL) {}
ListNode(int val,ListNode*next):val(val),next(next){}
};
//解法一:
//本题考查对链表删除操作,即从头结点开始遍历,找到当前链表的值
//将上一指针指向下一链表
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//判断当前头结点的val是否等于val
//循环条件就是head!=NULL,和head->val==val,若等于,就先用一个指针指向当前head,然后再把当前head指向head指向的下一个链表
while (head != NULL && head->val == val)
{
ListNode* solve = head;
head = head->next;
delete solve;
}
//若链表不是头结点,也就是头结点判断完毕,那就开始判断头结点后面的节点
//先定义一个节点取代当前的头结点,因为都是采用指针进行操作,故修改其中的值,整个链表都会发生变化
ListNode* result=head;
//这里的判断条件就是,当前节点不为空,当前节点的下一个节点也不为空,
while (result!=NULL&&result->next!=NULL)
{
//如果当前节点的下一个节点的值等于val,那么就对其进行操作
if (result->next->val == val)
{
ListNode* solve = result->next;
result->next = solve->next;
delete solve;
}
else//若不等于,就对其取代为下一个节点
{
result = result->next;
}
}
return head;
}
};
//解法二:
//设置一个虚拟头结点,也就是前面所述的设置一个头结点
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//定义一个空链表
ListNode* solve = new ListNode(0);
solve->next = head;
//将当前头指针赋予result
ListNode* result = solve;
while (result->next != NULL)
{
if (result->next->val == val)
{
ListNode* mid = result->next;
result->next = mid->next;
delete mid;
}
else {
result = result->next;
}
}
//循环结束,将头结点指向当前虚拟头结点所指向的指针方向
head = solve->next;
delete solve;
return head;
//最好是把所申请的内存进行删除,不然会造成内存泄露
}
};
L707.设计链表https://leetcode.cn/problems/design-linked-list/submissions/
本题中,需要对链表进行结构体定义,也就是链表的初始化,并且在类中定义两个变量,虚拟头结点的val值可以什么都不放,但也可以放本链表的相关长度值(但需要注意是从0开始到size-1)
class MyLinkedList {
public:
struct ListNode {
int val;
ListNode* next;
ListNode(int val) :val(val), next(NULL){}
};
//构造函数,用来初始化MyLinkedList对象
//这里定义的是虚拟头结点
MyLinkedList()
{
size = 0;
Resulthead = new ListNode(0);
}
//找到下标为index的节点的值,下标无效则返回
//也就是返回按照单列表的排序,index代表哪个链表,将他的值返回即可
int get(int index)
{
//看下标index是否比size大,或者小于0
if (index > (size - 1) || index < 0)
{
return -1;
}
ListNode* solve = Resulthead->next;
while (index--)
{
solve = solve->next;
}
return solve->val;
}
void addAtHead(int val) {
ListNode* mid = new ListNode(val);
mid->next = Resulthead->next;
Resulthead->next = mid;
//添加完之后 size要进行+1;
size++;
}
void addAtTail(int val) {
//定义一个val
ListNode* mid = new ListNode(val);
ListNode* cur = Resulthead;
//现在来寻找当前链表的最后一个表格
while (cur->next!=NULL)
{
cur = cur->next;
}
//已经找到最后一个链表,对其进行指针的交换即可
cur->next = mid;
size++;
}
void addAtIndex(int index, int val) {
//如果相等,直接调用附加到最后一个的函数
if (index < 0)
{
index = 0;
}
else if (index > size )
return;
ListNode* mid = new ListNode(val);
ListNode* result = Resulthead;
while (index--)
{
result = result->next;
}
mid->next = result->next;
result->next = mid;
size++;
}
void deleteAtIndex(int index) {
if (index >= size || index < 0) {
return;
}
ListNode* cur = Resulthead;
while (index--) {
cur = cur->next;
}
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
size--;
}
//打印链表
void printLinkedList() {
ListNode* cur = Resulthead;
while (cur->next != nullptr) {
cout << cur->next->val << " ";
cur = cur->next;
}
cout << endl;
}
private:
//每个对象中都有一个值,一个自定义指针
int size;//代表链表的长度
ListNode* Resulthead;//链表的头指针
};
L206.反转链表https://leetcode.cn/problems/reverse-linked-list/
本题一开始让我有点懵逼,也是采用的双指针对其进行翻转,但始终没有把逻辑理清楚,也就是一个快指针,一个慢指针,将快指针所指向的链表用一个中间变量存储起来,然后改变将快指针的指针指向慢指针,慢指针在等于快指针,相当于是一个交换标量,最好还是结合图一起来。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//先定义一个虚拟节点
//先判断当前头节点是否为空,若为空直接返回
if (head == NULL)return head;
ListNode* cur = head;
ListNode* pre = NULL;
//ListNode* result = NULL;
while (cur)
{
//先将当前节点指向的下一节点给一个节点存储起来
ListNode* result = cur->next;
cur->next = pre;
pre = cur;
cur = result;
}
return pre;
}
};