栈和队列详解

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;
}
相关推荐
OK_boom2 小时前
Dapper的数据库操作备忘
数据库
艺杯羹3 小时前
JDBC之ORM思想及SQL注入
数据库·sql·jdbc·orm·sql注入
blackA_3 小时前
数据库MySQL学习——day4(更多查询操作与更新数据)
数据库·学习·mysql
ShiinaMashirol3 小时前
代码随想录打卡|Day27(合并区间、单调递增的数字、监控二叉树)
java·算法
极限实验室4 小时前
Easysearch 迁移数据之 Reindex From Remote
数据库
朴拙数科4 小时前
基于LangChain与Neo4j构建企业关系图谱的金融风控实施方案,结合工商数据、供应链记录及舆情数据,实现隐性关联识别与动态风险评估
数据库·langchain·neo4j
小李学不完5 小时前
Oracle--SQL事务操作与管理流程
数据库
qq_441996055 小时前
为何 RAG 向量存储应优先考虑 PostgreSQL + pgvector 而非 MySQL?
数据库·mysql·postgresql
Ivan陈哈哈5 小时前
Redis是单线程的,如何提高多核CPU的利用率?
数据库·redis·缓存
wuqingshun3141595 小时前
蓝桥杯 5. 交换瓶子
数据结构·c++·算法·职场和发展·蓝桥杯