leetcode链表

这篇博客详细介绍了单链表的特性及操作,包括带头节点和不带头节点的插入元素方法,删除元素的步骤,以及如何创建链表。同时,展示了两种不同的链表反转实现,并提供了删除链表中特定元素的解决方案。内容涵盖了链表的基本操作和C++实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时间复杂度:算法的时间开销与问题规模之间的关系
单链表
特点:与数组与vector对象不同,其属于非顺序存储,使用next访问下一个元素,数据存储时不仅要存储数据,还需要存储下一个节点的地址,最后一个节点指向空值
1.插入元素
①带头节点,插入元素不需要单独定义表头,但是在传递参数时需要包含头节点
②不带头节点,插入元素时需要单独定义表头,传递参数时不需要包含头节点
2.删除元素
利用next来进行,通常需要获知第一个节点
3.创建链表

//单链表节点定义c++
struct ListNode{
    int val;
    ListNode *next;
    //下面对于代码中进行初始化链表很重要
    ListNode() : val(0), next(nullptr) {}   //初始化当前结点值为默认值0,指针为空
    ListNode(int x) : val(x), next(nullptr) {}    //初始化当前结点值为x,指针为空
    ListNode(int x, ListNode *next) : val(x), next(next) {}    //初始化当前结点值为x,下一个绩点为next
};

//分配新节点 上面的ListNode是可以更改的,属于自定义变量名
ListNode *head = nullptr;//定义一个初始为空的链表
head = new ListNode;//分配新节点
head->value = 12.5;
head->next = nullptr;//表示链表最后一个节点

删除链表中的某些特定元素

#include<iostream>
#include<vector>

struct ListNode {
	int val;
	ListNode *next;
	ListNode() : val(0), next(nullptr) {}   //初始化当前结点值为默认值0,指针为空
	ListNode(int x) : val(x), next(nullptr) {}    //初始化当前结点值为x,指针为空
	ListNode(int x, ListNode *next) : val(x), next(next) {}    //初始化当前结点值为x,下一个绩点为next

};
//class需要在main的前面
class Solution {
public:
	ListNode* removeElements(ListNode* head, int val) {
		if (head == nullptr) return NULL;
		ListNode *H = new ListNode;
		H->next = head;
		ListNode *p = H;// new head
		//在这里修改了p,H也会随之变化
		while (p->next != nullptr) {
			//H->next = p;
			if (p->next->val == val) {			
				p->next = p->next->next;
			}
			else
			{
				p = p->next;
			}
		}
		return H->next->next;
	}
};
int main() {
	Solution solution;
	int nums[] = { 1, 2, 6, 3, 4, 5, 6 };
	int length = sizeof(nums) / sizeof(int);
	ListNode *head=new ListNode;
	ListNode *H = new ListNode;
	head = H;
	//head = (ListNode)malloc(sizeof(ListNode));
	//给链表中赋值
	for (int i = 0;i < length; i++) {
		ListNode *p = new ListNode;//表头,默认值为0
		p->val = nums[i];
		//p->next = nullptr;
		H->next = p;
		H = p;
	}
	int val = 6;
	head = solution.removeElements(head, val);
	return 0;
}

上面的head是没办法通过p的改变来进行修改,只能够重新构建一个链表。这个链表名为p,通过修改p,H的值的索引会发生改变(这里我不太懂)

在这里插入图片描述

if (head == nullptr) return NULL;
		ListNode* p1 = head;
		ListNode* p2 = new ListNode(head->val);
		//p2 = head->val
		while (p1->next != nullptr) {
			ListNode* tmp = new ListNode(p1->next->val);
			tmp->next = p2;
			p2 = tmp;
			p1 = p1->next;
		}
		return p2;
if (head == nullptr || head->next == nullptr) return head;
		ListNode* p = head;
		ListNode* pre = nullptr;
		while (p) {
			ListNode* pnext = p->next;
			p->next = pre;
			pre = p;
			p = pnext;
		}
		return pre;

以上两个代码都是解决链表反转问题,为什么两个head的变化不一样,前者不会跟随p1变化,后者会跟随p变化
双链表
特点:每个数据结点都有两个指针,分别指向直接前驱与后继

//双链表节点定义c++
struct ListNode{
    int val;
    ListNode *next;
    ListNode *last;
    //ListNode(int x):val(x),next(nullpter){}
};

循环链表:单链与双链表

链表的缺点:必须从第一个节点开始遍历所有数据

参考资料
c++链表(详解版)
C++链表及其创建
C++ 自定义单向链表 ListNode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值