C++STL剖析(四)—— stack和queue的概念和使用

news2024/11/27 1:26:14

文章目录

  • 1. stack的介绍
  • 2. stack的构造
  • 3. stack的使用
    • 🍑 push
    • 🍑 top
    • 🍑 pop
    • 🍑 empty
    • 🍑 size
    • 🍑 swap
    • 🍑 emplace
  • 4. queue的介绍
  • 5. queue的构造
  • 6. queue的使用
    • 🍑 push
    • 🍑 size
    • 🍑 front
    • 🍑 back
    • 🍑 pop
    • 🍑 empty
    • 🍑 swap
    • 🍑 emplace
  • 7. 容器适配器
    • 🍑 什么是适配器
    • 🍑 stack和queue的底层结构
    • 🍑 deque的原理介绍
    • 🍑 deque的缺陷
    • 🍑 选择deque的原因
  • 8. 模拟实现「stack」和「queue」
    • 🍑 stack的模拟实现
    • 🍑 queue的模拟实现
  • 9. 总结


1. stack的介绍

「stack」是一种 容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。

在这里插入图片描述

可以看到「stack」是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。

在这里插入图片描述

也就是说, 「stack」的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:

  • empty:判空操作
  • back:获取尾部元素操作
  • push_back:尾部插入元素操作
  • pop_back:尾部删除元素操作

标准容器 vector、deque、list 均符合上面这些需求,默认情况下,如果没有为「stack」指定特定的底层容器,默认情况下使用 deque。

2. stack的构造

它的构造方式如下:

在这里插入图片描述

(1)使用默认的适配器构造一个空栈

stack<int> st1;

(2)使用其他的容器适配器构造一个空栈

stack<int, vector<int>> st2;
stack<int, list<int>> st3;

3. stack的使用

相对于前面学习的容器,「Stack」的接口更简单也更少,基本的使用函数如下。

🍑 push

在堆栈顶部插入一个新元素,位于其当前顶部元素之上。

在这里插入图片描述

代码示例

void test_stack()
{
	stack<int> st;

	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);
}

🍑 top

返回堆栈顶部元素的引用。

在这里插入图片描述

代码示例

void test_stack()
{
	stack<int> st;

	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);

	cout << st.top() << endl;
}

运行结果

在这里插入图片描述

🍑 pop

删除堆栈顶部的元素,有效地将其大小减小 1。

在这里插入图片描述

代码示例

void test_stack()
{
	stack<int> st;

	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);

	cout << st.top() << endl;

	st.pop();

	cout << st.top() << endl;
}

可以看到,最开始栈顶元素是 5,删除以后,就变成了 4

在这里插入图片描述

🍑 empty

返回堆栈是否为空,即它的大小是否为 0。

在这里插入图片描述

因为栈是不支持遍历的,所以这个接口可以用来实现栈的遍历。

void test_stack()
{
	stack<int> st;

	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);

	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}

}

运行结果

在这里插入图片描述

🍑 size

返回栈中元素的数量。

在这里插入图片描述

代码示例

void test_stack()
{
	stack<int> st;

	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);
	st.push(6);
	st.push(7);
	st.push(8);
	st.push(9);
	st.push(10);

	cout << st.size() << endl;
}

运行结果

在这里插入图片描述

🍑 swap

将容器适配器(*this)的内容与 x 的内容交换。

其实就是交换两个栈的元素数据。

在这里插入图片描述

代码示例

void test_stack()
{
	stack<int> st1;
	st1.push(1);
	st1.push(2);
	st1.push(3);
	st1.push(4);
	st1.push(5);

	stack<int> st2;
	st2.push(6);
	st2.push(7);
	st2.push(8);
	st2.push(9);
	st2.push(10);

	st1.swap(st2);

	while (!st1.empty()) {
		cout << st1.top() << " ";
		st1.pop();
	}

	while (!st2.empty()) {
		cout << st2.top() << " ";
		st2.pop();
	}
}

运行结果

在这里插入图片描述

🍑 emplace

在栈顶部添加一个新元素,位于其当前顶部元素之上。

在适当的位置构造这个新元素,并将 args 作为其构造函数的参数传递。

在这里插入图片描述

代码示例

void test_stack()
{
	stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);

	st.emplace(10);

	while (!st.empty()) {
		cout << st.top() << " ";
		st.pop();
	}
}

可以看到这个函数确实没啥用处…

在这里插入图片描述

4. queue的介绍

「队列 Queue」是一种容器适配器,专门用于在 FIFO 上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。

在这里插入图片描述

可以看到「queue」也是作为容器适配器实现的,容器适配器即将特定容器类封装作为其底层容器类,「queue」提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。

在这里插入图片描述

底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

  • empty:检测队列是否为空
  • size:返回队列中有效元素的个数
  • front:返回队头元素的引用
  • back:返回队尾元素的引用
  • push_back:在队列尾部入队列
  • pop_front:在队列头部出队列

标准容器类 deque 和 list 满足了这些要求。默认情况下,如果没有为 queue 实例化指定容器类,则使用标准容器 deque。

5. queue的构造

它的构造方式如下:

在这里插入图片描述

(1)使用默认的适配器构造一个空栈

queue<int> q1;

(2)使用其他的容器适配器构造一个空栈

queue<int, vector<int>> q2;
queue<int, list<int>> q2;

6. queue的使用

相对于前面学习的容器,「queue」的接口更简单也更少,基本的使用函数如下。

🍑 push

在队列的末尾插入一个新元素,位于当前最后一个元素之后。

在这里插入图片描述

代码示例

void test_queue()
{
	queue<int> q;

	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);
}

🍑 size

返回队列中元素的数量。

在这里插入图片描述

代码示例

void test_queue()
{
	queue<int> q;

	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);

	cout << q.size() << endl;
}

运行结果

在这里插入图片描述

🍑 front

返回对队列中下一个元素的引用。

也就是获取队头的元素。

在这里插入图片描述

代码示例

void test_queue()
{
	queue<int> q;

	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);

	cout << q.front() << endl;
}

运行结果

在这里插入图片描述

🍑 back

返回对队列中最后一个元素的引用。

也就是获取队尾元素。

在这里插入图片描述

代码示例

void test_queue()
{
	queue<int> q;

	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);

	cout << q.back() << endl;
}

运行结果

在这里插入图片描述

🍑 pop

删除队列中的下一个元素,有效地将其大小减少 1。

也就是删除队头元素

在这里插入图片描述

代码示例

void test_queue()
{
	queue<int> q;

	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);

	q.pop(); // 删除队头元素
	
	cout << q.size() << endl;
	cout << q.front() << endl;
}

运行结果

在这里插入图片描述

🍑 empty

返回队列是否为空,即队列大小是否为 0。

在这里插入图片描述

因为队列是先进先出,不支持遍历的,所以这个接口可以用来实现队列的遍历。

void test_queue()
{
	queue<int> q;

	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);
	q.push(6);

	while (!q.empty()) {
		cout << q.front() << " ";
		q.pop();
	}

}

运行结果

在这里插入图片描述

🍑 swap

将容器适配器(*this)的内容与 x 的内容交换。

其实就是交换两个队列中的元素数据。

在这里插入图片描述

代码示例

void test_queue()
{
	queue<int> q1;
	q1.push(1);
	q1.push(2);
	q1.push(3);
	q1.push(4);
	q1.push(5);
	q1.push(6);

	queue<int> q2;
	q2.push(8);
	q2.push(9);
	q2.push(10);

	q1.swap(q2);

	while (!q1.empty()) {
		cout << q1.front() << " ";
		q1.pop();
	}

	while (!q2.empty()) {
		cout << q2.front() << " ";
		q2.pop();
	}
}

运行结果

在这里插入图片描述

🍑 emplace

在队列的末尾添加一个新元素,位于当前最后一个元素之后。

在适当的位置构造这个新元素,并将 args 作为其构造函数的参数传递。

在这里插入图片描述

代码示例

void test_queue()
{
	queue<int> q1;
	q1.push(1);
	q1.push(2);
	q1.push(3);
	q1.push(4);
	q1.push(5);
	q1.push(6);

	while (!q1.empty()) {
		cout << q1.front() << " ";
		q1.pop();
	}

	q1.emplace(100);

	while (!q1.empty()) {
		cout << q1.front() << " ";
		q1.pop();
	}
}

这个接口和 stack 一样,没太大用处…

在这里插入图片描述

7. 容器适配器

🍑 什么是适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

在这里插入图片描述

🍑 stack和queue的底层结构

虽然「stack」和「queue」中也可以存放元素,但在 STL 中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为「stack」和「queue」只是对其他容器的接口进行了包装,STL 中「queue」和「queue」默认使用「deque」比如:

在这里插入图片描述

注意:容器支持迭代器,但是容器适配器不支持迭代器,因为栈和队列这种数据结构不能随便去遍历,不然会导致性质不易维护。

🍑 deque的原理介绍

「双端队列 deque」:是一种双开口的 “连续” 空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为 O ( 1 ) O(1) O(1),与「vector」比较,头插效率高,不需要搬移元素;与「list」比较,空间利用率比较高。

在这里插入图片描述

「deque」并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际「deque」类似于一个动态的二维数组,其底层结构如下图所示:

在这里插入图片描述

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其 “整体连续” 以及随机访问的假象,落
在了「deque」的迭代器身上,因此「deque」的迭代器设计就比较复杂,如下图所示:

在这里插入图片描述

那「deque」是如何借助其迭代器维护其假想连续的结构呢?

在这里插入图片描述

🍑 deque的缺陷

「vector」的优缺点:

  • 优点:适合尾插尾删,随机访问
  • 缺点:不适合头部或者中部插入删除,效率低,需要挪动数据;扩容有一定性能消耗,还可能存在一定程度的空间浪费。

「list」的优缺点:

  • 优点:任意位置插入删除效率高;按需申请释放空间。
  • 缺点:不支持随机访问;cpu 高速缓存命中低

「deque」就是结合了「vector」和「list」的优缺点而发明的!!!

与「vector」比较,「deque」的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是比「vector」高的。

与「list」比较, 其底层是连续空间,空间利用率比较高,不需要存储额外字段。

但是,「deque」有一个致命缺陷: 不适合遍历!因为在遍历时,「deque」的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑「vector」和「list」。

「deque」的应用并不多,而目前能看到的一个应用就是,STL 用其作为「stack」和「queue」的底层数据结构。

🍑 选择deque的原因

为什么选择「deque」作为「stack」和「queue」的底层默认容器?

「stack」是一种后进先出的特殊线性数据结构,因此只要具有 push_back()pop_back() 操作的线性结构,都可以作为「stack」的底层容器,比如「vector」和「list」都可以;

「queue」是先进先出的特殊线性数据结构,只要具有 push_back()pop_back() 操作的线性结构,都可以作为「queue」的底层容器,比如「list」。

但是 STL 中对「stack」和「queue」默认选择「deque」作为其底层容器,主要是因为:

  • 「stack」和「queue」不需要遍历(因此 stack 和 queue 没有迭代器),只需要在固定的一端或者两端进行操作。
  • 在「stack」中元素增长时,「queue」比「vector」的效率高(扩容时不需要搬移大量数据)
  • 「queue」中的元素增长时,「deque」不仅效率高,而且内存使用率高。

总的来说,就是结合了「deque」的优点,而完美的避开了其缺陷。

8. 模拟实现「stack」和「queue」

🍑 stack的模拟实现

关于 stack 的模拟实现很简单,主要就是针对一些常用的接口,具体代码如下:

namespace edc
{
	template<class T, class Container = deque<T>>
	class Stack
	{
	public:
		// 入栈
		void push(const T& x)
		{
			_con.push_back(x);
		}

		// 出栈
		void pop()
		{
			_con.pop_back();
		}

		// 获取栈顶元素
		T& top()
		{
			return _con.back();
		}

		const T& top() const
		{
			return _con.back();
		}

		//获取栈中有效元素个数
		size_t size() const
		{
			return _con.size();
		}

		//判断栈是否为空
		bool empty() const
		{
			return _con.empty();
		}

		//交换两个栈中的数据
		void swap(Stack<T, Container>& st)
		{
			_con.swap(st._con);
		}
	private:
		Container _con;
	};
	
	// 测试函数
	void test_stack()
	{
		Stack<int> st;
		st.push(1);
		st.push(2);
		st.push(3);
		st.push(4);
		st.push(5);
		st.push(6);

		cout << "栈中元素个数:" << st.size() << endl;

		cout << "出栈顺序:";
		while (!st.empty()) {
			cout << st.top() << " ";
			st.pop();
		}
	}
}

测试结果:

在这里插入图片描述

🍑 queue的模拟实现

关于 queue 的模拟实现也很简单,主要就是针对一些常用的接口,具体代码如下:

namespace edc
{
	template<class T, class Container = deque<T>>
	class Queue
	{
	public:
		// 入队
		void push(const T& x)
		{
			_con.push_back(x);
		}

		// 出队
		void pop()
		{
			_con.pop_front();
		}

		// 获取队头元素
		T& front()
		{
			return _con.front();
		}

		const T& front() const
		{
			return _con.front();
		}

		// 获取队尾元素
		T& back()
		{
			return _con.back();
		}

		const T& back() const
		{
			return _con.back();
		}

		//获取队列中有效元素个数
		size_t size() const
		{
			return _con.size();
		}

		//判断队列是否为空
		bool empty() const
		{
			return _con.empty();
		}

		//交换两个栈中的数据
		void swap(Queue<T, Container>& q)
		{
			_con.swap(q._con);
		}
	private:
		Container _con;
	};

	// 测试函数
	void test_queue()
	{
		Queue<int> q;
		q.push(1);
		q.push(2);
		q.push(3);
		q.push(4);
		q.push(5);
		q.push(6);
		q.push(7);

		cout << "队列中元素个数:" << q.size() << endl;

		cout << "出队顺序:";
		while (!q.empty()) {
			cout << q.front() << " ";
			q.pop();
		}
	}
}

测试结果:

在这里插入图片描述

9. 总结

对于栈和队列,我相信只要数据结构的基础还不错,那么本篇文章的接口函数肯定是手到擒来!

最后我们再看一下栈和队列在实际生活中的应用吧。

栈典型应用:

  • 浏览器中的后退与前进、软件中的撤销与反撤销。 每当我们打开新的网页,浏览器就讲上一个网页执行入栈,这样我们就可以通过「后退」操作来回到上一页面,后退操作实际上是在执行出栈。如果要同时支持后退和前进,那么则需要两个栈来配合实现。
  • 程序内存管理。 每当调用函数时,系统就会在栈顶添加一个栈帧,用来记录函数的上下文信息。在递归函数中,向下递推会不断执行入栈,向上回溯阶段时出栈。

队列典型应用:

  • 淘宝订单。 购物者下单后,订单就被加入到队列之中,随后系统再根据顺序依次处理队列中的订单。在双十一时,在短时间内会产生海量的订单,如何处理「高并发」则是工程师们需要重点思考的问题。
  • 各种待办事项。 例如打印机的任务队列、餐厅的出餐队列等等。

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

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

相关文章

面试官:String、StringBuffer、StringBuilder有什么区别?

回答思路&#xff1a; 阐述String概念理解 存在问题和设计考量 总结体现的两个特性 StringBuilder/StringBuffer相同点和不同点 三者使用场景总结 回答总结&#xff1a; String是Java中非常常见且基础的类&#xff0c;用于字符串的构造和管理&#xff0c;它是Immutable类的经典…

SpringCloud之断路器聚合监控

一、Hystrix Turbine简介 看单个的Hystrix Dashboard的数据并没有什么多大的价值&#xff0c;要想看这个系统的Hystrix Dashboard数据就需要用到Hystrix Turbine。Hystrix Turbine将每个服务Hystrix Dashboard数据进行了整合。Hystrix Turbine的使用非常简单&#xff0c;只需要…

APP 怎么免费接入 MobPush

1、获取 AppKey 申请 Appkey 的流程&#xff0c;请点击 http://bbs.mob.com/thread-8212-1-1.html?fromuid70819 2、下载 SDK 下载解压后&#xff0c;如下图&#xff1a; 目录结构 &#xff08;1&#xff09;Sample&#xff1a;演示Demo。&#xff08;2&#xff09;SDK&am…

干货 | 什么是磁传感器?最常用的磁传感器类型及应用

1、什么是磁传感器&#xff1f;磁传感器通常是指将磁场的大小和变化转换成电信号。磁场&#xff0c;以地球磁场(地磁)或磁石为例的磁场是我们熟悉但不可见的现象。将不可见的磁场转化为电信号&#xff0c;以及转化为可见效应的磁传感器一直以来都是研究的主题。从几十年前使用电…

2/9考试总结

时间安排 7:30–7:50 读题&#xff0c;T1貌似需要建图&#xff0c;T2 dp &#xff0c;T3 神秘博弈。 7:50–8:40 T1&#xff0c;首先可以建图&#xff0c;然后可以发现许多优秀性质&#xff0c;发现题目要求实际上是在每棵树上选一条价值最大的链。问题在于如何取最大&#xf…

MySQL事务管理

文章目录MySQL事务管理事务的概念事务的版本支持事务的提交方式事务的相关演示事务的隔离级别查看与设置隔离级别读未提交&#xff08;Read Uncommitted&#xff09;读提交&#xff08;Read Committed&#xff09;可重复读&#xff08;Repeatable Read&#xff09;串行化&#…

2023开工开学火热!远行的人们,把淘特箱包送上顶流

春暖花开&#xff0c;被疫情偷走的三年在今年开学季找补回来了。多个数据反馈&#xff0c;居民消费意愿大幅提升。在淘特上&#xff0c;开工开学节点就很是明显&#xff1a;1月30日以来&#xff0c;淘特箱包品类甚至远超2022年双11&#xff0c;成为开年“第一爆品”。与此同时&…

第四章第七节:CNN练习1使用四种网络结构(VGG、ResNet、MobileNet、InceptionNet)进行cifar10训练

文章目录一&#xff1a;cifar10数据集介绍二&#xff1a;代码&#xff08;1&#xff09;数据加载脚本编写&#xff08;2&#xff09;模型搭建①&#xff1a;VGG②&#xff1a;ResNet③&#xff1a;MobileNetV1④&#xff1a;InceptionNet&#xff08;3&#xff09;训练脚本一&a…

存储式示波器如何保存图片?

示波器是检测电子线路最有效的工具之一&#xff0c;通过观察电子电路中一些关键节点如某些引脚&#xff0c;MOS管的输出波形&#xff0c;可以直观的检查电路工作是否正常&#xff0c;验证电子电路设计是否恰当。在平时使用示波器的过程中&#xff0c;经常会用示波器去卡某一个信…

canvas 制作2048

效果展示 对UI不满意可以自行调整&#xff0c;这里只是说一下游戏的逻辑&#xff0c;具体的API调用不做过多展示。 玩法分析 2048 的玩法非常简单&#xff0c;通过键盘的按下&#xff0c;所有的数字都向着同一个方向移动&#xff0c;如果出现两个相同的数字&#xff0c;就将…

docker安装elashticsearch

福利&#xff1a;这是我的个人IT资源网站&#xff0c;所有资源都免费&#xff0c;注册登录后就可以看到密码&#xff0c;需要什么大家尽情选取&#xff01; 从docker下载elashticsearch镜像&#xff08;可以指定版本号&#xff09; docker pull elasticsearch:7.4.22. 从dock…

网络安全实验室3.脚本关

3.脚本关 1.key又又找不到了 url&#xff1a;http://lab1.xseclab.com/xss1_30ac8668cd453e7e387c76b132b140bb/index.php 点击链接&#xff0c;burp抓包&#xff0c;发送到重放模块&#xff0c;点击go 得到key is : yougotit_script_now 2.快速口算 url&#xff1a;http:…

树莓派开机自启动Python脚本或者应用程序

树莓派开机自启动Python脚本或者应用程序前言一、对于Python脚本的自启动方法1、打开etc/rc.local文件2、编辑输入需要启动的指令3、重启树莓派验证二、对于需要读写配置文件的应用程序的自启前言 在树莓派上写了一些Python脚本&#xff0c;还有一个java 的jar包想要在树莓派上…

2023年,什么样的CRM,才是您最需要的?

春节假期刚刚结束&#xff0c;当大家还沉浸在新春佳节的喜悦中时&#xff0c;很多地方已经争先恐后地奋力开跑了。近日&#xff0c;全国各地方政府相继出台并发布了2023年数字化转型规划&#xff0c;纷纷结合自身的区位特色和优势资源&#xff0c;明确2023年乃至此后数年的数字…

动态规划详解(完结篇)——如何抽象出动态规划算法?以及解题思路

今天直接开始讲解FIRST&#xff1a;如何抽象出动态规划算法&#xff1f;这个问题&#xff0c;困扰了无数代OIER&#xff0c;包括本蒟蒻在比赛的时候&#xff0c;看一道题&#xff0c;怎么想到他是什么算法的呢&#xff1f;这就需要抽象能力而不同的算法&#xff0c;往往有着不同…

The last packet sent successfully to the server was 0 milliseconds ago. 解决办法

mybatis-generator-maven-plugin插件The last packet sent successfully to the server was 0 milliseconds agoYou must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to…

Spark SQL 介绍

文章目录Spark SQL1、Hive on SparkSQL2、SparkSQL 优点3、SparkSQL 特点1) 容易整合2) 统一的数据访问3) 兼容 Hive4) 标准的数据连接4、DataFrame 是什么5、DataSet 是什么Spark SQL Spark SQL 是 Spark 用于结构化数据(structured data) 处理的Spark模块。 1、Hive on Spa…

维基百科数据抽取

1. 数据路径 https://dumps.wikimedia.org/enwiki/latest/ ----英文 https://dumps.wikimedia.org/zhwiki/latest/ ----中文 https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles.xml.bz2 --下载最新的 https://dumps.wikimedia.org/wikidatawiki/2023…

公司招了个腾讯P7:闲聊后被我套出拿下35Koffer的面试技巧

早上一进公司就见人事热热闹闹的带人办入职手续&#xff0c;早之前听说公司将来一个腾讯离职的同事&#xff0c;薪资已达中上水平&#xff0c;大家都很好奇到底是怎样的人才&#xff0c;果不其然&#xff0c;让我们见识到什么是测试天花板 在新人见面会上&#xff0c;自动化、测…

web开发

目录 使用Idea搭建Web项目 使用Idea开发Web项目基本知识 tomcat配置信息 HTML /CSS 开发主页 Servlet 学习和掌握的内容&#xff1a; HTML/CSSServlet MVC模式和Web开发数据库基本应用和JDBC应用软件项目开发流程 环境及工具版本&#xff1a; Windows10,JDK1.8 Idea2…