栈和队列详解

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;
}
相关推荐
nongcunqq4 小时前
abap 操作 excel
java·数据库·excel
rain bye bye5 小时前
calibre LVS 跑不起来 就将setup 的LVS Option connect下的 connect all nets by name 打开。
服务器·数据库·lvs
我不是QI6 小时前
DES 加密算法:核心组件、加解密流程与安全特性
经验分享·算法·安全·网络安全·密码学
阿里云大数据AI技术6 小时前
云栖实录|MaxCompute全新升级:AI时代的原生数据仓库
大数据·数据库·云原生
前端小刘哥6 小时前
新版视频直播点播EasyDSS平台,让跨团队沟通高效又顺畅
算法
不剪发的Tony老师6 小时前
Valentina Studio:一款跨平台的数据库管理工具
数据库·sql
明月(Alioo)7 小时前
机器学习入门,无监督学习之K-Means聚类算法完全指南:面向Java开发者的Python实现详解
python·算法·机器学习
叶梅树7 小时前
从零构建A股量化交易工具:基于Qlib的全栈系统指南
前端·后端·算法
weixin_307779137 小时前
在 Microsoft Azure 上部署 ClickHouse 数据仓库:托管服务与自行部署的全面指南
开发语言·数据库·数据仓库·云计算·azure
lingran__7 小时前
算法沉淀第三天(统计二进制中1的个数 两个整数二进制位不同个数)
c++·算法