数据结构———栈和队列(万字超详细总结,建议收藏)

本文详尽阐述了数据结构中的栈和队列。从栈的基本概念、操作,包括栈的初始化、插入、出栈等,到队列的概念、常见操作,如循环队列的实现和双端队列的概念,全方位解析了这两个重要的数据结构。
摘要由CSDN通过智能技术生成

目录

知识框架

栈的基本概念

栈的操作

 手撕栈

栈初始化

插入

出栈

获取栈顶元素

判断栈是否为空

获取栈的有效元素个数

销毁栈

完整代码 

测试结果

队列

队列的概念

队列常见的操作

队列的顺序存储结构

队列的假溢出现象

循环队列

循环队列的实现

初始化

 判断循环队列是否为空

判断循环队列是否为满

 入队列

出队列

删除元素。

取队头数据

取尾数据

打印队列

 销毁队列

 运行结果

队列结构的选择

队列的链式存储结构

队列的实现

完整代码

 运行结果

 双端队列

双端队列的概念


知识框架

栈的基本概念

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

栈的操作

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

 手撕栈

对于栈的实现我们是要用链表好还是数组好呢?

使用数组:

优点:数据连续存储在栈区,比堆区不连续存储要缓存友好,显然速度也更快;另外数组一般属于高级语言语法中的基本类型,结构简单,有利于编译器做寄存器优化、常量折叠、无用代码精简等,优化完速度还要更快。

缺点:数组大小在编译期写死 (C99 有了可变数组,但实际上 VC 也并未支持,C++ 亦未能兼容这一特性),数组开多大你就只能存多少数据,超了就是越界;另栈区空间宝贵,利用数组结构实现的栈能存的数据显然没有利用链表结构能存的那么多。所以注定了数组封装的栈根本就不能应用于工程实践。

使用链表:优点缺点恰好就是以上反过来说。

实际工程中的方案:C++ STL (可以说是算法 & 数据结构模板库中的标杆) 默认采用的是用双端队列来封装栈。双端队列底层由多块不连续的缓冲区组成,但各个缓冲区内部元素连续。这样可以减少内存分配次数,降低内存碎片,提高缓存命中率,可以说综合了数组和链表的优点。

我们这边使用的场景比较简单所以我们先用数组来实现栈,在后面也会提到如何使用队列来封装栈,由浅入深。

栈初始化

typedef int STDataType;
struct Stack
{
	STDataType* p;
	int top;
	int capacity;
};
//初始化栈
void StackInit(Stack* ps)
{
	ps->p = (STDataType*)malloc(sizeof(Stack));
	ps->top = 0;
	ps->capacity = 4;
}

插入

一进来我们先判断空间是否足够,如果不够那么我们需要开辟空间

// 入栈
void StackPush(Stack* ps, STDataType data)
{
	if (ps->capacity == ps->top)
	{
		//增容
		Stack* tmp = realloc(ps->p, sizeof(Stack) * ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("ERROR:");
			exit(-1);
		}
		ps->p = tmp;
		tmp = NULL;
		ps->capacity *= 2;
	}
	ps->p[ps->top] = data;
	ps->top++;
}

出栈

// 出栈
void StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;

}

获取栈顶元素

// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->p[ps->top - 1];
}

判断栈是否为空

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps)
{
	return ps->top == 0;
	//空返回1;非空返会0;
}

获取栈的有效元素个数

// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
	return ps->top;

}

销毁栈

void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->p);
	ps->p = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

完整代码 

Stack.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int STDataType;
struct Stack
{
	STDataType* p;
	int top;
	int capacity;
};
typedef struct Stack Stack;

void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);

Stack.c

#include "stack.h"

//初始化栈
void StackInit(Stack* ps)
{
	ps->p = (STDataType*)malloc(sizeof(Stack));
	ps->top = 0;
	ps->capacity = 4;
}
// 入栈
void StackPush(Stack* ps, STDataType data)
{
	if (ps->capacity == ps->top)
	{
		//增容
		Stack* tmp = realloc(ps->p, sizeof(Stack) * ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("ERROR:");
			exit(-1);
		}
		ps->p = tmp;
		tmp = NULL;
		ps->capacity *= 2;
	}
	ps->p[ps->top] = data;
	ps->top++;
}
// 出栈
void StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;

}
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	r
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

善始善终!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值