栈和队列详解

1.栈

1.1概念与结构

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

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

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

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

1.2栈的实现

stack.h

cpp 复制代码
#pragma once
#include"stdio.h"
#include"stdio.h"
#include"assert.h"
#include<stdbool.h>

//定义栈的结构
typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int capacity;     //栈的空间大小
	int top;          //栈顶
}ST;

//初始化
void STInit(ST* ps);
//释放空间
void STDestroy(ST* ps);

//栈顶---入数据、出数据
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);

//取栈顶元素
STDataType StackTop(ST* ps);

//栈是否为空
bool StackEmpty(ST* ps);

//获取栈中有效元素个数
int STSize(ST* ps);

1.初始栈

cpp 复制代码
void STInit(ST* ps)
{
	asssert(ps);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

2.销毁栈

cpp 复制代码
void STDestroy(ST* ps)
{
	assert(ps);
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

3.入栈

cpp 复制代码
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//判断空间是否充足
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity = 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->capacity, newcapacity * sizeof(newcapacity));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	ps->arr[ps->top] = x;
	ps->top++;
}

4.判断栈是否为空

cpp 复制代码
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

5.出栈

cpp 复制代码
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	--ps->top;
}

6.取栈顶元素

cpp 复制代码
STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

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

7.获取栈中有效元素个数

cpp 复制代码
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

2.队列

2.1概念与结构

概念:只允许在一端进行插入数据操作,在另一端进行删除操作的特殊线性表,队列具有先进先出的原则。

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

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

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

2.2队列的实现

queue.h

cpp 复制代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

//定义队列结构
typedef int QDataType;
typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QueueNode;

typedef struct Queue
{
	QueueNode* phead;
	QueueNode* ptail;
	int size;//保存队列有效数据个数
}Queue;

//队列初始化
void QueueInit(Queue* pq);

// ⼊队列,队尾
void QueuePush(Queue* pq, QDataType x);
// 出队列,队头
void QueuePop(Queue* pq);

//队列判空
bool QueueEmpty(Queue* pq);

//取队头数据
QDataType QueueFront(Queue* pq);

//取队尾数据
QDataType QueueBack(Queue* pq);

//队列有效元素个数
int QueueSize(Queue* pq);

//销毁队列
void QueueDestroy(Queue* pq);

1.队列初始化

cpp 复制代码
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

2.从队尾入队列

cpp 复制代码
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;

	if (pq->phead = NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = pq->ptail->next;
	}
	pq->size++;
}

3.队列判空

cpp 复制代码
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL && pq->ptail == NULL;
}

4.从队头出队列

cpp 复制代码
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	if (pq->ptail == pq->phead)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QueueNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	--pq->size;
}

5.取队头数据

cpp 复制代码
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->phead->data;
}

6.取队尾数据

cpp 复制代码
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->ptail->data;
}

7.队列有效元素个数

cpp 复制代码
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

8.销毁队列

cpp 复制代码
void QueueDestroy(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	QueueNode* pcur = pq->phead;
	while (pcur)
	{
		QueueNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
相关推荐
SelectDB31 分钟前
让变更流出 Doris:Apache Doris 5.0 基于增量计算的 CDC 技术解析
数据库
这个DBA有点耶40 分钟前
MCP隔离层+行级语义审计+输出校验:AI访问数据库的安全边界拆解
数据库·人工智能·ai编程
好悬给我拽开线2 小时前
ZILOT 论文解析
算法
这个DBA有点耶2 小时前
从反向扫描O(n)到正向扫描O(1):降序索引的物理机制与混合排序匹配规则
数据库
饮水桶_T3 小时前
JAVA IO流笔记
开发语言·数据结构·算法
2501_933923253 小时前
解读Redis:单线程模型
数据库·redis·缓存
星夜离尘564 小时前
MATLAB 离散数据分箱:半开区间、末端点与计数、加权和、平均
算法·matlab
Pniubi4 小时前
力扣76.最小覆盖子串
算法·leetcode·职场和发展
Tapdata4 小时前
被忽略的第三类上下文:Agent 进入真实业务后,还缺什么?
数据库·人工智能·架构
地平线开发者4 小时前
征程6|用 hrt\_model\_exec 看清 YOLOv5x 的输入、原始输出和后处理
人工智能·算法