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

目录

一.栈

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; //链栈为空时,赋值为-1
	printf("初始化成功!\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; //将栈顶结点赋值给p
    S->top = S->top->next;  //使得栈顶指针下移一位,指向后一结点
    free(p);    //释放结点p
    S->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; //将栈顶指针赋值给N
	do
	{
		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); //最后一个结点的指针域指向NULL
	free(S->top); //释放最后一个结点
	S->count = -1; //链栈长度置为-1
	printf("链栈清空成功!\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);//释放S
	return 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 7
                        
bool 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;
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浅析3D NAND多层架构的可靠性问题

SSD的存储介质是什么&#xff0c;它就是NAND闪存。那你知道NAND闪存是怎么工作的吗&#xff1f;其实&#xff0c;它就是由很多个晶体管组成的。这些晶体管里面存储着电荷&#xff0c;代表着我们的二进制数据&#xff0c;要么是“0”&#xff0c;要么是“1”。 目前业内3D-NAND工…

【吊打面试官系列】Java高并发篇 - ReadWriteLock 是什么 ?

大家好&#xff0c;我是锋哥。今天分享关于 【ReadWriteLock 是什么 &#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; ReadWriteLock 是什么 &#xff1f; 首先明确一下&#xff0c;不是说 ReentrantLock 不好&#xff0c;只是 ReentrantLock 某些时候有局限。 …

【动态规划】斐波那契数列模型(C++)

目录 1137.第N个泰波那契数 解法&#xff08;动态规划&#xff09; 算法流程 1. 状态表⽰&#xff1a; 2. 状态转移⽅程&#xff1a; 3. 初始化&#xff1a; 4. 填表顺序&#xff1a; 5. 返回值&#xff1a; C算法代码 优化&#xff1a; 滚动数组 测试&#xff1a; …

bootstrap实现九宫格效果(猫捉老鼠游戏)

最近&#xff0c;孩子的幼儿园让家长体验“半日助教活动”&#xff0c;每个家长需要讲授15-20分钟的课程。作为一名程序员&#xff0c;实在没有能教的课程&#xff0c;只能做了一个小游戏&#xff0c;带着小朋友们熟悉数字。 效果大致是这样的。九宫格的左上角是一只小猫图片&…

一张图片中有多个一样的目标物体,分别进行识别定位分割(Python实现)

需求&#xff1a; 一张图片中有多个目标物体&#xff0c;将多个目标物体进行识别分割定位 import cv2 import numpy as npdef show_photo(name,picture):cv2.imshow(name,picture)cv2.waitKey(0)cv2.destroyAllWindows()img_path r"test3.png" img cv2.imread(img…

社交媒体数据恢复:聊天宝

请注意&#xff0c;本教程仅针对聊天宝应用程序&#xff0c;而非其他聊天软件。以下是详细的步骤&#xff1a; 首先&#xff0c;请确保您已经登录了聊天宝应用程序。如果您尚未登录&#xff0c;请使用您的账号登录。 在聊天宝主界面&#xff0c;找到您希望恢复聊天记录的对话框…

LeetCode - 数组 - 四数之和

题目地址 描述 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一对应&#xff0c;则认为两个四元组重复&#xff09;&#x…

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

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

[WUSTCTF2020]level3

base64换表 但是这的表有一个引用 模拟执行 #DRKCTF{}aABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/ flag[ord(i) for i in a] for i in range(0,10):flag[i],flag[19-i]flag[19-i],flag[i] for i in flag:print(chr(i),end)新表 TSRQPONMLKJIHGFEDCBAU…

技术速递|无障碍应用程序之旅:键盘可访问性和 .NET MAUI

作者&#xff1a;Rachel Kang 排版&#xff1a;Alan Wang 首先让我们一起来看看您的应用程序是否支持键盘访问&#xff1a; 启动您的其中一个应用。如果您的设备尚未连接物理键盘&#xff0c;请连接物理键盘。像平常一样导航您的应用程序&#xff0c;并且仅使用键盘来执行此操…

DI-engine强化学习入门(三)DI-ZOO强化学习环境搭建与示例运行——Atari

Atari是一家知名的电子游戏公司&#xff0c;成立于1972年&#xff0c;是早期电子游戏产业的先驱之一。在强化学习领域&#xff0c;提到Atari通常指的是Atari 2600游戏的一系列环境&#xff0c;这些环境是用于开发和测试强化学习算法的标准平台。 Atari 2600 强化学习环境概述 …

ABC354学习笔记

高桥有一棵植物&#xff0c;这个植物在第 0 0 0 天时高度为 0 c m 0\,\mathrm{cm} 0cm&#xff0c;此后的第 i i i 天&#xff0c;他的植物会增高 2 i c m 2^i\,\mathrm{cm} 2icm。 高桥身高为 H c m H\,\mathrm{cm} Hcm。 高桥想知道在第几天&#xff0c;他的植物的高度会…

Vue移动端登录页面

使用的是vant组件&#xff0c;引用和使用组件请去官网学习&#xff0c;链接↓vant组件官网 <div class"center"><!-- 背景图片 --><div class"background"><imgsrc"/assets/background.jpg"width"100%"heigh…

STL题单总结

下周争取全部刷掉 牛客 知乎推荐的题 收藏的文章1 收藏的文章2 收藏的文章3 洛谷题单

ICQ 将于 6 月关闭,这是一种奇怪的方式,发现它在 2024 年仍然活跃

你知道ICQ还活着吗&#xff1f;不过&#xff0c;不要太兴奋;它将永远消失。 还记得ICQ吗&#xff1f;如果你这样做了&#xff0c;你可能会记得它是AOL在1998年购买的Messenger客户端&#xff0c;就在Yahoo Instant Messager和MSN Messenger加入竞争的时候。然后Skype出现了&…

嵌入式全栈开发学习笔记---C语言笔试复习大全23

目录 联合体 联合体的定义 联合体的长度 如果来判断设备的字节序&#xff1f; 如何把大端数据转换成小端数据&#xff1f; 枚举 枚举的定义 上一篇复习了结构体&#xff0c;这一节复习联合体和枚举。 说明&#xff1a;我们学过单片机的一般都是有C语言基础的了&#xff…

【资讯】5月巴塞罗那,东胜物联边缘计算网关亮相IOTSWC AWS展台

2024年5月21-23日&#xff0c;物联网解决方案世界大会 IOT SWC 在巴塞罗那举行&#xff0c;这是数字化转型趋势和颠覆性技术的顶级盛会。 作为AWS的硬件合作伙伴&#xff0c;东胜物联网边缘计算网关DSGW-210将在AWS展台1号馆展出&#xff0c;欢迎大家前来参观。 此次东胜在AW…

【Linux】写时拷贝技术COW (copy-on-write)

文章目录 Linux写时拷贝技术(copy-on-write)进程的概念进程的定义进程和程序的区别PCB的内部构成 程序是如何被加载变成进程的&#xff1f;写时复制&#xff08;Copy-On-Write, COW&#xff09;写时复制机制的原理写时拷贝的场景 fork与COWvfork与fork Linux写时拷贝技术(copy-…

阿里云、百度云和移动云的对象存储横向性能对比

文章目录 前言一、对比测试的方法和标准A. 测试环境的设置 二、对比测试的结果A、阿里云OSS测试结果2.B. 百度云结果C. 移动云结果分析与结论 总结 前言 在企业的数字化转型进程中&#xff0c;我们观察到越来越多的公司将其IT基础设施迁移到云端。随着企业业务的持续运营&…

5.Redis之常用数据结构单线程模型

围绕每个数据结构介绍相关命令当前版本的redis支持10个数据类型 Redis 底层在实现上述数据结构的时候,会在源码层面,针对上述实现进行特定的优化,来达到 节省时间/节省空间 效果,内部的具体实现的数据结构&#xff08;编码方式&#xff09;,还会有变数redis 承诺,现在我这有个 …