数据结构之栈和队列(超详解

目录

一.栈

1.栈的基本概念

2.栈的基本操作

3.栈的储存结构

 ①栈的顺序储存

(1)基本概念

 (2)代码实现

②栈的链式储存

 (1)基本概念

(2)代码实现

 二.队列

1.队列的基本概念

2.队列的基本操作

3.队列的储存结构

①队列的链式储存

(1)基本概念

​编辑 (2)代码实现

②循环队列

(1)基本概念

 (2)代码实现


一.栈

1.栈的基本概念

栈是一种常见的数据结构,它是一种“后进先出”(Last In First Out,LIFO)的数据结构,即最后放入栈的元素最先被取出。在计算机中,栈通常由一段连续的内存区域组成,它具有两个基本操作:压栈(Push)和弹栈(Pop)。

压栈将一个元素放入栈顶,弹栈将栈顶元素取出并从栈中删除。

除此之外,栈还具有一个特点:访问栈顶元素的时间复杂度是 O(1),也就是说,无论栈中有多少元素,访问栈顶元素的时间复杂度都是常数级别的。

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);

3.栈的储存结构

链式储存的栈相比于顺序储存的栈具有更好的动态性和灵活性,因为链式储存的栈可以动态地扩展或缩小,不需要事先确定储存空间的大小。但是由于链式储存需要使用指针,因此它的空间开销较大,同时由于每个节点都需要动态分配内存,所以它的时间开销也会相对较大。

 ①栈的顺序储存

(1)基本概念

栈是一种线性数据结构,可以通过数组实现顺序储存。栈的顺序储存特点是使用数组作为底层数据结构,只能从一端插入和删除元素,这一端被称为栈顶。栈的顺序储存还需要记录栈顶指针,用来指向当前栈顶元素的位置。

 (2)代码实现

栈的顺序存储结构可描述为:

// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{STDataType* _a;int _top;		// 栈顶int _capacity;  // 容量 
}Stack;

基本操作:

#include<stdlib.h>
#include<assert.h>
// 初始化栈 
void StackInit(Stack* ps)
{assert(ps);ps->_a = NULL;ps->_capacity = 0;//top指向栈顶的下一个元素ps->_top = 0;
}
// 入栈 
void StackPush(Stack* ps, STDataType data)
{assert(ps);if (ps->_capacity == ps->_top) {ps->_capacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;STDataType* newnode = (STDataType)realloc(ps->_a,sizeof(STDataType) * ps->_capacity);if (newnode==NULL){perror("realloc:");return;}ps->_a = newnode;}ps->_a[ps->_top] = data;ps->_top++;
}
// 出栈 
void StackPop(Stack* ps)
{assert(ps);assert(ps->_a);ps->_top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->_a);return ps->_a[ps->_top - 1];
}
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{assert(ps);return ps->_top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{assert(ps);return ps->_top==0;
}
// 销毁栈 
void StackDestroy(Stack* ps)
{ps->_a = NULL;ps->_capacity = 0;ps->_top = 0;
}

代码测试:

#include<stdio.h>
int main()
{Stack s;StackInit(&s);StackPush(&s, 1);StackPush(&s, 2);StackPush(&s, 3);StackPush(&s, 4);printf("栈中有%d个数字\n", StackSize(&s));while (!StackEmpty(&s)) {printf("%d\n", StackTop(&s));StackPop(&s);}StackDestroy(&s);return 0;
}

 

②栈的链式储存

 (1)基本概念

栈的链式储存是将栈中的元素通过链表的方式进行储存。

具体来说,链式储存的栈由两个部分组成:栈顶指针和链表。

其中,栈顶指针指向链表中的第一个元素,每次入栈操作都会将新元素插入到链表头部并更新栈顶指针,而出栈操作则是删除链表头部元素并更新栈顶指针。如果栈为空,则栈顶指针为空指针。

(2)代码实现

栈的链式储存结构可描述为:

/*构造节点*/
typedef struct StackNode{SElemType data;struct StackNode *next;
}StackNode, *LinkStackPrt;
/*构造链栈*/
typedef struct LinkStack{LinkStackPrt top;int count;
}LinkStack;

基本操作:

#include<stdio>
#include<stdlib>
#define OK 1
#define ERROR 0
typedef int SElemType; 
typedef int Status; //初始化链栈
Status InitLinkStack(LinkStack **S)
{*S = (LinkStack*)malloc(sizeof(LinkStack)); //申请内存空间if ((*S) == NULL) //判断申请内存空间是否成功{printf("申请内存空间失败,初始化失败!\n"); //输出提示语return ERROR;}(*S)->top = NULL; //栈为空时,为NULL,这样最后一个结点的指针域为NULL(*S)->count = -1; //链栈为空时,赋值为-1printf("初始化成功!\n"); //输出提示语return OK;
}//建立链栈
Status CreateLinkStack(LinkStack *S)
{int i = 0;SElemType e;StackNode *N;printf("请输入元素(每个元素之间空格分开,最后一个元素输入后直接换行):");do{scanf("%d", &e);N = (StackNode*)malloc(sizeof(StackNode)); //创建结点申请内存空间if (N == NULL) //判断申请内存空间是否成功{printf("申请内存空间失败,无法继续创建结点!"); //输出提示语return ERROR;}N->data = e; //将e的值赋值给结点N的数据域N->next = S->top; //由于链栈的栈顶在链头,所以入栈操作,插入的新结点的指针域要指向原来的栈顶S->top = N; //将N结点成为栈顶S->count++; //链栈长度加一} while(getchar()!='\n'); //判断为换行时 输入结束printf("所有元素入栈成功!\n");return OK;
}//压栈(与链表的头插操作相似)
Status Push(LinkStack *S, SElemType e){LinkStackPrt p = (LinkStackPrt)malloc(sizeof(StackNode));p->data = e;p->next = S->top;    //把当前的栈顶元素赋值给新节点的直接后继S->top = p; //将新的结点S赋值给栈顶指针S->count++;return OK;
}//判断栈是否为空
bool StackEmpty(LinkStack *S)
{if (S->count == -1) //判断是否为空栈{return true;}return false;
}/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
//弹栈(与链表的头删操作相似)
Status Pop(LinkStack *S, SElemType *e){LinkStackPrt p;if(StackEmpty(S)){return ERROR;}*e = S->top->data;p = S->top; //将栈顶结点赋值给pS->top = S->top->next;  //使得栈顶指针下移一位,指向后一结点free(p);    //释放结点pS->count--;return OK;
}//输出链栈的元素个数
Status LengthLinkStack(LinkStack *S)
{if (S->count == -1) //判断链栈是否为空栈{printf("链栈为空栈,元素个数为零!\n"); return ERROR;}printf("链栈的元素个数为:%d\n", S->count + 1); return OK;
}//输出栈顶元素
Status OutTop(LinkStack *S)
{if (S->count == -1) //判断链栈是否为空栈{printf("链栈为空栈,没有栈顶元素!\n"); //输出提示语return ERROR;}printf("链栈的栈顶元素为:%d\n", S->top->data); //输出链栈栈顶元素的值return OK;
}
//输出链栈各个元素
Status OutValue(LinkStack *S)
{StackNode *N;int i = 1;if (S->count == -1) //判断是否为空栈{printf("链栈为空栈,没有元素可输出!\n"); //输出提示语return ERROR;}N = S->top; //将栈顶指针赋值给Ndo{printf("第%d个元素为:%d\n", i++, N->data);N = N->next; //N指向下一个结点} while (N != NULL);printf("所有元素按照从栈顶到栈底的顺序完毕!\n"); //输出提示语return OK;
}
//销毁链栈
Status ClearStack(LinkStack *S)
{StackNode *N;if (S->count == -1) //判断链栈是否为空栈{printf("链栈为空栈,不用清空,请勿重复执行此功能!\n");return ERROR;}do{N = S->top; S->top = N->next; //栈顶指针指向N结点的下一个结点 free(N); //释放N所指向的内存空间} while (S->top != NULL); //最后一个结点的指针域指向NULLfree(S->top); //释放最后一个结点S->count = -1; //链栈长度置为-1printf("链栈清空成功!\n"); //输出提示语return OK;
}

代码测试:


int main()
{LinkStack *S;SElemType e;InitLinkStack(&S);//初始化链栈CreateLinkStack(S); //建立链栈LengthLinkStack(S);  //输出链栈的元素个数OutTop(S); //输出链栈栈顶元素//插入指定元素到栈顶printf("要插入的元素的值为:");scanf("%d", &e);Push(S, e);//删除栈顶元素if (Pop(S, &e)){printf("删除成功!\n删除的栈顶元素的值为:%d\n", e);}OutValue(S);  //输出链栈各个元素ClearStack(S);  //清空链栈//链栈是否为空if (StackEmpty(S)){printf("栈为空栈!\n");}else{printf("栈不为空!\n");}free(S);//释放Sreturn 0;
}

 

 二.队列

1.队列的基本概念

队列是一种常用的数据结构,它具有先进先出(FIFO)的特点。

1. 队头:队列的第一个元素。
2. 队尾:队列的最后一个元素。
3. 入队:将一个元素加入到队列的末尾。
4. 出队:从队列的头部删除一个元素。
5. 队列长度:队列中元素的个数。

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 
bool QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

3.队列的储存结构

①队列的链式储存

(1)基本概念

链队列:采用链式存储结构实现的队列。通常链队列用单链表来表示。一个链队列显然需要两个分别指示队头和队尾的指针(分别称为头指针和尾指针)才能唯一确定。这里和线性表的单链表一样,为了操作方便起见,给链队列添加一个头结点,并令头指针始终指向头结点。

 (2)代码实现

存储结构:

// 链式结构:表示队列 
typedef struct QListNode
{QDataType _data;struct QListNode* _next;
}QNode;// 队列的结构 
typedef struct Queue
{QNode* _front;QNode* _rear;int size;
}Queue;

 基本操作:

#include<assert.h>
#include<stdlib.h>
#include<stdio.h>
#include<stdbool.h>
// 初始化队列 
void QueueInit(Queue* q)
{q->_front = NULL;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)
{if (!QueueEmpty(q)){q->_front = q->_front->_next;}
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{assert(q && q->_front);return q->_front->_data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{assert(q && q->_rear);return q->_rear->_data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* q)
{if (q->size==0){return true;}return false;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{while (q->_front){QNode* p = q->_front;q->_front = q->_front->_next;free(p);p = NULL;}q->_front = q->_rear = NULL;
}

代码测试:

int main()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);printf("有%d个元素\n", QueueSize(&q));printf("%d ", QueueFront(&q));QueuePop(&q);printf("%d ", QueueFront(&q));QueuePop(&q);printf("%d ", QueueFront(&q));QueuePop(&q);printf("%d ", QueueFront(&q));QueuePop(&q);QueueDestroy(&q);return 0;
}

 

②循环队列

(1)基本概念

循环队列:是将数组的首尾相连,组成的一个特殊结构。头、尾指针以及队列元素之间的关系不变,只是在循环队列中,头、尾指针“依环状增1"的操作可用“模”运算来实现。通过取模,头指针和尾指针就可以在顺序表空间内以头尾衔接的方式“循环”移动。 

 (2)代码实现

储存结构:

typedef struct {int* st;int length, top, tail;
} MyCircularQueue;

基本操作:


#include <stdio.h>
#include <stdlib.h>#define OK 1
#define ERROR 0
#define OVERFLOW -1#define MAXSIZE 7bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
//循环队列的创建
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* obj = (MyCircularQueue*) malloc(sizeof(MyCircularQueue));obj->st = (int*) malloc(sizeof(int) * k);obj->top = 0;obj->tail = 0;obj->length = k;return obj;
}
//循环队列入队
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {if (myCircularQueueIsFull(obj)) return false;obj->st[obj->top] = value;obj->top = (obj->top + 1) % obj->length;return true;
}
//循环队列出队
bool myCircularQueueDeQueue(MyCircularQueue* obj) {if (myCircularQueueIsEmpty(obj)) return false;obj->tail = (obj->tail + 1) % obj->length;return true;
}
//求队头元素
int myCircularQueueFront(MyCircularQueue* obj) {return myCircularQueueIsEmpty(obj) ? -1 : obj->st[obj->tail];
}
//求队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {return myCircularQueueIsEmpty(obj) ? -1 : obj->st[(obj->top + obj->length - 1) % obj->length];
}
//循环队列的判空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->top == obj->tail;
}
//循环队列的判满
bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->top + 1) % obj->length == obj->tail;
}
//销毁
void myCircularQueueFree(MyCircularQueue* obj) {free(obj->st);free(obj);
}

代码测试:


int main() {MyCircularQueue *sq;//循环队列的创建 sq=myCircularQueueCreate(MAXSIZE);//入队 myCircularQueueEnQueue(sq, 1);myCircularQueueEnQueue(sq, 2);myCircularQueueEnQueue(sq, 3);myCircularQueueEnQueue(sq, 4);int rEnQueue = myCircularQueueEnQueue(sq, 5);if (rEnQueue == OK) {printf("向循环队列入队成功!\n");} else {printf("向循环队列入队失败!\n");}//输出链表元素DisplayQueue(sq);printf("\n");//出队 int rDeQueue = myCircularQueueDeQueue(sq);if (rDeQueue == OK) {printf("向循环队列出队成功!\n");} else {printf("向循环队列出队失败!\n");}//输出链表元素DisplayQueue(sq);printf("\n");//求队头元素int topData = myCircularQueueFront(sq);printf("向循环队列获取队头元素:%d\n", topData);//求队尾元素int tailData = myCircularQueueRear(sq);printf("向循环队列获取队头元素:%d\n", tailData);//判空bool ClearStatus = myCircularQueueIsEmpty(sq);if (ClearStatus == true) {printf("循环队列为空!\n\n");}else {printf("循环队列不为空!\n\n");}//销毁 myCircularQueueFree(sq);return 1;
}

 

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

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

相关文章

Spring MVC+mybatis 项目入门:旅游网(一)项目创建与准备

个人博客&#xff1a;Spring MVCmybatis 项目入门:旅游网&#xff08;一&#xff09;项目创建与准备 | iwtss blog 先看这个&#xff01; 这是18年的文章&#xff0c;回收站里恢复的&#xff0c;现阶段看基本是没有参考意义的&#xff0c;技术老旧脱离时代&#xff08;2024年辣…

从0开始学统计-卡方检验

1.什么是卡方检验&#xff1f; 卡方检验是一种用于检验观察频数与期望频数之间差异的统计方法。它通常用于分析分类变量之间的关联性或独立性。在卡方检验中&#xff0c;我们将观察到的频数与期望频数进行比较&#xff0c;从而确定它们之间的差异是否显著。 卡方检验的基本思…

【机器学习与大模型】驱动下的应用图像识别与处理

摘要&#xff1a; 本文深入探讨了机器学习在图像识别与处理领域的应用&#xff0c;特别是在大模型的推动下所取得的巨大进展。详细阐述了图像识别与处理的基本原理、关键技术&#xff0c;以及机器学习算法和大模型如何提升其性能和准确性。通过实际案例分析了其在多个领域的广泛…

虚机配置USB CDROM设备热迁移crash

虚机配置USB CDROM设备热迁移crash 问题现象定位过程堆栈分析日志分析打开trace异常日志上下文分析SpecificationCBWCSW 命令执行发送读命令读取数据 正常日志异常堆栈 修复方案结论 基础原理设备模型数据结构设备实例化 UHCIFrame ListTDQH SCSI 问题现象 dogfood环境一台虚机…

夏日炎炎,手机如何避免变成热源?这些降温技巧分享给你

夏日炎炎&#xff0c;手机也容易“中暑”。 高温不仅会让手机性能大打折扣&#xff0c;还可能引发安全隐患。因此&#xff0c;如何让手机在高温下“冷静”下来&#xff0c;成为了许多手机用户关心的问题。 本文将为你提供一些实用的降温技巧&#xff0c;帮助你的手机安全度过…

小猪APP分发:一站式免费应用推广解决方案

在竞争激烈的移动应用市场中&#xff0c;寻找一个高效且成本友好的方式来推广自己的应用程序&#xff0c;成为了众多开发者面临的共同挑战。幸运的是&#xff0c;像"小猪APP分发www.appzhu.cn"这样的平台应运而生&#xff0c;为开发者提供了一个全面、免费的应用分发…

(优作)风力摆控制系统

本系统由瑞萨 100LGA 单片机控制模块&#xff0c; 6050 三轴陀螺仪加速度模块&#xff0c;直流风机及其驱 动模块&#xff0c;显示模块&#xff0c;键盘模块&#xff0c;蜂鸣器模块以及风力摆机械结构组成&#xff0c; MPU6050 采集风摆姿 态&#xff0c;单片机处理姿态数…

RHCSA —— 第一节 (简介)

目录 一、红帽 RedHat Linux 二、计算机 三、操作系统 四、Linux 入门 一、红帽 RedHat Linux RHCSA英文全称&#xff1a;Red Hat Certified System Administrator &#xff0c;中文全称&#xff1a;红帽认证系统管理员 RHCE英文全称&#xff1a;Red Hat Certified Engi…

软件系统部署方案(Word原版文件)

一、 引言 &#xff08;一&#xff09; 编写目的 二、 外部设计 &#xff08;一&#xff09; 标识符和状态 &#xff08;二&#xff09; 约定 1&#xff0e; 数据库涉及字符规范 2&#xff0e; 字段命名规范 &#xff08;三&#xff09; 专门指导 &#xff08;四&#…

C++初阶之模板进阶

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 算法 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 目录 一.非类型模板参数 二.模板的特化 2.1引入 2.2全特化 2.3…

八、函数和数组

8.1 函数 函数几乎是学习所有的程序设计语言时都必须过的一关。对于学习过其他的程序语言的用户来说&#xff0c;函数可能并不陌生。但是Shell中的函数与其他的程序设计语言的函数有许多不同之处。 8.1.1什么是函数 通俗地讲&#xff0c;所谓函数就是将一组功能相对独立的代码…

记忆力和人才测评,如何提升记忆力?

什么是记忆力&#xff1f; 如何通俗意义上的记忆力&#xff1f;我们可以把人的经历、经验理解成为一部纪录片&#xff0c;那么已经过去发生的事情&#xff0c;就是影片之前的情节&#xff0c;对于这些信息&#xff0c;在脑海里&#xff0c;人们会将其进行处理和组合&#xff…

SAP-CO成本控制概念之标准成本

“ 本篇介绍&#xff1a;标准成本的会计概念&#xff0c;标准成本的制定标准&#xff1b;通过结合会计标准成本的概念与SAP CO标准成本估算功能&#xff0c;更具象化的了解SAP如何实现标准成本管理&#xff0c;为后续学习SAP实际成本核算打下基础。” 01 — 背景需求 SAP实施…

2024年春招高薪职业报告:大模型算法研究员领跑

近日&#xff0c;脉脉高聘发布的研究报告《2024春招高薪职业和人才洞察》&#xff08;以下简称《洞察》&#xff09;显示&#xff0c;2024年一季度&#xff0c;大模型算法研究员新发岗位以平均月薪6.4万元领跑高薪岗位榜。受人才培养周期和技术门槛影响&#xff0c;人工智能行业…

机器学习大模型驱动:未来的趋势与应用

文章目录 &#x1f4d1;前言一、什么是机器学习大模型&#xff1f;1.1 大模型的特点1.2 大模型的技术基础 二、大模型的技术实现2.1 Transformer 架构2.2 预训练和微调2.3 模型并行和数据并行 三、大模型的应用场景3.1 自然语言处理&#xff08;NLP&#xff09;3.2 计算机视觉&…

vue3 使用css实现一个弧形选中角标样式

文章目录 1. 实现效果2. 实现demo 在前端开发中&#xff0c;ui同学经常会设计这样的样式&#xff0c;用于区分选中的状态 下面抽空简单些了一下&#xff0c;记录下&#xff0c;后面直接复制用 1. 实现效果 实现一个菜单切换&#xff0c;右下角有个角标的样式 2. 实现demo 主要…

Java进阶学习笔记20——枚举

认识枚举&#xff1a; 枚举是一种特殊的类。 枚举类的格式&#xff1a; 说明&#xff1a; 第一行是罗列枚举的对象名称。只能写合法的标识符&#xff08;名称&#xff09;&#xff0c;多个名称用逗号隔开。 这些名称本质上都是常量&#xff0c;每个变量都会记住枚举类的一个…

Optica数据库 (原OSA美国光学学会电子期刊)文献去哪里查找下载

Optica&#xff08;OSA&#xff09;数据库涵盖了光学和光子学理论研究和实际应用的各个领域&#xff0c;包括&#xff1a;光学设备、光学成像、光纤通信、分析方法、光通信、光纤、半导体激光、光传输、光学系统、计量学、带宽、量子电子学。 该库包括18种学会期刊&#xff08…

MVCC 原理分析、MySQL是如何解决幻读的

文章目录 一、前言回顾1.1 事务四大特性ACID1.2 并发事务问题1.3 事务隔离级别 二、MVCC2.1 为什么使用MVCC2.2 基本概念——当前读、快照读、MVCC2.2.1 当前读2.2.2 快照读2.2.3 MVCC 2.3 隐藏字段—— TRX_ID、ROLL_PTR2.4 undo log2.4.1 介绍2.4.2 版本链 2.5 Read View读视…

python写接口性能测试

import time import requestsdef measure_response_time(api_url):try:start_time time.time()response requests.get(api_url, timeout10) # 设置超时时间为10秒end_time time.time()response_time end_time - start_timeprint(f"接口 {api_url} 的响应时间为&#…