【循环顺序队的实现】

news2024/11/16 23:51:54

1.队列的逻辑结构 与 抽象数据类型定义

  • 先进先出的线性表
    在这里插入图片描述
    在顺序队列中,我们使用头指针front指向队首元素;用尾指针rear指向队尾元素的下一个位置(当然这里的指针是用下标模拟出来的
    同时顺序队列中的元素当然是用数组来存储的

  • 抽象数据类型如下
    在这里插入图片描述
    注意这里的传参,本篇使用指针传参,与图中c++的引用有所区别

2.一般顺序队列的模拟操作

  • 初始时,头尾指针均指向下标为0的位置
  • 始终遵循先进先出原则;队头出队,队尾入队
    在这里插入图片描述

3.一般顺序队所面临的假上溢问题:(问题一)

设数组大小为MAXQSIZE
当尾指针rear==MAXQSIZE时 就会出现溢出现象,而这种溢出又分为两种情况

  • 1.真溢出
    即数组的所有空间都存在元素

特征为:
(1)头指针 front = 0
(2)尾指针 rear = MAXQSIZE

在这里插入图片描述

  • 2.假溢出
    即数组中还存在空闲空间,但尾指针已经越界

特征为:
(1)头指针 front != 0
(2)尾指针 rear = MAXQSIZE

在这里插入图片描述
而为了避免这种假上溢问题,我们就引入了循环队列来解决

4.循环队列解决假上溢问题

4.1将队中元素依次向队头方向移动

但是这样做有一个显著的缺点,即浪费时间;每移动一次,队中元素都要移动。所以并不推荐

4.2循环队列解决假上溢问题

将队空间设想成一个循环的表,即分配给队列的m个存储单元可以循环使用,当rear为maxqsize时若数组的开始端空着,又可从头使用空着的空间;当front为maxqsize时,同理。

设数组名为data, 则核心思路为:

  • data[0]接在data[MAXQSIZE-1]之后
  • 即当rear+1==MAXQSIZE时,令rear=0;

要想实现上述顺序的循环操作,就需要一个重要的运算方法,即模运算
在这里插入图片描述

  • 队尾插入元素时:
Q->data[Q->rear]=e;//将元素插入到当前尾指针指向的空间(即队尾元素的后一个位置)
Q->rear=(Q->rear+1)% MAXQSIZE;//更新队尾指针指向队尾元素的下一个位置

这里取模的作用就是rear为maxqsize时若数组的开始端空着,就可以更新尾指针指向空着的开始端空间(详见第2种插入的情况)

    • 1.一般情况下的插入:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

      1. 数组存在空闲的开始端在数组的最后一个空间插入时(此时尾指针需要更新到空闲的数组开始端):

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 队头删除元素时:
*e=Q->data[Q->front];//将队头元素传递给变量e
Q->front=(Q->front+1)% MAXQSIZE;//更新队头指针指向当前队头的位置

这里取模的作用就是front为maxqsize时若数组的开始端空着,就可以更新头指针指向空着的开始端空间(详见第2种删除的情况)

    • 1.一般情况下的删除:
      在这里插入图片描述
      在这里插入图片描述

在这里插入图片描述

    • 2.数组存在空闲的开始端且此时头指针指向的空间为数组的最后一个空间(此时头指针需要更新到空闲的数组开始端):
      在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.3循环顺序对的 物理结构 与 逻辑结构 的辨析

在解决假上溢问题时,我用一维数组的结构图来分析了具体的操作,而这正是循环顺序对的真实的物理结构,我们仅仅是使用特定的操作使其操作起来如同想象中的头尾相连的环形逻辑结构而已,如下图:

在这里插入图片描述

5.循环队列面临的队空 与 队满判断条件一致的问题 (问题二)

通过取模法我们解决了一般队列的假上溢问题,但是,正常的循环顺序对又给我们带来了新的问题,如下图:
在这里插入图片描述
通过分析我们可以发现,若每个空间都存储一个队列元素,那么不论是队满还是队空,两种情况的判断条件会完全一致

Q->front==Q->rear

6.解决队空 与 队满判断条件一致的方法:

一般有如下三种解决方案,而本篇使用第3种
在这里插入图片描述

6.1循环队列解决队满时判断方法–少用一个元素空间:

在这里插入图片描述
这种方式可以区别队空和队满的判断条件:
判断队空(头尾指针重合时,队空):

Q->front==Q->rear//头尾指针指针重合时,队空

判断队满(由于少用一个空间,故头尾指针相邻时,队满):

(Q->rear+1)%MAXQSIZE==Q->front
//见上图:共有两种情况
<1>一般情况,Q->rear+1==Q->front
<2>当尾指针指向数组最后一个空间(rear+1==MAXQSIZE)
头指针指向数组第一个空间时(rear==0),
需要用到取模运算:(Q->rear+1)%MAXQSIZE==Q->front

7.循环顺序队的整队实现(少用一个元素空间)

7.1队列的顺序存储结构

//1.队列的顺序存储结构
typedef struct Queue
{
	QElemType * data;//存储元素的动态数组
	int front;//头指针,若队列不空,指向队列头元素
	int rear;//尾指针,若队列不空,指向队列尾元素的下一个位置
	//注意这里的头尾指针并不是指针变量,而是用下标模拟指针功能的int变量
}Queue;
//Queue:用来定义循环顺序对列

一个循环顺序队的存储结构中包含头指针,指向队列头元素尾指针,指向队列尾元素的下一个位置存储元素的动态数组这三个部分

7.2循环顺序队的初始化

注意:这里需要传入结构指针,因为要修改结构体中成员进行动态分配内存

bool InitQueue(Queue *q)
7.2.1算法步骤:

(1)为循环顺序对动态分配空间
(2)初始化头尾指针为0,表示队列为空

//1.循环顺序队的初始化
//注意:这里需要传入结构指针,因为要修改结构体中成员进行动态分配内存
bool InitQueue(Queue *q)
{
	//[1]为循环顺序对动态分配空间
	q->data=(QElemType *)malloc(MAXQSIZE*sizeof(QElemType));
	//这里由于数组首地址为一个指针,故可以使用q.data来接受mallocmalloc返回的指针

	if (!q->data)
	{
		return false;//内存分配失败
	}

	//[2]初始化头尾指针为0,表示队列为空
	q->front=q->rear=0;
	return true;
}

7.3求循环顺序队的长度

注意:这里不用传入结构指针,因为只计算长度,不改变结构体

int QueueLength(Queue q)
7.3.1算法步骤:

(1)(尾指针 与 头指针作差 再加MAXQSIZE)并取余MAXQSIZE,得到队列长度
//注意这里加MAXQSIZE并取余MAXQSIZE,是防止尾指针在低地址端

7.3.2三种情况下的图解

在这里插入图片描述

//2.求循环顺序队的长度
//注意:这里不用传入结构指针,因为只计算长度,不改变结构体
int QueueLength(Queue q)
{
	//[1](尾指针 与 头指针作差 再加MAXQSIZE)并取余MAXQSIZE,得到队列长度
	//注意这里加MAXQSIZE并取余MAXQSIZE,是防止尾指针在低地址端
	return (q.rear - q.front + MAXQSIZE) % MAXQSIZE;
}

7.4循环顺序队的入队操作(核心1)

注意:这里需要传入结构指针,因为要修改结构体中成员:传入元素,修改尾指针

bool EnQueue(Queue * q,QElemType e)
7.4.1算法步骤:

1)判断队列是否已满
(2)进行入队操作
<1>新元素插入到当前尾指针指向的空间(当前队尾元素的下一个位置)
<2>更新尾指针,指向新的队尾结点的下一个位置

//3.循环顺序队的入队操作
//注意:这里需要传入结构指针,因为要修改结构体中成员:传入元素,修改尾指针
bool EnQueue(Queue * q,QElemType e)
{
	
	//[1]判断队列是否已满
	//这里对MAXQSIZE进行取余,是为了应对以下情况
	//尾指针指向数组最后一个空间(rear+1==MAXQSIZE),头指针指向数组第一个空间时(rear==0)
	//因为 MAXQSIZE % MAXQSIZE == 0
	if ((q->rear + 1) % MAXQSIZE == q->front)
	{
		return false;//队满
	}

	//[2]进行入队操作
	//<1>新元素插入到当前尾指针指向的空间(当前队尾元素的下一个位置)
	q->data[q->rear] = e;
	//<2>更新尾指针,指向新的队尾结点的下一个位置
	//这里对MAXQSIZE进行取余,是为了应对以下情况(防止上溢出)
	//尾指针指向数组最后一个空间(rear+1==MAXQSIZE),要更新尾指针指向数组第一个空间时(rear==0)   
	//因为 MAXQSIZE % MAXQSIZE == 0
	q->rear = (q->rear + 1) % MAXQSIZE;

	return true;
}

7.5循环顺序队的入队操作(核心2)

注意:这里需要传入结构指针,因为要修改结构体中成员:修改头指针

bool Dequeue(Queue * q,QElemType * e)
7.5.1算法步骤:

(1)判断队列是否为空
(2)保存队头元素
(3)更新头指针,指向新的队头结点

//4.循环顺序队的出队操作
//注意:这里需要传入结构指针,因为要修改结构体中成员:修改头指针
bool Dequeue(Queue * q,QElemType * e)
{
	//[1]判断队列是否为空
	if (q->rear == q->front)
	{
		return false;//队空
	}

	//[2]保存队头元素
	*e = q->data[q->front];

	//[3]更新头指针,指向新的队头结点
	//这里对MAXQSIZE进行取余,是为了应对以下情况(防止上溢出)
	//头指针指向数组最后一个空间(front+1==MAXQSIZE),要更新头指针指向数组第一个空间时(front == 0) 
	//因为 MAXQSIZE % MAXQSIZE == 0
	q->front = (q->front + 1) % MAXQSIZE;
	return true;
}

7.6循环顺序队的取队头元素操作(核心3)

注意:这里不需要传入结构指针,因为不修改结构体中成员,仅传出元素

bool GetFront(Queue q, QElemType* e)
7.6.1算法步骤:

(1)判断是否队空
(2)取出队头元素

//5.循环顺序队的取队头元素操作
//注意:这里不需要传入结构指针,因为不修改结构体中成员,仅传出元素
bool GetFront(Queue q, QElemType* e)
{
	//[1]判断是否队空
	if (q.rear == q.front)
	{
		return false;//队空
	}

	//[2]取出队头元素
	*e = q.data[q.front];
	
	return true;
}

7.7循环顺序队的清空操作

注意:这里需要传入结构指针,因为要修改结构体中成员;头尾指针

bool ClearQueue(Queue* q) 
7.7.1算法步骤

(1)直接将头尾指针重置为0

//6.循环顺序队的清空操作
//注意:这里需要传入结构指针,因为要修改结构体中成员;头尾指针
bool ClearQueue(Queue* q) 
{
	//[1]直接将头尾指针重置为0
	//注意:这里是逻辑上的清空,物理上并没有清空队列,只是重置了头尾指针
	//在入队新元素时,是可以将原来队列中可能存在的元素覆盖掉的
	q->front = q->rear = 0; // 重置头尾指针
	return true;
}

7.8循环顺序队的销毁操作

注意:这里需要传入结构指针,因为要修改结构体中成员;头尾指针,并释放数组空间

bool DestroyQueue(Queue* q) 
7.8.1算法步骤

(1)直接销毁存储队列元素的动态数组
(2)注意重置头尾指针

//7.循环顺序队的销毁操作
//注意:这里需要传入结构指针,因为要修改结构体中成员;头尾指针,并释放数组空间
bool DestroyQueue(Queue* q) 
{
	//[1]直接销毁存储队列元素的动态数组
	if (q->data) 
	{
		free(q->data); // 释放动态分配的内存
		q->data = NULL;
	}

	//[1]注意重置头尾指针
	q->front = q->rear = 0; // 重置指针
	return true;
}

7.9遍历队列并打印(从队头开始)

bool TraverseQueue(Queue* q)
7.9.1算法步骤:

(1)初始化计数器等于头指针的值
(2)循环遍历队列元素
注意更新计数器时的取模操作(i+1==MAXQSIZE时,i更新到下标为0处),保证循环结构的正确性

//8.遍历队列并打印(从队头开始)
bool TraverseQueue(Queue* q)
{
	//[1]初始化计数器等于头指针的值
	int i = q->front;

	//[2]循环遍历队列元素
	while (i != q->rear) 
	{
		printf("%d ", q->data[i]);
		i = (i + 1) % MAXQSIZE;
		//注意更新计数器时的取模操作,保证循环结构的正确性
	}
	printf("\n");
	return true;
}

7. 10所有操作汇总:

//循环顺序队列(动态数组,用浪费一个数组空间的方式来解决)
#include<stdio.h>
#include<stdlib.h>


#define MAXQSIZE 100//最大队列长度

#define bool int
#define true 1
#define false 0

typedef int QElemType;


//1.队列的顺序存储结构
typedef struct Queue
{
	QElemType * data;//存储元素的动态数组
	int front;//头指针,若队列不空,指向队列头元素
	int rear;//尾指针,若队列不空,指向队列尾元素的下一个位置
	//注意这里的头尾指针并不是指针变量,而是用下标模拟指针功能的int变量
}Queue;
//Queue:用来定义循环顺序对列



//1.循环顺序队的初始化
//注意:这里需要传入结构指针,因为要修改结构体中成员进行动态分配内存
bool InitQueue(Queue *q)
{
	//[1]为循环顺序对动态分配空间
	q->data=(QElemType *)malloc(MAXQSIZE*sizeof(QElemType));
	//这里由于数组首地址为一个指针,故可以使用q.data来接受mallocmalloc返回的指针

	if (!q->data)
	{
		return false;//内存分配失败
	}

	//[2]初始化头尾指针为0,表示队列为空
	q->front=q->rear=0;
	return true;
}

//2.求循环顺序队的长度
//注意:这里不用传入结构指针,因为只计算长度,不改变结构体
int QueueLength(Queue q)
{
	//[1](尾指针 与 头指针作差 再加MAXQSIZE)并取余MAXQSIZE,得到队列长度
	//注意这里加MAXQSIZE并取余MAXQSIZE,是防止尾指针在低地址端
	return (q.rear - q.front + MAXQSIZE) % MAXQSIZE;
}



//3.循环顺序队的入队操作
//注意:这里需要传入结构指针,因为要修改结构体中成员:传入元素,修改尾指针
bool EnQueue(Queue * q,QElemType e)
{
	
	//[1]判断队列是否已满
	//这里对MAXQSIZE进行取余,是为了应对以下情况
	//尾指针指向数组最后一个空间(rear+1==MAXQSIZE),头指针指向数组第一个空间时(rear==0)
	//因为 MAXQSIZE % MAXQSIZE == 0
	if ((q->rear + 1) % MAXQSIZE == q->front)
	{
		return false;//队满
	}

	//[2]进行入队操作
	//<1>新元素插入到当前尾指针指向的空间(当前队尾元素的下一个位置)
	q->data[q->rear] = e;
	//<2>更新尾指针,指向新的队尾结点的下一个位置
	//这里对MAXQSIZE进行取余,是为了应对以下情况(防止上溢出)
	//尾指针指向数组最后一个空间(rear+1==MAXQSIZE),要更新尾指针指向数组第一个空间时(rear==0)   
	//因为 MAXQSIZE % MAXQSIZE == 0
	q->rear = (q->rear + 1) % MAXQSIZE;

	return true;
}

//4.循环顺序队的出队操作
//注意:这里需要传入结构指针,因为要修改结构体中成员:修改头指针
bool Dequeue(Queue * q,QElemType * e)
{
	//[1]判断队列是否为空
	if (q->rear == q->front)
	{
		return false;//队空
	}

	//[2]保存队头元素
	*e = q->data[q->front];

	//[3]更新头指针,指向新的队头结点
	//这里对MAXQSIZE进行取余,是为了应对以下情况(防止上溢出)
	//头指针指向数组最后一个空间(front+1==MAXQSIZE),要更新头指针指向数组第一个空间时(front == 0) 
	//因为 MAXQSIZE % MAXQSIZE == 0
	q->front = (q->front + 1) % MAXQSIZE;
	return true;
}



//5.循环顺序队的取队头元素操作
//注意:这里不需要传入结构指针,因为不修改结构体中成员,仅传出元素
bool GetFront(Queue q, QElemType* e)
{
	//[1]判断是否队空
	if (q.rear == q.front)
	{
		return false;//队空
	}

	//[2]取出队头元素
	*e = q.data[q.front];
	
	return true;
}

//6.循环顺序队的清空操作
//注意:这里需要传入结构指针,因为要修改结构体中成员;头尾指针
bool ClearQueue(Queue* q) 
{
	//[1]直接将头尾指针重置为0
	//注意:这里是逻辑上的清空,物理上并没有清空队列,只是重置了头尾指针
	//在入队新元素时,是可以将原来队列中可能存在的元素覆盖掉的
	q->front = q->rear = 0; // 重置头尾指针
	return true;
}



//7.循环顺序队的销毁操作
//注意:这里需要传入结构指针,因为要修改结构体中成员;头尾指针,并释放数组空间
bool DestroyQueue(Queue* q) 
{
	//[1]直接销毁存储队列元素的动态数组
	if (q->data) 
	{
		free(q->data); // 释放动态分配的内存
		q->data = NULL;
	}

	//[1]注意重置头尾指针
	q->front = q->rear = 0; // 重置指针
	return true;
}


//8.遍历队列并打印(从队头开始)
bool TraverseQueue(Queue* q)
{
	//[1]初始化计数器等于头指针的值
	int i = q->front;

	//[2]循环遍历队列元素
	while (i != q->rear) 
	{
		printf("%d ", q->data[i]);
		i = (i + 1) % MAXQSIZE;
		//注意更新计数器时的取模操作,保证循环结构的正确性
	}
	printf("\n");
	return true;
}

// 主函数测试代码
int main() 
{
	Queue q;

	// 初始化队列
	if (InitQueue(&q)) {
		printf("初始化队列成功!\n");
	}

	// 入队操作
	for (int i = 1; i <= 10; i++) 
	{
		EnQueue(&q, i);
	}

	// 遍历队列
	printf("队列中的元素: ");
	TraverseQueue(&q);

	// 出队操作
	int e;
	Dequeue(&q, &e);
	printf("出队元素: %d\n", e);

	// 再次遍历队列
	printf("队列中的元素: ");
	TraverseQueue(&q);

	// 取队头元素
	GetFront(q, &e);
	printf("队头元素: %d\n", e);

	// 清空队列
	ClearQueue(&q);
	printf("队列清空后长度: %d\n", QueueLength(q));

	// 销毁队列
	DestroyQueue(&q);

	return 0;
}

在这里插入图片描述

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

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

相关文章

【系统架构设计】嵌入式系统设计(1)

【系统架构设计】嵌入式系统设计&#xff08;1&#xff09; 嵌入式系统概论嵌入式系统的组成硬件嵌入式处理器总线存储器I/O 设备与接口 软件 嵌入式开发平台与调试环境交叉平台开发环境交叉编译环境调试 嵌入式网络系统嵌入式数据库管理系统实时系统与嵌入式操作系统嵌入式系统…

【Qt笔记】QToolButton控件详解

目录 一、前言 二、QToolButton的基本特性 2.1 图标和文本 2.2 自动提升 2.3 下拉菜单 2.4 工具提示 2.5 弹出模式 三、高级功能 3.1 自定义大小与形状 3.2 检查框与单选按钮 3.3 动画效果 四、常用方法与信号槽 常用方法 信号槽 五、实际应用示例 说明 六、总…

ESP32 CYD 使用 LVGL 在屏幕上显示图像 | Random Nerd Tutorials

在本指南中&#xff0c;你将学习如何使用LVGL在ESP32 Cheap Yellow Display (CYD) 板上处理和加载图像。ESP32将使用Arduino IDE进行编程。 对ESP32 Cheap Yellow Display不熟悉&#xff1f; 从这里开始&#xff1a;开始使用ESP32 Cheap Yellow Display Board – CYD (ESP32-2…

线性代数 第三讲 线性相关无关 线性表示

线性代数 第三讲 线性相关无关 线性表示 文章目录 线性代数 第三讲 线性相关无关 线性表示1.向量运算1.线性相关与线性无关1.1 线性相关与线性无关基本概念 2.线性表示&#xff08;线性组合&#xff09;3.线性相关无关与线性表示的定理大总结3.1 向量β可由向量组线性表出的同义…

心觉:潜意识显化很简单,只是很多人想复杂了

很多人知道潜意识的力量很大&#xff0c;是意识力量的30000倍以上 也知道该怎么显化自己的潜意识 但是就是做不到 这就像很多肥胖的人知道运动可以减肥 知道减肥之后就可以穿漂亮的衣服 知道减肥之后自己有多帅多美 但是就是迈不开腿 根本原因是你的潜意识和意识上的认知不…

RenderMan v26.2更新内容!云渲染平台支持新版本

皮克斯的最新RenderMan v26.2版本带来了一系列激动人心的新特性和改进&#xff0c;进一步巩固了其在高端渲染领域的领导地位&#xff0c;为艺术家们提供了更丰富的创意工具和更流畅的工作流程。作为老牌的云渲染农场&#xff0c;瑞云依然支持新版本的使用。 RenderMan v26.2更新…

移动端视频编辑SDK解决方案,关键帧曲线塑造生动效果

美摄科技&#xff0c;作为移动视频编辑技术的领航者&#xff0c;携其革命性的移动端视频编辑SDK解决方案&#xff0c;正以前所未有的创新力&#xff0c;为视频创作者们开启了一扇通往无限创意的大门。 重塑视频编辑体验&#xff0c;让创意触手可及 美摄科技的移动端视频编辑S…

公网信息泄露监测(网盘、暗网、搜索引擎、文档平台)思路分享

一、背景 众测项目中白帽可能会提交一些信息泄露漏洞&#xff0c;同时甲方可会收到一些白帽提交的公网信息泄露文件漏洞&#xff0c;例如百度网盘被员工分享某些文件或者某些包含敏感信息的文件可以通过如谷歌、百度等搜索引擎通过特定语法搜索到。为了可以及时发现泄露的文件…

九泰智库 | 医械周刊- Vol.54

⚖️ 法规动态 国家药监局综合司发布医疗器械管理法草案征求意见稿 国家药监局综合司发布了《中华人民共和国医疗器械管理法&#xff08;草案征求意见稿&#xff09;》&#xff0c;公开征求意见&#xff0c;以加强医疗器械的管理并推动产业高质量发展。该草案共十一章190条&a…

深入解析财务报表:掌握重要财务指标的技巧

一、概述 财务报表中有大量信息&#xff0c;如果我们在分析时缺乏明确的方向或忽视了重点&#xff0c;就很容易在繁杂的数据中迷失方向。本文将深入探讨财务报表中的几个重要指标&#xff0c;帮助大家更有针对性地理解这些内容&#xff0c;包括如何分析资产负债率、解读净资产…

基于python的web框架 Flask 入门基础知识【1】

Flask是一个轻量级的可定制框架&#xff0c;使用Python语言编写&#xff0c;较其他同类型框架更为灵活、轻便、安全且容易上手。 目录 一、项目环境搭配以及安装运行 1.下载安装 2.最小的应用 3.运行应用 4.运行结果 4.1 外部可见的服务器 二、路由 三、http请求 3.1静…

无人机的核心技术!!!

无人机的核心技术涵盖了多个关键领域&#xff0c;这些技术共同支撑了无人机的稳定飞行、精准控制、高效数据传输以及多样化的应用功能。 1. 飞行控制技术 核心地位&#xff1a;飞行控制技术是无人机的核心关键技术之一&#xff0c;它确保了无人机在复杂飞行环境下的稳定性和安…

论文AI生成软件大PK!揭秘学术界的高效神器,选对了让你研究效率翻倍

在当今的学术界&#xff0c;研究与写作的压力不断攀升&#xff0c;论文的质量与数量往往成为衡量学者成就的重要指标。 然而&#xff0c;面对繁杂的研究任务和紧张的时间线&#xff0c;如何提升学术生产力成为了广大研究人员、学生及教育工作者的共同诉求。 在这样的背景下&a…

了解 JavaScript SEO

如果您是 SEO 专家&#xff0c;而不是开发人员&#xff0c;那么您可能不需要深入了解网站开发的所有复杂性。但是您确实需要了解基础知识&#xff0c;因为网站的编码方式对其性能有很大影响&#xff0c;因此对 SEO 潜力有很大影响。在关于 HTML 标签的文章中&#xff0c;我们介…

CTFHub SSRF靶场通关攻略(6-11)

FastCGI协议 首先写一个php的一句话木马&#xff0c;并进行base64编码 <?php eval($_POST[cmd]);?> 编码完成后把他写入shell.php文件中 echo "PD9waHAgQGV2YWwoJF9QT1NUW2NtZF0pOz8" | base64 -d > shell.php 使用Gopherus工具生成payload: 执命令 …

中国卫星影像图Level5

卫星地图&#xff0c;又称“卫星遥感图像或是卫星影像”&#xff0c;顾名思义&#xff0c;是借助卫星为媒介&#xff0c;向用户真实反馈地球地表面貌的图像。与传统意义的地图不同&#xff0c;卫星地图上看到的地表面貌是真实而实时的&#xff0c;因此&#xff0c;卫星地图的使…

2024-8-28作业C++/QT

代码&#xff1a; #include <iostream> #include <cstring> #include <array> #include <iomanip> using namespace std; int main() { //array<char,128> a; //array<char,128>::iterator iter; string str; getline(c…

工信部人工智能证书在哪报名?报名入口!

证书出台背景&#xff1a; 为进一步贯彻落实中共中央印发《关于深化人才发展体制机制改革的意见》和国务院印发《关于“十四五”数字经济发展规划》等有关工作的部署要求&#xff0c;深入实施人才强国战略和创新驱动发展战略&#xff0c;加强全国数字化人才队伍建设&#xff0…

探索音视频SDK在软件集成与私有化部署中的技术难题与解决策略

随着数字化转型的加速&#xff0c;音视频通信已成为众多行业不可或缺的一部分&#xff0c;从在线教育到企业协作&#xff0c;从电商直播到远程医疗&#xff0c;音视频SDK&#xff08;软件开发工具包&#xff09;作为实现这些功能的核心技术&#xff0c;其重要性日益凸显。然而&…

Threejs制作窗户透亮效果

应该经常看到这样的图片&#xff0c;昏暗的屋里&#xff0c;阳光通过窗户照射进来&#xff0c;将照射到的地方照亮&#xff0c;没有照到的地方依然昏暗&#xff0c; Threejs提供了一种特殊的灯光用来实现上图中的效果叫RectAreaLight&#xff0c;他是一种平面光源&#xff0c;平…