【算法与数据结构】链表

news2024/10/7 10:24:02

链表

链表:结构定义

链表是由一串节点串联在一起的,链表的每个节点存储两个信息:数据+下一个节点的地址

在这里插入图片描述
分清楚两个概念:什么是内存内部,什么是程序内部
内存内部: 信息存储在内存空间里的
程序内部: 通过什么信息,去操作结构
如果想操作链表的话,我们依靠的是程序内部的信息,而不是内存内部的信息;所以在操作过程中,这些程序内部信息千万不能丢了,因为如果一旦丢了,那么对于内存内部的信息,就永远失去了访问的权限。

代码

结构定义

typedef struct Node{
	int data;
	struct Node *next;
} Node;

构造节点

Node * getNewNode(int val)
{
	Node *p = (Node*)malloc(sizeof(Node));
	p->data = val;
	p->next = NULL;  // 新的节点的下一个指向空
	return p;
}

删除链表
循环遍历节点,先用一个指针p指向头节点,因为先需要移动到下一个节点,再销毁前一个指针,所以需要一个q指针来记录下一个节点,然后销毁当前节点指针p

void clear(Node *head)
{
	if (head == NULL) return;
	// 循环遍历链表中每个节点, 当遍历不为空,就一直向后走
	for (Node *p = head, *q; p; p = q)   // p是当前节点
	{
		q = p->next;   // 先让q指向下一个节点
		free(p);       // 再销毁当前节点
	}
	return;
}

链表:插入元素

插入过程的操作顺序,直接影响了我们是否能正确插入一个元素
程序内部信息:head变量:指向整个链表的头地址,node变量:指向待插入的新节点
需要把4号节点插入到2节点后面
在这里插入图片描述
首先,需要一个指针p, 需要找到待插入位置的前一个元素,即1号节点,p指向1号元素
在这里插入图片描述
然后,让新的节点(4号节点)指向2号元素
在这里插入图片描述
然后,让1号元素指向新的节点(4号元素):
在这里插入图片描述
此时,在逻辑结构上,就已经完成了插入操作:
在这里插入图片描述

代码

因为这是无头链表结构,在实现插入操作的时候,返回的是完成插入之后新链表的首地址
无头链表插入操作后链表的首地址是可能发生改变的。
第一种情况:链表为空,或者插入的位置是0位置(原来链表头的位置),就会导致整个链表的头地址发生改变 ,直接返回新节点
第二种情况: 链表不为空,且插入位置在0之后,就是一般的插入操作,返回原链表头节点指针
p指针是用来找到待插入指针的前一个元素

Node * insert(Node *head, int pos, int val)
{
	if (pos == 0)
	{ 
		Node *node = getNewNode(val);  // 先创建新节点
		node->next = head;             // 让新节点指向原来的头节点
		return node;                   // 直接返回新节点
	}
	Node *p = head;                               // p找到待插入位置的前一个元素
	for (int i = 1; i < pos; i++) p = p->next;   // p走到待插入位置的前一个位置
	Node *node = getNewNode(val);                 // 创建新节点
	node->next = p->next;                        // 先让新节点的next指向待插入位置的节点,即p->next
	p->next = node;                             // 再让p的next指向新节点
	// 此时逻辑上已经完成了插入的操作
	return head;                               // 返回原链表头节点

}

链表:错误插入

由于链表的插入很容易犯错,这里演示一个错误的插入操作
先找到待插入位置的前一个元素
在这里插入图片描述
正确的插入顺序是,让新的元素指向2号元素;错误的操作是,让1号元素(待插入元素的前一个元素)指向新的元素(4号元素),那么就会发现2号元素的地址信息丢失了,也就是发生内存泄漏。
内存泄漏: 其实写的所有程序都占用内存空间,2号元素和3号元素,依然占用着我们的内存空间,但在程序中对这段信息没有办法进行操作。
对于中大型需要长期线上运行的系统,需要对内存泄漏的问题及其关注和避免的。

在这里插入图片描述

链表:无头链表

在头部是不存储信息的,所以在链表的头部存储的仅仅是一个指针。
在这里插入图片描述

链表:有头链表

在头部存储信息,在链表的头部存储的是一个节点。只不过这个节点有存储数据的区域,但我们不使用这个区域
虚拟头节点: 一般就是有头链表的头节点
在这里插入图片描述

代码演示

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>



typedef struct Node{
	int data;
	struct Node *next;
} Node;


Node * getNewNode(int val)
{
	Node *p = (Node*)malloc(sizeof(Node));
	p->data = val;
	p->next = NULL;  // 新的节点的下一个指向空
	return p;
}

Node *insert(Node *head, int pos, int val)
{
	if (pos == 0)
	{ 
		Node *node = getNewNode(val);  // 先创建新节点
		node->next = head;             // 让新节点指向原来的头节点
		return node;                   // 直接返回新节点
	}
	Node *p = head;                               // p找到待插入位置的前一个元素
	for (int i = 1; i < pos; i++) p = p->next;   // p走到待插入位置的前一个位置
	Node *node = getNewNode(val);                 // 创建新节点
	node->next = p->next;                        // 先让新节点的next指向待插入位置的节点,即p->next
	p->next = node;                             // 再让p的next指向新节点
	// 此时逻辑上已经完成了插入的操作
	return head;                               // 返回原链表头节点

}


void clear(Node *head)
{
	if (head == NULL) return;
	// 循环遍历链表中每个节点, 当遍历不为空,就一直向后走
	for (Node *p = head, *q; p; p = q)   // p是当前节点
	{
		q = p->next;   // 先让q指向下一个节点
		free(p);       // 再销毁当前节点
	}
	return;
}

void output_linklist(Node *head)
{
	// 0   1   2
	// 22->33->55
	int n = 0;
	for (Node *p = head; p; p = p->next) n += 1;   // 先求链表的长度n
	// 打印第一行序号
	for (int i = 0; i < n; i++)
	{
		printf("%3d", i);
		printf("  ");    // 对应链表的->两个字符
	}
	printf("\n");

	// 打印第二行链表
	for (Node *p = head; p; p = p->next)
	{
		printf("%3d", p->data);
		printf("->");
	}
	printf("\n\n");
	return; 


}


int main()
{
	srand(time(0));
    #define MAX_OP 7
	Node *head = NULL;
	for (int i = 0; i < MAX_OP; i++)
	{
		int pos = rand() % (i + 1), val = rand() % 100;    // 这里的第一个pos因为是随机数对1取余,永远都是0
		printf("insert %d at %d to linklist\n", val, pos);
		head = insert(head, pos, val);
		output_linklist(head);

	}
	std::cin.get();
	return 0;
}

输出:
在这里插入图片描述

链表:花式查找操作的实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>


#define DL 3
#define STR(n) #n
#define DIGIT_LEN_STR(n) "%" STR(n) "d"



typedef struct Node{
	int data;
	struct Node *next;
} Node;


Node * getNewNode(int val)
{
	Node *p = (Node*)malloc(sizeof(Node));
	p->data = val;
	p->next = NULL;  // 新的节点的下一个指向空
	return p;
}

Node *insert(Node *head, int pos, int val)
{
	if (pos == 0)
	{ 
		Node *node = getNewNode(val);  // 先创建新节点
		node->next = head;             // 让新节点指向原来的头节点
		return node;                   // 直接返回新节点
	}
	Node *p = head;                               // p找到待插入位置的前一个元素
	for (int i = 1; i < pos; i++) p = p->next;   // p走到待插入位置的前一个位置
	Node *node = getNewNode(val);                 // 创建新节点
	node->next = p->next;                        // 先让新节点的next指向待插入位置的节点,即p->next
	p->next = node;                             // 再让p的next指向新节点
	// 此时逻辑上已经完成了插入的操作
	return head;                               // 返回原链表头节点

}


void clear(Node *head)
{
	if (head == NULL) return;
	// 循环遍历链表中每个节点, 当遍历不为空,就一直向后走
	for (Node *p = head, *q; p; p = q)   // p是当前节点
	{
		q = p->next;   // 先让q指向下一个节点
		free(p);       // 再销毁当前节点
	}
	return;
}

void output_linklist(Node *head, int flag = 0)
{
	// 0   1   2
	// 22->33->55
	int n = 0;
	for (Node *p = head; p; p = p->next) n += 1;   // 先求链表的长度n
	// 打印第一行序号
	for (int i = 0; i < n; i++)
	{
		// printf("%3d", i);
		printf(DIGIT_LEN_STR(DL), i);
		printf("  ");    // 对应链表的->两个字符
	}
	printf("\n");

	// 打印第二行链表
	for (Node *p = head; p; p = p->next)
	{
		// printf("%3d", p->data);
		printf(DIGIT_LEN_STR(DL), p->data);
		printf("->");
	}
	printf("\n");
	if (flag == 0) printf("\n\n");
	return; 


}

int find(Node *head, int val)  
{
	// 查找,遍历链表的每个节点
	Node *p = head;  // 当前节点指针
	int n = 0;      // 用来记录输出元素个数
	while (p)
	{
		if (p->data == val){
			output_linklist(head, 1);
			int len = n * (DL + 2);      // 空字符个数
			for (int i = 0; i < len; i++) printf(" ");   // 输出前面的空格
			printf("^\n");
			for (int i = 0; i < len; i++) printf(" ");   // 输出前面的空格
			printf("|\n");
			return 1;
		}
		n += 1;
		p = p->next;
	}
	return 0;

}



int main()
{
	srand(time(0));
    #define MAX_OP 7
	Node *head = NULL;
	// 测试插入操作
	for (int i = 0; i < MAX_OP; i++)
	{
		int pos = rand() % (i + 1), val = rand() % 100;    // 这里的第一个pos因为是随机数对1取余,永远都是0
		printf("insert %d at %d to linklist\n", val, pos);
		head = insert(head, pos, val);
		output_linklist(head);

	}

	// 测试查找操作
	int val;
	while (scanf_s("%d", &val)){
		if (!find(head, val)) printf("not found\n");
	}
	std::cin.get();
	return 0;
}

输出链表的生成:
在这里插入图片描述
输出查找操作
在这里插入图片描述

链表:用有头链表改写插入操作

定义一个虚拟头节点,然后定义一个指针p,指向虚拟头节点
让虚拟头节点的下一节点为原来的头指针,此时形成了一个有头链表
然后开始插入操作,一样的,先找到待插入位置的前一个元素位置,这时候因为在0位置前有一个虚拟头节点,所以对于pos=0的情况,就是虚拟头节点本身。
注意:虚拟头节点的下一个节点才是要返回的头节点

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>


#define DL 3
#define STR(n) #n
#define DIGIT_LEN_STR(n) "%" STR(n) "d"



typedef struct Node{
	int data;
	struct Node *next;
} Node;


Node * getNewNode(int val)
{
	Node *p = (Node*)malloc(sizeof(Node));
	p->data = val;
	p->next = NULL;  // 新的节点的下一个指向空
	return p;
}

// 有头链表的插入操作 
Node *insert(Node *head, int pos, int val)
{
	Node newhead, *p = &newhead;   
	newhead.next = head;           // 让虚拟头节点的下一节点为head
	// 此时已经构造了一个有头链表
	for (int i = 0; i < pos; i++) p = p->next;   // 先找到待插入位置的前一位
	Node *node = getNewNode(val);
	node->next = p->next;
	p->next = node;
	return newhead.next;    // 虚拟头节点的下一个节点才是要返回的头节点
}


void clear(Node *head)
{
	if (head == NULL) return;
	// 循环遍历链表中每个节点, 当遍历不为空,就一直向后走
	for (Node *p = head, *q; p; p = q)   // p是当前节点
	{
		q = p->next;   // 先让q指向下一个节点
		free(p);       // 再销毁当前节点
	}
	return;
}

void output_linklist(Node *head, int flag = 0)
{
	// 0   1   2
	// 22->33->55
	int n = 0;
	for (Node *p = head; p; p = p->next) n += 1;   // 先求链表的长度n
	// 打印第一行序号
	for (int i = 0; i < n; i++)
	{
		// printf("%3d", i);
		printf(DIGIT_LEN_STR(DL), i);
		printf("  ");    // 对应链表的->两个字符
	}
	printf("\n");

	// 打印第二行链表
	for (Node *p = head; p; p = p->next)
	{
		// printf("%3d", p->data);
		printf(DIGIT_LEN_STR(DL), p->data);
		printf("->");
	}
	printf("\n");
	if (flag == 0) printf("\n\n");
	return; 


}

int find(Node *head, int val)  
{
	// 查找,遍历链表的每个节点
	Node *p = head;  // 当前节点指针
	int n = 0;      // 用来记录输出元素个数
	while (p)
	{
		if (p->data == val){
			output_linklist(head, 1);
			int len = n * (DL + 2) + 1;      // 空字符个数
			for (int i = 0; i < len; i++) printf(" ");   // 输出前面的空格
			printf("^\n");
			for (int i = 0; i < len; i++) printf(" ");   // 输出前面的空格
			printf("|\n");
			return 1;
		}
		n += 1;
		p = p->next;
	}
	return 0;

}



int main()
{
	srand(time(0));
    #define MAX_OP 7
	Node *head = NULL;
	// 测试插入操作
	for (int i = 0; i < MAX_OP; i++)
	{
		int pos = rand() % (i + 1), val = rand() % 100;    // 这里的第一个pos因为是随机数对1取余,永远都是0
		printf("insert %d at %d to linklist\n", val, pos);
		head = insert(head, pos, val);
		output_linklist(head);

	}

	// 测试查找操作
	int val;
	while (scanf_s("%d", &val)){
		if (!find(head, val)) printf("not found\n");
	}
	std::cin.get();
	return 0;
}

链表:循环链表

单向循环链表

单向循环链表:在单向链表的基础上加一个循环结构,循环结构是指最后一个节点指向了第一个节点
注意: 在单向循环链表中的头指针head指向整个链表的最后一个节点
为什么要指向最后一个节点:因为最后一个节点充当着一个实实在在的链表中的节点,也充当着一个虚拟头节点。有了这个虚拟头节点之后,当需要插入节点到链表中时,插入到哪个位置就向后走几步即可
在这里插入图片描述

代码

结构定义
与单向链表的节点定义一样

typedef struct Node{
	int data;
	struct Node *next;
} Node;

构造循环

Node *ConstructLoop(Node *head)   // 构造链表循环
{
	if (head == NULL) return head;
	Node *p = head;
	while (p->next) p = p->next;  // 找到链表的最后一个节点
	p->next = head;   //最后的节点的下一个节点指向头节点
	head = p;         // 头指针指向最后一个节点
	return head;      // 返回头指针
}

删除循环链表
与单向链表的删除一样

void clear(Node *head)        // 删除单向链表
{
	if (head == NULL) return;
	// 循环遍历链表中每个节点, 当遍历不为空,就一直向后走
	for (Node *p = head, *q; p; p = q)   // p是当前节点
	{
		q = p->next;   // 先让q指向下一个节点
		free(p);       // 再销毁当前节点
	}
	return;
}

单向循环链表:插入

如果头指针head指向的不是链表最后一个节点,而是第一个节点,那么在插入元素到index=0的位置时,是不是要先找到0位置节点的前一个节点,那就是链表的最后一个节点,也就是说,为了在0位置插入一个节点,还要先遍历完链表的全部节点才能进行插入操作,所以将头指针head设置为链表最后一个节点是合理。在这里插入图片描述
插入在index=0位置后,不需要修改head指向的节点,保持指向为最后一个节点即可。
在这里插入图片描述
插入到链表的最后一个节点的后面,则需要在插入完成后修改head指向的节点
在这里插入图片描述
在这里插入图片描述

代码

Node *insertLoop(Node *head, int pos, int val)
{
	int n = 1;
	Node *q = head->next;
	while (q != head)  // 记录循环链表的长度
	{
		n += 1;
		q = q->next;
	}
	Node *p = head;                              // 当前指针指向头节点,相当于单向链表的虚拟头节点
	for (int i = 0; i < pos; i++) p = p->next;   // 找到待插入位置的前一位
	Node *node = getNewNode(val);

	// 插入操作
	if (pos < n)
	{
		node->next = p->next;
		p->next = node;
		return head;   // 如果插入的位置不是在最后一个节点之后,返回原头指针
	}
	else
	{
		node->next = p->next;
		p->next = node;
		head = node;          // 否则,头指针指向最后一个节点
		return head;
	}
	      
}

链表:双向链表

双向链表: 除了有指向下一个节点的变量next指针之外,还有指向上一个节点的变量pre指针
第一个节点的pre指针指向空地址
最后一个节点的next指针指向空地址
在这里插入图片描述

代码

结构定义

typedef struct BiNode{
	int data;
	struct BiNode *next;
	struct BiNode *pre;
} BiNode;

构造节点

BiNode *getNewBiNode(int val)
{
	BiNode *p = (BiNode*)malloc(sizeof(BiNode));
	p->data = val;
	p->next = NULL;
	p->pre = NULL;
	return p;

}

删除双向链表
与单向链表的删除一样

void clear(Node *head)        // 删除单向链表
{
	if (head == NULL) return;
	// 循环遍历链表中每个节点, 当遍历不为空,就一直向后走
	for (Node *p = head, *q; p; p = q)   // p是当前节点
	{
		q = p->next;   // 先让q指向下一个节点
		free(p);       // 再销毁当前节点
	}
	return;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/499445.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

复习笔记1

考纲(张友生版本软件架构 考试题型&#xff1a; 10*3单选 5*3简答题 5*3设计图&#xff08;含画图&#xff09; 10*2 论述题 10*2综合题 复习以课件为主&#xff0c;书为辅 第一章 (软件危机) &#xff1f; &#xff1f; 构造模型与实现 掌握软件结构体系核心模型 第二章 软件体…

阿里云Alibaba Cloud Linux镜像系统介绍及常见问题解答FAQ

阿里云服务器操作系统Alibaba Cloud Linux镜像怎么样&#xff1f;可以代替CentOS吗&#xff1f;Alibaba Cloud Linux兼容性如何&#xff1f;有人维护吗&#xff1f;漏洞可以修复吗&#xff1f;Alibaba Cloud Linux完全兼容CentOS&#xff0c;并由阿里云官方免费提供长期维护。 …

Java并发,夺命 60 问

基础 1.并行跟并发有什么区别&#xff1f; 从操作系统的角度来看&#xff0c;线程是CPU分配的最小单位。 并行就是同一时刻&#xff0c;两个线程都在执行。这就要求有两个CPU去分别执行两个线程。 并发就是同一时刻&#xff0c;只有一个执行&#xff0c;但是一个时间段内&am…

linux系统中rpm与Yum软件仓库

rpm的作用&#xff1a; 在没有rpm软件管理之前我们在安装、升级、卸载服务程序时要考虑到其他程序、库的依赖关系&#xff0c;所以在进行安装、校验、卸载、升级等操作时的难度就非常之大。 rpm机制则为就是为了解决这些问题而设计的&#xff0c;rpm有点像windows系统中的控制…

xawtv涉及的vivid系统调用分析

xawtv涉及的vivid系统调用分析 文章目录 xawtv涉及的vivid系统调用分析调用过程分析摄像头驱动程序必需的11个ioctl非必须必须 分析数据的获取过程1.请求分配缓冲区: ioctl(4, VIDIOC_REQBUFS // 请求系统分配缓冲区2.查询映射缓冲区:3.把缓冲区放入队列:4.启动摄像头5.用selec…

Docker-Flannel网络讲解

目录 什么是Flannel Flannel原理 部署 环境准备 安装etcd 安装fannel 在server2上装flannel 测试 什么是Flannel flannel是 CoreOS 团队针对 Kubernetes 设计的一个覆盖网络&#xff08;Overlay Network&#xff09;工具&#xff0c;其目的在于帮助每一个使用 Kuberent…

文心一言 VS chatgpt (15)-- 算法导论3.2 4~5题

四、函数 ⌈ lg ⁡ n ⌉ ! \lceil \lg n \rceil ! ⌈lgn⌉! 多项式有界吗&#xff1f;函数 ⌈ lg ⁡ lg ⁡ n ⌉ ! \lceil \lg \lg n \rceil ! ⌈lglgn⌉! 多项式有界吗&#xff1f; 文心一言&#xff1a; chatgpt&#xff1a; 对于第一个问题&#xff0c;函数 ⌈ lg ⁡ n…

C++类和对象(6)

类和对象 1.在谈构造函数1.1. 构造函数体赋值1.2. 初始化列表1.3. explicit关键字 2. static成员2.1. 概念2.2. 特性 3.友元函数3.2.友元类 4. 内部类5.匿名对象6.拷贝对象时的一些编译器优化7.再次理解类和对象 1.在谈构造函数 1.1. 构造函数体赋值 在创建对象时&#xff0c…

【SPSS】回归分析详细操作教程(附案例实战)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

数据结构入门-顺序表链表

线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。线性表是一种实际中广泛使用多个数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线。…

前后端图片交互的简易方式

前后端图片交互的简易方式 一、交互方式说明二、前后端具体代码实现前端具体代码实现后端具体代码实现效果 测试结果 一、交互方式说明 在项目的实际开发中&#xff0c;难免会遇到前端需要渲染数据库中保存的图片&#xff0c;那咱知道图片也属于一种文件&#xff0c;不好保存到…

maven依赖jar包时版本冲突的解决

1、第一声明优先原则 在pom.xml配置文件中&#xff0c;如果有两个名称相同版本不同的依赖声明&#xff0c;那么先写的会生效。 所以&#xff0c;先声明自己要用的版本的jar包即可。 所以&#xff0c;添加新依赖时要放在最后边&#xff0c;以防止新依赖替换原有依赖造成版本冲…

Mybatis基础操作XML映射文件

Mybatis基本操作 一、环境准备 数据库表和springboot工程在课程资料中都有提供 注意&#xff0c;entrydate是用的jdk1.8中的LocalDate类型&#xff0c;createTime用的是jdk1.8中的LocalDateTime类型 二、删除 Mybatis中提供了一种参数占位符 #{id} empMapper.java package…

Leetcode461. 汉明距离

Every day a leetcode 题目来源&#xff1a;461. 汉明距离 解法1&#xff1a;模拟 先将x和y转为为对应二进制的字符串&#xff0c;再遍历两个字符串进行比较。 代码&#xff1a; /** lc appleetcode.cn id461 langcpp** [461] 汉明距离*/// lc codestart class Solution {…

HTML的两个实战项目

文章目录 HTML的两个实战项目1. 个人简历1. 1 快速生成模板1.2 根据简历格式进行预设计1.3 开始创作吧1.3.1 基本信息1.3.2 教育背景1.3.3 专业技能1.3.4 我的项目1.3.5 自我评价 2. 输入简历信息页面设计2.1 设计大概框架2.2 开始创作吧2.2.1 输入姓名2.2.2 上传照片2.2.3 输入…

Axure教程——用中继器制作动态柱状图

今天作者就教大家在Axure里面如何用中继器做一个可以动态的柱状图。 制作完成之应具备以下交互效果&#xff1a; 1.在中继器表格中填写具体数据和坐标轴后&#xff0c;自动生成对应的柱状图 2.鼠标移动到每项&#xff0c;显示其数据 预览地址&#xff1a;https://tj4v11.axshar…

node笔记_读文件(异步读取、流式读取)

文章目录 ⭐前言⭐ 读取文件异步读 readFile读取txt 流式读 createReadStream读取视频 ⭐ 结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本期分享node读取文件。 往期文章 node_windows环境变量配置 node_npm发布包 linux_配置node node_nvm安装配置 node笔记_http服务…

2023/05/02~07 刷题记录

A - AABCC 题义&#xff1a; 题解&#xff1a; 读完题目可以想到直接暴力&#xff0c;但是肯定超时别想了。 因为 a b c 都是素数&#xff0c;所以我们可以先求出所有的素数 进行减少循环的次数&#xff0c;然后遍历。在遍历过程中&#xff0c;我们也要去进行剪枝 &#xff0c;…

10_Uboot启动流程_2

目录 _main函数详解 board_init_f函数详解 relocate_code函数详解 relocate_vectors函数详解 board_init_r 函数详解 _main函数详解 在上一章得知会执行_main函数_main函数定义在文件arch/arm/lib/crt0.S 中,函数内容如下: 第76行,设置sp指针为CONFIG_SYS_INIT_SP_ADDR,也…

美团外卖红包优惠券:美团外卖节红包或美团外卖天天神券怎么领取使用?

什么是美团外卖节红包或美团外卖天天神券&#xff1f; 美团外卖节红包、美团外卖天天神券都可以称为美团外卖红包优惠券。使用美团外卖节红包、美团外卖天天神券&#xff0c;点餐可以享受优惠。且美团外卖节红包、美团外卖天天神券每天都可以免费领取。美团会员红包不能与美团…