深入理解栈与队列:从基本概念到高级实现

news2024/9/24 11:28:32

  • 💓 博客主页:江池俊的博客
  • ⏩ 收录专栏:数据结构探索
  • 👉专栏推荐:✅cpolar ✅C语言进阶之路
  • 💻代码仓库:江池俊的代码仓库
  • 🔥编译环境:Visual Studio 2022
  • 🎉欢迎大家点赞👍评论📝收藏⭐

在这里插入图片描述

文章目录

  • 🐳一、栈
    • 💨1.1 栈的概念及结构
    • 💨1.2 栈的创建
      • ✨<1> 栈的存储结构
      • ✨<2> 栈的接口
    • 💨1.3 栈的实现
      • 💥【1】初始化栈
      • 💥【2】进栈
      • 💥【3】出栈
      • 💥【4】获取栈顶元素
      • 💥【5】获取栈中有效元素个数
      • 💥【6】判空
      • 💥【7】销毁栈
  • 🐳二、队列
    • 💨2.1 队列的概念及结构
    • 💨2.2 队列的创建
      • ✨<1>队列的结构
      • ✨<2>队列的接口
    • 💨2.3 队列的实现
      • 💥【1】初始化队列
      • 💥【2】队尾入队
      • 💥【3】队头出队
      • 💥【4】取队头元素
      • 💥【5】取队尾元素
      • 💥【6】获取队列中有效元素个数
      • 💥【7】判空
      • 💥【8】销毁队列
  • 🐳三、源码
    • 💨3.1 栈
    • 💨3.2 队列

🐳一、栈

💨1.1 栈的概念及结构

一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端称为栈顶,另一端称为栈底 。栈中的数据元素遵守 后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

出栈:栈的删除操作叫做出栈。出数据也在栈顶

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

💨1.2 栈的创建

栈的实现一般可以使用 数组或者链表 实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

✨<1> 栈的存储结构


 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
//typedef int STDataType;
//#define N 10
//typedef struct Stack
//{
//	STDataType _a[N];
//	int _top; // 栈顶
//}Stack;

// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		// 栈顶
	int capacity;  // 容量 
}Stack;

✨<2> 栈的接口

// 初始化栈 
void StackInit(Stack* ps);
// 入栈 
void StackPush(Stack* ps, STDataType data);
// 出栈 
void StackPop(Stack* ps);
// 获取栈顶元素 
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数 
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps);
// 销毁栈 
void StackDestroy(Stack* ps);

💨1.3 栈的实现

💥【1】初始化栈

创建一个空的栈,使其数组指针为 NULL,容量为 0,栈顶指针为 0

// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->a = NULL;
	
	ps->capacity = 0;
	ps->top = 0;//top指向栈顶元素的下一个
	
	// 表示top指向栈顶元素
	//pst->top = -1;
}

💥【2】进栈

  1. 初始化:首先,函数通过assert来检查传入的栈指针ps是否非空,以确认该栈存在。如果栈已满(ps->top == ps->capacity),则不执行任何操作。
  2. 扩容:如果栈不满,但接近满载,代码将进行扩容操作。如果栈的当前容量ps->capacity0(即初始状态或刚经历过扩容),新的容量设为 4。否则,新的容量为当前容量的两倍。这样做是为了预先保留足够的空间,避免频繁的扩容操作。
  3. 重新分配内存:使用realloc函数重新分配栈的内存空间。新的内存大小为新的容量乘以数据类型的大小。如果重新分配失败(realloc返回NULL),则输出错误信息并返回。
  4. 数据入栈:将数据data存储在栈顶的位置,即将data赋值给ps->a[ps->top]。然后,栈顶指针ps->top自增 1,表示栈中多了一个元素。
// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->capacity == ps->top)
	{
		int newcapacity = ps->capacity == 0 ? 4 : (ps->capacity) * 2;
		STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->a = temp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = data;
	ps->top++;
}

💥【3】出栈

  1. 初始化:首先,函数通过 assert 来检查传入的栈指针ps是否非空,以确认该栈存在。这保证了不会对一个不存在的栈进行操作。
  2. 栈非空:接着,函数通过另一个 assert 来确认栈顶指针ps->top大于 0,即栈非空。如果栈为空,那么执行出栈操作没有意义,因此代码会在这里停止执行并输出错误信息。
  3. 出栈:如果栈非空,那么代码将栈顶指针ps->top自减 1,表示栈顶的元素已经出栈。
// 出栈 
void StackPop(Stack* ps)
{
	assert(ps);
	//栈不为空
	assert(ps->top > 0);

	ps->top--;
}

💥【4】获取栈顶元素

  1. 初始化:首先,函数通过assert来检查传入的栈指针ps是否非空,以确认该栈存在。这保证了不会对一个不存在的栈进行操作。
  2. 栈非空:接着,函数通过另一个assert来确认栈顶指针ps->top大于0,即栈非空。如果栈为空,那么获取栈顶元素的操作没有意义,因此代码会在这里停止执行并输出错误信息。
  3. 获取栈顶元素:如果栈非空,那么代码将返回栈顶元素,即ps->a[ps->top - 1]。这里之所以使用ps->top - 1,是因为在C/C++中,数组的索引是从0开始的,而栈顶元素实际上是位于栈顶指针所指示的位置的前一个位置。
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
	assert(ps);
	//栈不为空
	assert(ps->top > 0);

	return ps->a[ps->top - 1];
}

💥【5】获取栈中有效元素个数

// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
	assert(ps);

	return ps->top;
}

💥【6】判空

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{
	assert(ps);
	/*if (ps->top == 0)
		return 1;
	return 0;*/

	return ps->top == 0;
}

💥【7】销毁栈

// 销毁栈 
void StackDestroy(Stack* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

🐳二、队列

💨2.1 队列的概念及结构

队列: 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out)

入队列:进行插入操作的一端称为 队尾

出队列:进行删除操作的一端称为 队头

在这里插入图片描述

💨2.2 队列的创建

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,需要将后面的元素向前移动,时间复杂度为 O(1) 效率会比较低。
在这里插入图片描述

✨<1>队列的结构

// 链式结构:表示队列 
typedef int QDataType; //元素类型
//队列的节点
typedef struct QListNode
{
	QDataType data;
	struct QListNode* next;
}QNode; 
// 队列的结构 
typedef struct Queue
{
	QNode* front; //对头
	QNode* rear; //队尾
	int size; //队列元素个数
}Queue;

✨<2>队列的接口

// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

💨2.3 队列的实现

💥【1】初始化队列

通过断言检查输入的有效性,然后初始化队列的front、rear和size属性,为后续队列操作做好准备。

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);

	q->front = q->rear = NULL;
	q->size = 0;
}

💥【2】队尾入队

创建一个新的节点,并将其添加到队列的尾部。如果队列为空,新节点会同时成为队列的前端和后端;如果队列不为空,新节点会添加到队列的后端,并更新队列的后端为新节点。

  1. 断言:通过assert语句检查输入的队列指针是否非空。如果队列指针为空,则程序会在此处停止并输出错误信息。
  2. 动态分配内存:创建一个新的节点newnode,并为其分配内存空间。使用malloc函数实现动态内存分配。如果分配失败(即malloc返回NULL),则输出错误信息并结束函数。
  3. 设置新节点数据:设置新节点的数据为输入的data,并将新节点的下一个节点设置为NULL
  4. 插入新节点:如果队列为空(即队列的前端q->front和队列的后端q->rear都为NULL),那么将新节点设置为队列的前端和后端。如果队列不为空,那么将新节点添加到队列的后端,并更新队列的后端为新节点。
  5. 更新队列大小:每添加一个新节点,队列的大小增加1,因此增加队列的size属性。
// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}

	newnode->data = data;
	newnode->next = NULL;

	if (q->front == NULL)
	{
		q->front = q->rear = newnode;
	}
	else
	{
		q->rear->next = newnode;
		q->rear = newnode;
	}
	
	q->size++;//队列元素加一
}

💥【3】队头出队

删除队列的队头元素,并更新队列的队头和队尾。同时,需要注意处理队列为空的情况,以防止产生野指针。

  1. 断言:通过assert语句检查输入的队列指针是否非空,以及队列是否非空。如果队列指针为空或队列为空,则程序会在此处停止并输出错误信息。
  2. 获取队头节点:保存当前队列的队头节点cur
  3. 更新队头:将队列的队头更新为下一个节点。如果队列变为空(即队列的队头和队尾都为NULL),那么将队尾也设置为NULL
  4. 释放内存:由于已经删除了队头节点,需要使用free函数释放该节点的内存空间。
  5. 更新队列大小:每删除一个元素,队列的大小减1
// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	//队列不为空
	assert(q->front);
	QNode* cur = q->front;
	q->front = q->front->next;
	//队列只有一个元素的情况,要考虑队尾的指针,防止野指针
	if (q->front == NULL)
		q->rear = NULL;

	free(cur);

	q->size--;//队列元素减一
}

💥【4】取队头元素

// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	//队列不为空
	assert(q->front);
	
	return q->front->data;
}

💥【5】取队尾元素

// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	//队列不为空
	assert(q->front);

	return q->rear->data;
}

💥【6】获取队列中有效元素个数

// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);

	return q->size;
}

💥【7】判空

通过比较队列的队头指针q->front是否等于NULL来判断队列是否为空。如果队列为空(即队列的前端和后端都为NULL),则返回非零结果(这里可能是一个表示“真”的值,例如1)。如果队列非空,则返回0。

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	assert(q);

	return q->front == NULL;
}

💥【8】销毁队列

遍历队列中的所有节点并逐个释放其内存空间,然后重置队列的属性以使其成为一个空队列。

  1. 断言:通过assert语句检查输入的队列指针是否非空。如果队列指针为空,则程序会在此处停止并输出错误信息。
  2. 遍历队列:通过一个循环遍历队列中的所有节点。循环继续进行,直到当前节点cur为空。 * 获取当前节点:使用队列的前端指针q->front来获取当前节点cur。 * 释放内存:使用free函数释放当前节点cur的内存空间。 * 移动指针:将当前节点cur的指针更新为下一个节点。
  3. 重置队列属性:将队列的前端指针q->front和后端指针q->rear重置为NULL,并将队列的大小属性q->size重置为0。
// 销毁队列 
void QueueDestroy(Queue* q)
{
	assert(q);

	QNode* cur = q->front;
	while (cur)//当cur为空时结束
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	q->front = q->rear = NULL;
	q->size = 0;
}

🐳三、源码

💨3.1 栈

//Stack.h文件
#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
//typedef int STDataType;
//#define N 10
//typedef struct Stack
//{
//	STDataType _a[N];
//	int _top; // 栈顶
//}Stack;


// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		// 栈顶
	int capacity;  // 容量 
}Stack;

// 初始化栈 
void StackInit(Stack* ps);
// 入栈 
void StackPush(Stack* ps, STDataType data);
// 出栈 
void StackPop(Stack* ps);
// 获取栈顶元素 
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数 
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps);
// 销毁栈 
void StackDestroy(Stack* ps);

//Stack.c文件
#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->a = NULL;
	
	ps->capacity = 0;
	ps->top = 0;//top指向栈顶元素的下一个
	
	// 表示top指向栈顶元素
	//pst->top = -1;
}
// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->capacity == ps->top)
	{
		int newcapacity = ps->capacity == 0 ? 4 : (ps->capacity) * 2;
		STDataType* temp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->a = temp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = data;
	ps->top++;
}
// 出栈 
void StackPop(Stack* ps)
{
	assert(ps);
	//栈不为空
	assert(ps->top > 0);

	ps->top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
	assert(ps);
	//栈不为空
	assert(ps->top > 0);

	return ps->a[ps->top - 1];
}
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
	assert(ps);

	return ps->top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{
	assert(ps);
	/*if (ps->top == 0)
		return 1;
	return 0;*/

	return ps->top == 0;
}
// 销毁栈 
void StackDestroy(Stack* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

//Test.c文件
#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"


void Test()
{
	Stack s;
	StackInit(&s);
	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	printf("%d ", StackTop(&s));
	StackPop(&s);
	printf("%d ", StackTop(&s));
	StackPop(&s);
	
	StackPush(&s, 4);
	StackPush(&s, 5);
	
	//    一     对     多
	// 入栈顺序  --  出栈顺序
	while (!StackEmpty(&s))
	{
		printf("%d ", StackTop(&s));
		StackPop(&s);
	}
	printf("\n");

}

int main()
{
	Test();
	return 0;
}

💨3.2 队列

//Queue.h文件
#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

// 链式结构:表示队列 
typedef int QDataType; //元素类型
//队列的节点
typedef struct QListNode
{
	QDataType data;
	struct QListNode* next;
}QNode;
// 队列的结构 
typedef struct Queue
{
	QNode* front; //对头
	QNode* rear; //队尾
	int size; //队列元素个数
}Queue;

// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

//Queue.c文件
#define _CRT_SECURE_NO_WARNINGS 1

#include "Queue.h"

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);

	q->front = q->rear = NULL;
	q->size = 0;
}
// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}

	newnode->data = data;
	newnode->next = NULL;

	if (q->front == NULL)
	{
		q->front = q->rear = newnode;
	}
	else
	{
		q->rear->next = newnode;
		q->rear = newnode;
	}
	
	q->size++;//队列元素加一
}
// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	//队列不为空
	assert(q->front);
	QNode* cur = q->front;
	q->front = q->front->next;
	//队列只有一个元素的情况,要考虑队尾的指针,防止野指针
	if (q->front == NULL)
		q->rear = NULL;

	free(cur);

	q->size--;//队列元素减一
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	//队列不为空
	assert(q->front);
	
	return q->front->data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	//队列不为空
	assert(q->front);

	return q->rear->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);

	return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	assert(q);

	return q->front == NULL;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{
	assert(q);

	QNode* cur = q->front;
	while (cur)//当cur为空时结束
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	q->front = q->rear = NULL;
	q->size = 0;
}

//Test.c文件
#define _CRT_SECURE_NO_WARNINGS 1

#include "Queue.h"

void Test()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	printf("%d ", QueueFront(&q));
	QueuePop(&q);
	printf("%d ", QueueFront(&q));
	QueuePop(&q);

	QueuePush(&q, 4);
	QueuePush(&q, 5);
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}

	QueueDestroy(&q);
}

int main()
{
	Test();
	return 0;
}

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

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

相关文章

算法设计与分析复习--贪心(二)

文章目录 上一篇哈夫曼编码单源最短路最小生成树Kruskal算法Prim算法 多机调度问题下一篇 上一篇 算法设计与分析复习–贪心&#xff08;一&#xff09; 哈夫曼编码 产生这种前缀码的方式称为哈夫曼树 哈夫曼树相关习题AcWing 148. 合并果子 #include <iostream> #inc…

Network(三)动态路由与ACL配置

一 三层交换机 1 三层交换机概述 三层交换二层交换三层转发 2 虚拟接口概述 在三层交换机上配置的VLAN接口为虚拟接口&#xff0c;使用Vlanif&#xff08;VLAN虚拟接口&#xff09;实现VLAN间路由&#xff0c;VLAN接口的引入使得应用更加灵活 三层交换机VLAN间通信的转发…

基于Qt QList和QMap容器类示例

## QList<T> QList<T>容器是一个数组列表,特点如下: 1.大多数情况下可以用QList。像prepend()、append()和insert()这种操作,通常QList比QVector快的多。这是因为QList是基于index标签存储它的元素项在内存中(虽然内存不连续,这点与STL的list 是一样的),比…

EDA实验-----4*4矩阵键盘与数码管显示测试(Quartus ‖)

目录 一、实验目的 二、实验仪器设备 三、实验原理 四、实验要求 五、实验步骤 六、实验报告 七、实验过程 1.矩阵键盘按键原理 2.数码管原理 3.分频器代码 4.电路图连接 5.文件烧录 一、实验目的 了解数码管的工作原理&#xff1b;掌握4*4矩阵键盘和数码管显示的编…

gradle8.0或者其他版本下载太慢或者time out超时(完美解决方法)

官网镜像地址 如果其他软件除了android studio可以在下面完整直接下载 地址&#xff1a;https://mirrors.cloud.tencent.com/gradle/ Android Stuiod如何配置更换 项目名称\gradle\wrapper\gradle-wrapper.properties 下面是我已经更改后的了&#xff0c;大家如果跟这个不一样换…

解决WPF项目xaml出现“正在等待IntelliSense完成”的问题

在WPF项目xaml里经常出现“正在等待IntelliSense完成”的场景&#xff0c;如下图&#xff1a; 解决办法 工具–选项

Rust与其他语言对比:优势在哪里?

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将深入探讨Rust语言与其他编程语言比较的优势&#xff0c;并通过具体的代码示例和性能数据来加深理解。 Rust与其他语言的比较 1. 内存安全性 Rust&#xff1a;采用所有权系统&#xff0c;编译器在编译时检查内存安全…

sftp 从windows10向linux(centos7)传输文件

前言背景&#xff1a;该示例是需要从windows10向本地linux系统传输一个qt安装文件&#xff0c;不想或者无法安装xftp这些传输工具&#xff0c;直接通过命令传输&#xff1b; 首先保证windows10 ping通linux系统ip&#xff0c;linux ping 通windows10系统&#xff1b; 注意&am…

Android修行手册-POI操作中文API文档

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

uview-plus中二级菜单左右联动更改为uni-app+vue3+vite写法

uview-plus3.0重磅发布&#xff0c;全面的Vue3移动组件库 该插件使用的vue2写法&#xff0c;但支持vue3引用&#xff0c;在此基础上修改为uni-appvue3vite; <template><view class"u-wrap mainClass"><!-- <back-header :title"pageTitle&quo…

【python】--python基础学习

目录 一、基础语法二、基础数据类型1、变量赋值2、数值型3、字符串型4、列表List5、元组Tuple6、字典dictionary7、数据类型转换 三、python运算符四、条件控制与循环五、常用函数1、字符串函数2、format函数 一、基础语法 标识符是允许作为变量&#xff08;函数、类等&#x…

RHCSA --- Linux存储管理

存储管理 Boot&#xff1a;可引导操作系统的分区&#xff08;必须是主分区&#xff09; 分区 ll /dev/nvme0n* 表示的是 nvme接口的磁盘 0n1 1 0n2 2 0n3 3 brw-rw----. 1 root disk 259, 0 Nov 15 19:31 /dev/nvme0n1 磁盘1 brw-rw----. 1 ro…

Python3.7+PyQt5 pyuic5将.ui文件转换为.py文件、Python读取配置文件、生成日志

1.实际开发项目时&#xff0c;是使用Qt Designer来设计UI界面&#xff0c;得到一个.ui的文件&#xff0c;然后利用PyQt5安装时自带的工具pyuic5将.ui文件转换为.py文件&#xff1a; pyuic5 -o mywindow.py mywindow.ui #先是py文件名&#xff0c;再是ui文件名样式图 QT5 UI&am…

SQLite 安装和 Java 使用教程

SQLite是一个C语言库&#xff0c;它实现了一个小型、快速、自包含、高可靠性、功能齐全的SQL数据库引擎。SQLite是世界上使用最多的数据库引擎。SQLite内置于所有手机和大多数计算机中&#xff0c;并捆绑在人们每天使用的无数其他应用程序中。 SQLite文件格式稳定、跨平台、向…

分库分表

分库&#xff0c;分表&#xff0c;分库分表 “只分库“&#xff0c;“只分表“&#xff0c;“既分库又分表" 何时分库 在面对高并发的情况下&#xff0c;数据库连接成为性能瓶颈。当数据QPS过高导致数据库连接数不足时&#xff0c;考虑分库。在读多写少的场景下&#x…

场景交互与场景漫游-交运算与对象选取(8-1)

交运算与对象选取 在面对大规模的场景管理时&#xff0c;场景图形的交运算和图形对象的拾取变成了一项基本工作。OSG作为一个场景管理系统&#xff0c;自然也实现了场景图形的交运算&#xff0c;交运算主要封装在osgUtil 工具中在OSG中&#xff0c;osgUtil是一个非常强有力的工…

基于学生心理学算法优化概率神经网络PNN的分类预测 - 附代码

基于学生心理学算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于学生心理学算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于学生心理学优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针…

电子学会2023年6月青少年软件编程(图形化)等级考试试卷(四级)真题,含答案解析

青少年软件编程(图形化)等级考试试卷(四级) 一、单选题(共10题,共30分) 1. 下列积木运行后的结果是?( )(说明:逗号后面无空格) A.

【ATTCK】MITRE Caldera-路径发现插件

CALDERA是一个由python语言编写的红蓝对抗工具&#xff08;攻击模拟工具&#xff09;。它是MITRE公司发起的一个研究项目&#xff0c;该工具的攻击流程是建立在ATT&CK攻击行为模型和知识库之上的&#xff0c;能够较真实地APT攻击行为模式。 通过CALDERA工具&#xff0c;安全…

AOT:一个.Net 8最牛逼和最受欢迎关注的功能!

这次.Net 8发布&#xff0c;更新了诸多功能&#xff0c;但从各个编程社区看到大家讨论和交流最多的&#xff0c;还是AOT这个功能。 AOT本身在.Net 7就开始引入了&#xff0c;但这次.Net 8做了诸多更新&#xff1a; 1、增加了macOS 平台的 x64 和 Arm64 体系结构的支持&#x…