【STL】-- 知识总结

news2024/11/17 12:51:09

目录

STL六大组件介绍

容器

序列式容器

vector

list

知识点考察

关联式容器

map/set

set介绍

set常用接口

map介绍

map常用接口

底层结构:红黑树

unordered_map/set

unordered_map/set介绍

底层结构:哈希表

知识考察

适配器

stack

queue

priority_queue

迭代器

什么是迭代器

迭代器的定义

迭代器失效

迭代器分类


STL六大组件介绍

从使用的角度来看,重点关注容器、算法和迭代器三个组件:

在使用C++进行程序编写的过程中,容器的使用必不可少,如用vector/list/map等来进行数据的存储。算法可以非常便捷的对容器进行操作,比如用sort对vector中的数据排序,使用find在map中查找元素等等。在通过算法操作容器的时候,不得不提到迭代器,它就像是容器和算法间的粘合剂:

迭代器的存在,首先封装隐藏了底层的实现细节。其次,为用户提供了统一的方式去访问容器,极大的降低了使用的成本。

从底层的角度,分析各个组件的功能及联系:

容器:各种数据结构,如: vector,list,set,map用来存放数据。

算法:各种常用算法如sort,swap,reverse,find等。

迭代器:扮演容器与算法之间的胶合剂。从实现角度来看,迭代器将operator*, operator->, operator++, operator--等相关操作进行重载的类。所有STL容器都附带有自己专属的迭代器,用户可以用统一的方式对容器进行访问。

仿函数:实现了operator(),这个类能够像函数一样调用,函数指针可视为狭义的仿函数。可作为算法的某种策略,例如改变sort排序的比较规则,map/set的key比较大小的规则。

配接器:用来修饰容器、仿函数、迭代器接口。如:stack,queue,主要体现了复用。

配置器:负责空间配置与管理,从实现角度来看,配置器实现了动态空间配置,空间管理,空间释放。例如:容器需要频繁的申请和释放小块的内存,这种情况下可以使用空间配置器,提高效率。

容器

序列式容器

vector

介绍:vector是表示可变大小数组的序列式容器,采用连续存储空间来存储元素,支持下标的随机访问,它的大小是可以动态改变的。vector在访问元素、尾插和尾删的场景下相对高效。

如上图所示,vector底层设计通过三个迭代器的指针分别记录数据块的起始位置,末尾有效数据和存储容量的末尾位置。vector的迭代器是原生的指针。

vector常用接口:

push_back:尾插

pop_back:尾删

operator[]:[]重载,使vector可以向数组一样访问。

rsize:改变vector的size,在开辟空间的同时还会初始化。

resrve:改变vector的capacity。

list

list的底层结构是双向链表,该容器可以前后双向迭代。list在任意位置插入和删除元素的执行效率更好。

如上图所示,list_node的结构分为三个部分,分别是指向下一个节点的指针Next,执行前一个节点的指针Prev和存储数据的Val。

常用接口:

push_front/pop_front:头插、头删。

push_back/pop_back:尾插、尾删。

insert/erase:在pos位置插入值为val的元素,删除pos位置的元素。

知识点考察

vector和list的区别?

1.底层结构:vector采用连续的空间对数据进行存储(动态顺序表)。list物理结构不连续(带头节点的双向循环链表)。

2.随机访问:vector支持随机访问,访问某个元素的效率是O(1)。list不支持随机访问,访问某个元素的效率是O(n)。

3.迭代器:vector迭代器是原生的指针,list对原生态指针进行了封装。

4.使用场景:vector适合需要高效存储,支持随机访问,不关心插入删除效率的场景(中间插入要挪动数据,效率太低)。而list更适合大量的插入和删除操作,不关心随机访问的场景。

vector如何扩容?

当指向最后一个有效数据位置的迭代器和容量末尾的迭代器重合的时候,代表容器已满,需要进行扩容,在vs下按照1.5倍扩容,g++下按照2倍扩容。但这仅供参考,具体增长多少是根据具体的需求定义的,vs下是PJ版STL,g++是SGI版STL。主要原因就是,扩大了空间浪费,扩小了不够用频繁扩容,所以没有固定的标准说一定扩多少。

resize和reserve有什么区别?

resize在开辟空间的同时还会初始化,改变size的大小。reserve只负责开辟空间。

关联式容器

map/set

set介绍

1. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放
value,但在底层实际存放的是由<value, value>构成的键值对。                                                    2. set中插入元素时,只需要插入value即可,不需要构造键值对。
3. set中的元素不可以重复(因此可以使用set进行去重)。
4. 使用set的迭代器遍历set中的元素,可以得到有序序列。
5. set中的元素默认按照小于来比较。
6. set中查找某个元素,时间复杂度为:$log_2 n$。
7. set中的元素不允许修改,修改方式是先删除在插入新的元素,直接修改会破坏set的有序性。
8. set中的底层使用二叉搜索树(红黑树)来实现。

set常用接口

empty:检测set是否为空。

size::返回set中有效元素的个数。

insert:向set中插入元素x。

erase:删除set中pos位置上的元素。

find:返回set中值为x的元素的个数。

map介绍

1. map中的的元素是键值对
2. map中的key是唯一的,并且不能修改
3. 默认按照小于的方式对key进行比较。
4. map中的元素如果用迭代器去遍历,可以得到一个有序的序列
5. map的底层为平衡搜索树(红黑树),查找效率比较高$O(log_2 N)$
6. 支持[]操作符,operator[]中实际进行插入查找,返回值是key对应的value。

map常用接口

operator[]:map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。

empty:检测set是否为空。

size::返回set中有效元素的个数。

insert:向set中插入元素x。

erase:删除set中pos位置上的元素。

find:返回set中值为x的元素的个数。

底层结构:红黑树

在介绍红黑树之前先介绍一下AVl树:

由于在极端的情况下,二叉搜索树可能会退化成单边树,此时查找效率就会退化成O(N)。AVL树的出现解决了上述问题,当新节点插入到AVL树中后,控制每个节点左右子树的高度差的绝对值不超过1。AVL树是高度平衡的二叉搜索树,搜索数据的时间复杂度为O(log_2 n)。

template<class K,class V>
class AVLTreeNode
{
public:
	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;
	pair<K, V> _data;
	int _bf;
	AVLTreeNode(const pair<K,V>& kv)
		:_left(nullptr), _right(nullptr)
		, _parent(nullptr), _bf(0),_data(kv)
	{}
};

AVL树的插入可以简单的分为两步,首先是按照二叉搜索的方式插入新节点,其次就是通过平衡因子调整树的平衡。下面重点关注什么情况下需要调整,如何进行调整。

节点pCur(新插入的节点)插入后,pParent(新节点的父节点)的平衡因子一定需要调整,在插入之前,pParent的平衡因子分为三种情况:-1,0, 1, 分以下两种情况:
1. 如果pCur插入到pParent的左侧,只需给pParent的平衡因子-1。
2. 如果pCur插入到pParent的右侧,只需给pParent的平衡因子+1。
此时:pParent的平衡因子可能有三种情况:0,正负1, 正负2
1. 如果pParent的平衡因子为0,说明插入之前pParent的平衡因子为正负1,插入后被调整
成0,此时满足AVL树的性质,插入成功
2. 如果pParent的平衡因子为正负1,说明插入前pParent的平衡因子一定为0,插入后被更
新成正负1,此时以pParent为根的树的高度增加,需要继续向上更新调整。
3. 如果pParent的平衡因子为正负2,则pParent的平衡因子违反平衡树的性质,需要对其进
行旋转处理。

AVl树的旋转可以大致的分为如下几种情况:

 以左单旋为例:

新节点插入较高左子树的右侧,左边低右边高,以40为根的二叉树不平衡。大致过程如下:
1.subRL变成parent的右孩子。

2.subR变成根节点。

3.parent变成subR的左孩子。

代码实现的过程中要注意几个点:旋转完后subR是该子树的根节点,它可能是整颗树的根节点也可能只是一颗子树。还要注意subRL是否为空。

void RotateL(Node* parent)
	{
		Node* SubR = parent->_right;
		Node* SubRL = SubR->_left;
		
		//cur的左孩子给parent的右
		parent->_right = SubRL;
		if (SubRL) SubRL->_parent = parent;
		//cur变成父节点,parent变成cur的左
		Node* ppNode = parent->_parent;

		parent->_parent = SubR;
		SubR->_left = parent;
		if (ppNode == nullptr)
		{
			_root = SubR;
			_root->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = SubR;
			}
			else if (ppNode->_right == parent)
			{
				ppNode->_right = SubR;
			}
			SubR->_parent = ppNode;
		}
		parent->_bf = SubR->_bf = 0;
	}

AVL树分析:

AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这
样可以保证查询时高效的时间复杂度,即log_2 N)。

但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但结构经常修改,就不太适合。

红黑树介绍:

红黑树也是一种二叉搜索树,它的结构是接近平衡的。每个节点要么是红色,要么是黑色。通过对任何一条从根到叶子节点的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,近似平衡,在极端场景下,搜索效率会变成2*log_2 N。

红黑树的性质:

1. 每个结点不是红色就是黑色。
2. 根节点是黑色的。
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的。
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点。
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点。

 红黑树的插入操作:默认新增节点为红色

1.按照二叉搜索树的方式插入新节点

2.检测新节点插入后,红黑树性质是否遭到破坏

情况1:c为红,p为红,g为黑,u存在且为红。

新节点插入后有连续的红节点出现,处理方法:将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。

情况2:c为红,p为红,g为黑,u不存在或者存在且为黑(c/p/g成直线)。

 p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,
p为g的右孩子,cur为p的右孩子,则进行左单旋转
p、g变色--p变黑,g变红

情况3:c为红,p为红,g为黑,u不存在或者存在且为黑(c/p/g成一条折线)。

 p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,
p为g的右孩子,cur为p的左孩子,则针对p做右单旋转
则转换成了情况2,按照情况2进行处理。
红黑树和AVL树对比:
查询效率方面,极端场景下AVL -- log_2 N,红黑树2*log_2 N,AVl树略优。但是由于红黑树不追追求绝对的平衡,降低了旋转次数,在经常需要增删的结构中红黑树更优,实际应用中红黑树更多。

unordered_map/set

unordered_map/set介绍

unordered系列的关联式容器在使用方式上和map/set基本相似,只是底层结构不同。上文提到的红黑树效率在查询时效率可以达到logN,当树中节点非常多的时候,查询效率也不理想。unordered系列容器的底层结构使用的是哈希表,查询效率O(1)。

底层结构:哈希表

构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立
一一映射的关系,那么在查找时通过该函数可以很快找到该元素。

开散列(哈希桶)

开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地
址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链
接起来,各链表的头结点存储在哈希表中。

哈希冲突:不同的关键字通过相同的哈希函数计算出相同的哈希地址,该中现象被称为哈希冲突或哈希碰撞。

哈希函数:哈希函数设计的越精妙,产生哈希冲突的可能性就越低,但是无法避免哈希冲突。哈希函数设计原则要注意一下几点:

1.哈希函数的定义域必须包括需要存储的全部关键码,而如果散列表允许有m个地址时,其值
域必须在0到m-1之间。
2.哈希函数计算出来的地址能均匀分布在整个空间中。
3.哈希函数应该比较简单。

直接定址法:取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B。
优点:简单、均。
缺点:需要事先知道关键字的分布情况。
使用场景:适合查找比较小且连续的情况。

除留余数法:设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函数:Hash(key) = key% p(p<=m),将关键码转换成哈希地址。

开散列增容:桶的个数是一定的,随着元素的不断插入,每个桶中元素的个数不断增多,极端情况下,可能会导致一个桶中链表节点非常多,会影响的哈希表的性能,因此在一定条件下需要对哈希
表进行增容,那该条件怎么确认呢?开散列最好的情况是:每个哈希桶中刚好挂一个节点,再继续插入元素时,每一次都会发生哈希冲突,因此,在元素个数刚好等于桶的个数时,可以给哈希表增容。

开散列与闭散列比较:应用链地址法处理溢出,需要增设链接指针,似乎增加了存储开销。事实上:由于开地址法必须保持大量的空闲空间以确保搜索效率,如二次探查法要求装载因子a <=
0.7,而表项所占空间又比指针大的多,所以使用链地址法反而比开地址法节省存储空间

知识考察

map和set之间的区别?

1.map存储的是键值对<k,v>,set中只放value,底层存的是<v,v>的键值对。

2.map重载了[],可以通过operator[]进行插入查找,返回值是key对应value的引用,可以对value修改。set的修改方式是先删除这个元素在进行插入。

map和unordered_map之间的区别?
1.底层结构不同,map底层是红黑树,unordered_map的底层是哈希表。

2.unordered_map使用迭代器遍历,得到的数据是无序的,map遍历得到的是有序的序列。

3.一般情况下,unordered_map的查询效率比map更快。

4.从内存存角度来说hash因为底层维护了哈希表的存在,内存消耗远大于红黑树,但是因为哈希表增删查改时的直接映射,使其增删查效率来说可以做到平均O(1),对数据修改较多且不考虑内存问题的场景可以优先考虑hash。

5.红黑树是基于搜索树设计的,具有天然的有序性,hash因为存在哈希冲突所以不能保证存储的数据有序,那么对数据存储存在有序性需求的优先使用红黑树。

一个类型想要做map的key,有什么要求吗?

1.能取模或者配一个仿函数能够转换成整型取模。

2.支持 == 比较。

适配器

stack

stack是一种容器适配器,只能从容器的一端进行元素的插入与提取,后进先出。stack的底层容器可以是任何标准的容器类模板或者一些特定的容器类,这些容器类应该支持如下操作:(empty,back,push_back,pop_back)

常用接口

empty:检测stack是否为空。

size:返回stack中的元素个数。

top:返回栈顶元素的引用。

push:将元素val压入stack中。

pop:将stack中尾部的元素弹出。

queue

队列是一种元素适配器,容器一端插入元素,另一端提取元素,先进先出。queue其底层容器类可以是标准容器类模板之一,也可以是专门设计的容器类,该底层容器类至少要支持如下操作:

empty、size、front、back、push_back、pop_front。

 常用接口使用:
empty:检测队列是否为空。

size:返回队列中有效元素个数。

front:返回队头元素的引用。

back:返回队尾元素的引用。

push: 在队尾将元素入队列。

pop:队头元素出队列。

priority_queue

优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆。如果想要创建小堆,通过greater改变比较方式。
常用接口:

empty:判断优先级队列是否为空。

top:返回堆顶元素。

push:向优先级队列中插入元素。

pop:删除堆顶元素。

迭代器

什么是迭代器

行为像指针一样的类型。可能是指针,也可能是被封装成的指针,让使用者不用关心容器的底层实现细节,可以用统一的方式轻松访问容器。

迭代器的定义

1.构造函数。

2.具有指针类似的操作,重载operator*和operator->。

3.迭代器要能够比较,重载operator!= 和operator==。

4.迭代器要能够移动,重载operator++()/operator++(int),根据容器的底层数据结构决定是否要支持前置--和后置--。

迭代器失效

1.迭代器指向的位置是不可知的,野指针。

如:vector扩容,导致的野指针问题。list/map删除(erase)节点,导致的野指针问题。

 以vector扩容为例

2.迭代器指向的位置已经不在是原来的位置,意义变了。

如:vector不扩容,但是挪动数据(插入或者删除),使迭代器指向的位置已经不是原来的位置。

3.迭代器失效解决办法

在使用前对迭代器重新赋值。

迭代器分类

1.单向迭代器:如forward_list、unordered_map/set。

2.双向迭代器:如map/set、list。

3.随机迭代器:如vector、string。

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

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

相关文章

【ESP系列】ESP01S官方MQTT案例实验

前言 偶然发现安信可官网有ESP01S和STM32连接TCP和MQTT的案例。弄了一两天&#xff0c;把我使用的流程在这里记录下。MQTT的固件一定要烧录进去&#xff0c;默认固件是没有MQTT相关的AT指令的。 环境 Keli5&#xff0c;STM32F103C8T6 官方Keil工程链接&#xff1a;ESP8266的S…

虫情测报灯

在农业生产过程中&#xff0c;农作物的虫害问题永远都是放在首位的。随着现代生活科技的发展和社会进步&#xff0c;人们对物质也有了新的要求。伴随农作物品种的增加&#xff0c;农药和化肥的使用也在导致农业虫害问题日益加剧&#xff0c;在这种不良的耕作状态下&#xff0c;…

JSP介绍

目录 获取表单提交的数据 请求对象 request response 在请求中存取属性 转发与重定向 session cookie pageContext对象 jsp 动作标签 JSP内置对象是什么: 在jsp开发中会频繁使用到一些对象,如ServletContext HttpSession PageContext等.如果每次我们在jsp页面中需要使…

JavaWeb 速通Listener

目录 一、Listener快速入门 1.Listener简介 : 2.Java事件处理机制 : 二、ServletContextListener 1.作用 : 2.相关方法 : 3.应用实例 : 三、ServletContextAttributeListener 1.作用 : 2.相关方法 : 3.应用实例 : 四、HttpSessionListener 1.作用 : 2.相关方法 :…

KeilMDk软仿真设置_STM32F03C8

1、KeilMDK软仿真的价值 (1)在没有硬件的情况下进行程序的编写调试。 (2)避免频繁的下载程序&#xff0c;延长单片机Flash寿命。 2、软仿真配置。 (1)打开Keil工程。 (2)点击“Options for Target ***”&#xff0c;如下图所示。 (3)点击“Debug”。 (4)进行如下配置。 U…

无涯教程-TensorFlow - XOR实现

在本章中&#xff0c;无涯教程将学习使用TensorFlow的XOR实现&#xff0c;在TensorFlow中开始XOR实施之前&#xff0c;看一下XOR表值。这将帮助了解加密和解密过程。 A B A XOR B 0 0 0 0 1 1 1 0 1 1 1 0 XOR密码加密方法基本上用于加密&#xff0c;即通过生成与适当密钥匹配…

科技大厂GenAI最新动态一览!AI创意字终极全攻略;一文入门LLM应用开发框架LangChain;Llama初学者指南 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 使用浏览器插件 immersive translate&#xff0c;将外语书翻译成双语对照版 immersive translate 是一款非常好用的浏览器翻译插件。今…

idea2023 springboot2.7.5+mybatisplus3.5.2+jsp 初学单表增删改查

创建项目 修改pom.xml 为2.7.5 引入mybatisplus 2.1 修改pom.xml <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><!--mysq…

XSS攻击是什么?它有哪些类型?

xss攻击是什么&#xff1f; XSS全称是Cross Site Scripting即跨站脚本&#xff0c;当目标网站目标用户浏览器渲染HTML文档的过程中&#xff0c;出现了不被预期的脚本指令并执行时&#xff0c;XSS就发生了。 作为一种HTML注入攻击&#xff0c;XSS攻击的核心思想就是在HTML页面中…

git错误记录

露id没有影响&#xff0c;搞得微软不知道我ip一样 git fatal: 拒绝合并无关的历史的错误解决(亲测有效)

使用Pandas处理Excel文件

Excel工作表是非常本能和用户友好的&#xff0c;这使得它们非常适合操作大型数据集&#xff0c;即使是技术人员也不例外。如果您正在寻找学习使用Python在Excel文件中操作和自动化内容的地方&#xff0c;请不要再找了。你来对地方了。 在本文中&#xff0c;您将学习如何使用Pan…

ansible(1)-- 部署ansible连接被控端

目录 一、部署ansible 1.1 安装 1.2 测试连接 192.168.136.55 ansible 192.168.136.56被控端 一、部署ansible 1.1 安装 zabbix-s只是主机名&#xff0c;不用在意&#xff0c;更好该主机也安装了zabbix&#xff0c;不好更改。 下载阿里云epel源 #安装阿里云的epel源&#…

33.Netty源码之读写数据

highlight: arduino-light 写数据 写数据的三种方式 md 快递场景(包裹) Netty 写数据(数据) 揽收到仓库 write&#xff1a;写到一个 buffer 从仓库发货 flush: 把 buffer 里的数据发送出去 揽收到仓库并立马发货 (加急件) writeAndFlush&#xff1a;写到 buffer&#xff0c;立马…

Android5:活动生命周期

创建项目Stopwatch activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayoutxmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android:layout_w…

产品经理必知必会0.2

Q1:产品经理需要具备的能力&#xff1f; A:硬实力&#xff1a;产品设计、需求分析、竞品分析、数据分析、撰写文档 软实力&#xff1a;沟通能力、学习能力、用户思维、主动性、好奇心、同理心、责任心、抗压能力、目标导向.... 扩展能力&#xff1a;商业思维、市场敏感度... Q…

3D与沉浸式技术,如何助力企业数字化转型?

说起3D&#xff0c;估计许多读者朋友会在第一时间想起《阿凡达》系列和《侏罗纪公园》系列电影大作。每一帧细节纤毫毕现的逼真画面&#xff0c;让观众几乎分不清虚拟与现实&#xff0c;完全沉浸在导演打造的视觉盛宴中。 事实上&#xff0c;除了大家所熟知的3D影视动画之外&am…

ps丢失d3dcompiler_47.dll怎么办,启动无反应,分享三个解决方法

d3dcompiler_47.dll64位是windows系统中重要的dll文件&#xff0c;缺少了它可能会引起部分软件或者游戏不能运行。 如果系统出现“找不到d3dcompiler_47.dll”或“d3dcompiler_47.dll丢失”等错误信息&#xff0c;那么我们就该着手修复它。 先带了解一下d3dcompiler_47.dll是什…

【MATLAB基础绘图第16棒】绘制热图(Heatmap)

热图&#xff08;Heatmap&#xff09; 热图的主要作用是直观展示重点研究对象的差异情况&#xff0c;多用于经济学与工学差异性分析之中。 heatmap函数创建热图 语法 hheatmap(tbl,xvar,yvar) hheatmap(tbl,xvar,yvar,ColorVariable,cvar) hheatmap(cdata) hheatmap(xvalue…

开发板启动过程

开发板启动过程 开发板上电后首先运行SOC内部iROM中固化的代码(BL0)&#xff0c;这段代码先对基本的软硬件环境(时钟等…)进行初始化&#xff0c;然后再检测拨码开关位置获取启动方式&#xff0c;然后再将对应存储器中的uboot搬移到内存&#xff0c;然后跳转到uboot运行 uboot…

《TCP IP网络编程》第二十四章

第 24 章 制作 HTTP 服务器端 24.1 HTTP 概要 本章将编写 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;服务器端&#xff0c;即 Web 服务器端。 理解 Web 服务器端&#xff1a; web服务器端就是要基于 HTTP 协议&#xff0c;将网页对…