数据结构:栈和队列的实现附上源代码(C语言版)

目录

前言

1.栈

1.1 栈的概念及结构

1.2 栈的底层数据结构选择

1.2 数据结构设计代码(栈的实现)

1.3 接口函数实现代码

(1)初始化栈

(2)销毁栈

(3)压栈

(4)出栈

(5)获取栈顶元素

(6)获取栈中有效元素的个数

(7)检测栈是否为空

1.4 测试函数

2. 队列

2.1 队列概念及结构

2.2 队列的底层数据结构的选择

2.2 数据结构设计代码(队列的实现)

2.3 接口函数

(1)初始化队列

(2)销毁队列

(3)队尾入队列

(4)队头出队列

(5)获取队列头部元素

(6)获取队列尾部元素

(7)获取队列中有效元素个数

(8)检测队列是否为空

2.4 测试函数

3. 栈和队列的源代码

3.1 栈

(1)Stack.h

(2)Stack.c

(3)STtest.c

3.2 队列

(1)Queue.h

(2)Queue.c

(3)Qtest.c

总结


前言

这篇文章是关于栈和队列的C语言实现,干货满满,大家可以边看边手写代码,最后附上栈和队列的参考代码。


1.栈

1.1 栈的概念及结构

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

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
出栈:栈的删除操作叫做出栈。出数据也在栈顶

这个数据结构可以理解为炸串。在最开始,插入丸子时,要插到这根签的最底部,就是入栈。开始吃的时候,一般从最上面的丸子入手,就是出栈

1.2 栈的底层数据结构选择

我们学过顺序表和链表两种数据结构,用那种会更好呢?

  • 相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。不用挪动数据,删除操作也很简单。
  • 而链表如果要入栈,就是链表的尾插,我们需要找到链表的尾结点,效率低。出栈也是一样。

1.2 数据结构设计代码(栈的实现)

在用C语言实现栈各种接口函数,需要创建三个文件,分别是STtest.c,Stack.c和Stack.h。

  • STtest.c文件用来测试接口函数是否能成功。
  • Stack.c文件里面放的是各种接口函数实现的代码
  • Stack.h文件放置各种头文件的声明,栈数据结构的设计和接口函数的声明。下面的代码就是放在此文件中。
typedef int STDataType;
// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
typedef int STDataType;
#define N 10
typedef struct Stack
{STDataType _a[N];int _top; // 栈顶
}Stack;// 支持动态增长的栈
typedef struct Stack
{STDataType* a;int top;      //栈顶int capacity; //容量
}ST;//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDataType StackTop(ST* ps);
//获取栈中有效元素个数
int StackSize(ST* ps);
//检测栈是否为空,为空返回true
bool StackEmpty(ST* ps);

1.3 接口函数实现代码

(1)初始化栈

初始化栈一开始要断言,断言来判断ps指针是否为空,如果为空会直接终止程序并给出提示,方便之后的调试,之后的断言不再赘述。指针指向空,内部整型数据赋值为0。但是top得注意,top其实也是个下标。看下面的注释,top可以有两种赋值方式,只是表示不同意思。

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

(2)销毁栈

因为我们是以数组为基础,是动态开辟的连续空间,直接释放掉ps中的数组指针,并要置为空。

void StackDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;//易错ps->top = ps->capacity = 0;
}

(3)压栈

栈的压栈操作跟顺序表的尾插类似,先要检查内部空间容量是否足够,一开始给四个该数据结构的空间,之后的按两倍来扩容。最后就是插入数据,栈顶减一。

void StackPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}ps->a = tmp;ps->capacity = newCapacity;}ps->a[ps->top] = x;ps->top++;
}

(4)出栈

这次不仅要判断ps是否不为空指针,还要判断栈内是否有元素,这样才可以删除元素,让栈顶减一即可。

void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));ps->top--;
}

(5)获取栈顶元素

这里的判断跟上个接口函数一样,只有栈内有元素,才能取栈顶元素。

STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top - 1];
}

(6)获取栈中有效元素的个数

此时的top表示的是栈顶的下一个元素的下标,刚好就是元素个数,直接返回栈顶top

int StackSize(ST* ps)
{assert(ps);return ps->top;
}

(7)检测栈是否为空

很多人会写个if语句判断,其实可以直接像下面一样写,ps->top == 0变成一个判断语句,如果为真返回一个部位0的数,如果为假返回0。

bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}

1.4 测试函数

我们写两个测试函数,第一个测试函数,是出栈和入栈的操作,可以调试查看。第二个测试函数是栈的数据打印,需要使用StackTop获取栈顶元素,然后将打印的数据出栈。

void TestStack1()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackDestroy(&st);
}void TestStack2()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}StackDestroy(&st);
}int main()
{TestStack1();TestStack2();return 0;
}

输出结果:

2. 队列

2.1 队列概念及结构

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

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

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

 这个数据结构可以理解为在银行取号,先取号的人,就是入队列。然后先取到号的人,就先去窗口处理业务,这就是出队列。

2.2 队列的底层数据结构的选择

跟栈一样,队列也可以用顺序表和链表来实现,那哪一个更好呢?

  • 相较于数组,使用链表更优一些。队列的入队和出队,分别是链表的尾插和头删,不过我们会创建两个指针指向头结点和尾结点,所以不会有时间的消耗。
  • 而数组在头部插入和删除数据,都要挪动数据,效率较低。

链表的数据结构存储的是一个数据变量,和指向下一个结点的指针变量。我们入队列和出队列分别在队尾和队头,所以我们在队列的数据结构定义两个链表的指针变量head和tail,表示队头和队尾

2.2 数据结构设计代码(队列的实现)

跟栈的实现一样,首先要创建三个文件Qtest.c,Queue.c和Queue.h。

  • Qtest.c文件用来测试接口函数是否能成功。
  • Queue.c文件里面放的是各种接口函数实现的代码
  • Queue.h文件放置各种头文件的声明,栈数据结构的设计和接口函数的声明。下面的代码就是放在此文件中。
// 链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QueueNode;// 队列的结构
typedef struct Queue
{QueueNode* head;QueueNode* tail;
}Queue;//初始化队列
void QueueInit(Queue* pq); 
//销毁队列
void QueueDestroy(Queue* pq);
//队尾入队列
void QueuePush(Queue* pq, QDataType x);
//队头出队列
void QueuePop(Queue* pq);
//获取队列头部元素
QDataType QueueFront(Queue* pq);
//获取队列尾部元素
QDataType QueueBack(Queue* pq);
//获取队列中有效元素个数
int QueueSize(Queue* pq);
//检测队列是否为空,如果为空返回true
bool QueueEmpty(Queue* pq);

2.3 接口函数

(1)初始化队列

队列初始化,只需要将队头链表指针和队尾链表指针置为空指针就好。

void QueueInit(Queue* pq)
{assert(pq);pq->head = NULL;pq->tail = NULL;
}

(2)销毁队列

因为是以链表为基础,需要用while循环释放掉每一个动态开辟的结点。

void QueueDestroy(Queue* pq)
{assert(pq);QueueNode* cur = pq->head;while (cur != NULL){QueueNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}

(3)队尾入队列

队尾入队列就是链表的尾插,但是我们有tail指针,直接在tail后面插入就好。不过需要分是否为空队列两种情况,如果是空队列,head和tail指针都指向新结点,如果不是空队列,在tail之后插入。

void QueuePush(Queue* pq, QDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("Queue malloc fail");return;}newnode->data = x;newnode->next = NULL;if (pq->head == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}
}

(4)队头出队列

在操作之前,我们需要判断队列是否有元素。然后在释放第一个结点,改变指针指向。

void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));QueueNode* next = pq->head->next;free(pq->head);pq->head = next;
}

(5)获取队列头部元素

QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}

(6)获取队列尾部元素

QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}

(7)获取队列中有效元素个数

这需要一个计数变量。

int QueueSize(Queue* pq)
{assert(pq);int n = 0;QueueNode* cur = pq->head;while (cur){n++;cur = cur->next;}return n;
}

(8)检测队列是否为空

跟栈判空相同。

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

2.4 测试函数

写两个测试函数,第一是入队列和出队列的操作,可以一步一步调试看情况。第二个测试函数,是打印队列里的数据,现获取队头的数据,然后再出队。

void TestQueue1()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePop(&q);QueuePop(&q);QueuePop(&q);QueuePop(&q);printf("%d\n", QueueBack(&q));QueueDestroy(&q);
}void TestQueue2()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)){QDataType front = QueueFront(&q);printf("%d ", front);QueuePop(&q);}printf("\n");
}int main()
{TestQueue1();TestQueue2();return 0;
}

输出的结果:

3. 栈和队列的源代码

3.1 栈

(1)Stack.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int STDataType;下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
//typedef int STDataType;
//#define N 10
//typedef struct Stack
//{
//	STDataType _a[N];
//	int _top; // 栈顶
//}Stack;// 支持动态增长的栈
typedef struct Stack
{STDataType* a;int top;      //栈顶int capacity; //容量
}ST;
//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDataType StackTop(ST* ps);
//获取栈中有效元素个数
int StackSize(ST* ps);
//检测栈是否为空,为空返回true
bool StackEmpty(ST* ps);

(2)Stack.c

#include "Stack.h"void StackInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = 0;//ps->top = -1ps->capacity = 0;
}void StackDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}void StackPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity){int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);}ps->a = tmp;ps->capacity = newCapacity;}ps->a[ps->top] = x;ps->top++;
}void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));ps->top--;
}STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top - 1];
}int StackSize(ST* ps)
{assert(ps);return ps->top;
}bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}

(3)STtest.c

#include "Stack.h"void TestStack1()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackDestroy(&st);
}void TestStack2()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);//printf("%d ", StackTop(&st));//StackPop(&st);//printf("%d ", StackTop(&st));//StackPop(&st);//StackPush(&st, 5);//StackPush(&st, 6);while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}StackDestroy(&st);
}int main()
{TestStack1();//TestStack2();return 0;
}

3.2 队列

(1)Queue.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>// 链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QueueNode;// 队列的结构
typedef struct Queue
{QueueNode* head;QueueNode* tail;
}Queue;//初始化队列
void QueueInit(Queue* pq); 
//销毁队列
void QueueDestroy(Queue* pq);
//队尾入队列
void QueuePush(Queue* pq, QDataType x);
//队头出队列
void QueuePop(Queue* pq);
//获取队列头部元素
QDataType QueueFront(Queue* pq);
//获取队列尾部元素
QDataType QueueBack(Queue* pq);
//获取队列中有效元素个数
int QueueSize(Queue* pq);
//检测队列是否为空,如果为空返回true
bool QueueEmpty(Queue* pq);

(2)Queue.c

#include "Queue.h"void QueueInit(Queue* pq)
{assert(pq);pq->head = NULL;pq->tail = NULL;
}void QueueDestroy(Queue* pq)
{assert(pq);QueueNode* cur = pq->head;while (cur != NULL){QueueNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}void QueuePush(Queue* pq, QDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("Queue malloc fail");return;}newnode->data = x;newnode->next = NULL;if (pq->head == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}
}void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));QueueNode* next = pq->head->next;free(pq->head);pq->head = next;
}QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}int QueueSize(Queue* pq)
{assert(pq);int n = 0;QueueNode* cur = pq->head;while (cur){n++;cur = cur->next;}return n;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

(3)Qtest.c

void TestQueue1()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePop(&q);QueuePop(&q);QueuePop(&q);QueuePop(&q);printf("%d\n", QueueBack(&q));QueueDestroy(&q);
}void TestQueue2()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)){QDataType front = QueueFront(&q);printf("%d ", front);QueuePop(&q);}printf("\n");
}int main()
{//TestQueue1();TestQueue2();return 0;
}


总结

栈和队列的实现其实相较于链表的实现简单一些,是因为其结构的特殊要求。之后会出一篇关于栈和队列的OJ题目。多多重复,百炼成钢!

创作不易,希望这篇文章能给你带来启发和帮助,如果喜欢这篇文章,请留下你的三连,你的支持的我最大的动力!!!

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

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

相关文章

金三银四求职攻略:如何在面试中脱颖而出

随着春天的脚步渐近&#xff0c;对于众多程序员来说&#xff0c;一年中最繁忙、最重要的时期也随之而来。金三银四&#xff0c;即三月和四月&#xff0c;被广大程序员视为求职的黄金时段。在这段时间里&#xff0c;各大公司纷纷开放招聘&#xff0c;求职者们则通过一场又一场的…

初阶数据结构之---栈和队列(C语言)

引言 在顺序表和链表那篇博客中提到过&#xff0c;栈和队列也属于线性表 线性表&#xff1a; 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构。线性表在逻辑上是线性结构&#xff0c;也就是说是连…

xxl-job--02--可视化界面各功能详细介绍

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 可视化界面1 新增执行器2.新增任务**执行器**&#xff1a;**任务描述**&#xff1a;**路由策略**&#xff1a;**Cron**&#xff1a;cron表达式**运行模式**JobHandl…

java Springboot vue 健身房系统,简单练手项目

该项目主要分为管理员和会员模块 管理员具有&#xff1a;会员管理&#xff0c;器材管理,员工管理&#xff0c;健身课程管理 会员模块&#xff0c;可以在线报名健身课程&#xff0c;查看自己课程 采用VUE前端开发和springboot后端开发&#xff0c;极简代码编写&#xff0c;没…

ubuntu20.04安装docker及运行

ubuntu20.04安装docker及运行 ubuntu环境版本 Ubuntu Focal 20.04 (LTS) 查看系统版本 rootubuntu20043:~# cat /proc/version Linux version 5.15.0-78-generic (builddlcy02-amd64-008) (gcc (Ubuntu 11.3.0-1ubuntu1~22.04.1) 11.3.0, GNU ld (GNU Binutils for Ubuntu) …

Vue(黑马学习笔记)

Vue概述 通过我们学习的htmlcssjs已经能够开发美观的页面了&#xff0c;但是开发的效率还有待提高&#xff0c;那么如何提高呢&#xff1f;我们先来分析下页面的组成。一个完整的html页面包括了视图和数据&#xff0c;数据是通过请求从后台获取的那么意味着我们需要将后台获取…

通过XML调用CAPL脚本进行测试(新手向)

目录 0 引言 1 XML简介 2 通过XML调用CAPL脚本 0 引言 纪念一下今天这个特殊日子&#xff0c;四年出现一次的29号。 在CANoe中做自动化测试常用的编程方法有CAPL和XML两种&#xff0c;二者各有各的特色&#xff0c;对于CAPL来说新手肯定是更熟悉一些&#xff0c;因为说到在C…

Vue开发实例(五)修改项目入口页面布局

修改项目入口 一、创建新入口二、分析代码&#xff0c;修改入口三、搭建项目主页面布局1、Container 布局容器介绍2、创建布局3、布局器铺满屏幕4、创建Header页面5、加入Aside、Main和Footer模块 一、创建新入口 创建新的入口&#xff0c;取消原来的HelloWorld入口 参考代码…

剑指offer刷题记录Day2 07.数组中重复的数字 ---> 11.旋转数组的最小数字

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、重建二叉树①代码实现&#xff08;带注释&am…

【重温设计模式】职责链模式及其Java示例

职责链模式的介绍 在开发过程中&#xff0c;我们经常会遇到这样的问题&#xff1a;一个请求需要经过多个对象的处理&#xff0c;但是我们并不知道具体由哪个对象来处理&#xff0c;或者说&#xff0c;我们希望由接收到请求的对象自己去决定如何处理或者是将请求传递给下一个对…

【深度学习笔记】计算机视觉——锚框

锚框 目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;ground-truth bounding box&#xff09;。 不同的模型使用的区域采样方法可能不同。 这里…

吴恩达deeplearning.ai:正则化对于偏方差的影响制定用于性能评估的基准

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai专栏 这节我们看看正则化系数 文章目录 以线性回归为例交叉验证误差对于确定 λ \lambda λ的作用 指定用于性能评估的基准语音识别的例子 以线性回归为例 让我们举一个例子&#xff1a; 模型&am…

Outlook邮箱IMAP密码怎么填写?账户设置?

Outlook邮箱IMAP密码是什么&#xff1f;Outlook如何设置IMAP&#xff1f; 许多用户会选择通过IMAP协议将邮箱与各种邮件客户端进行连接。而在设置过程中&#xff0c;填写IMAP密码是必不可少的一步。那么&#xff0c;Outlook邮箱的IMAP密码应该如何填写呢&#xff1f;接下来&am…

【Linux】深入理解ls命令

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 基本用法 常用选项 示例 高级用法 结语 我的其他博客 前言 在 Linux 系统中&#xff0c;ls 命令是一个强大而又基础的工具&am…

高刷显示器 - HKC VG253KM

&#x1f525;&#x1f525; 今天来给大家揭秘一款电竞神器 - HKC VG253KM 高刷电竞显示器&#xff01;这款显示器可是有着雄鹰展翅般的设计灵感&#xff0c;背后的大鹏展翅鹰翼图腾让人过目难忘。那么&#xff0c;这款显示器到底有哪些过人之处呢&#xff1f;一起来看看吧&…

【MySQL】基于Docker搭建MySQL一主二从集群

本文记录了搭建mysql一主二从集群&#xff0c;这样的一个集群master为可读写&#xff0c;slave为只读。过程中使用了docker&#xff0c;便于快速搭建单体mysql。 1&#xff0c;准备docker docker的安装可以参考之前基于yum安装docker的文章[1]。 容器相关命令[2]。 查看正在…

Pod和容器设计模式

为什么需要 Pod&#xff1b; Pod 的实现机制&#xff1b; 详解容器设计模式。 一、为什么需要 Pod 容器的基本概念 现在来看第一个问题&#xff1a;为什么需要 Pod&#xff1f;我们知道 Pod 是 Kubernetes 项目里面一个非常重要的概念&#xff0c;也是非常重要的一个原子调…

144. 二叉树的前序遍历

给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#xff1a;root [1] 输出&am…

SpringCloud(18)之Sleuth +Zipkin链路追踪

一、Zipkin介绍 Zipkin是一个开放源代码分布式的跟踪系统&#xff0c;它可以帮助收集服务的时间数据&#xff0c;以解决微服务架构中的延迟问 题&#xff0c;包括数据的收集、存储、查找和展现。每个服务向zipkin报告计时数据&#xff0c;zipkin会根据调用关系通 过Zipkin UI…

1.2 在卷积神经网络中,如何计算各层感受野的大小

1.2 在卷积神经网络中&#xff0c;如何计算各层感受野的大小 分析与解答&#xff1a; 在卷积神经网络中&#xff0c;由于卷积的局部连接性&#xff0c;输出特征图上的每个节点的取值&#xff0c;是由卷积核在输入特征图对应位置的局部区域内进行卷积而得到的&#xff0c;因此这…