【数据结构】栈和队列详解&&栈和队列实现

主页:醋溜马桶圈-CSDN博客

专栏:数据结构_醋溜马桶圈的博客-CSDN博客

gitee:mnxcc (mnxcc) - Gitee.com

目录

1.数组栈的实现

1.1 栈的概念及结构

1.2 栈的实现

1.2.1 创建栈

1.2.2 初始化

1.2.3 销毁

1.2.4 入栈

1.2.5 出栈

1.2.6 返回栈顶元素

1.2.7 判空

1.2.8 栈的元素个数

1.3 实现代码

1.3.1 Stack.h

1.3.2 Stack.c

2.队列的实现 

2.1 队列的概念及结构

​编辑2.2 队列的实现

2.2.1 创建一个队列

2.2.2 初始化

2.2.3 销毁

2.2.4 入队列

2.2.5 出队列

2.2.6 取队列头数据

2.2.7 取队列尾数据

2.2.8 判空

2.2.9 返回队列有效元素个数

2.2.10 访问

2.3 实现代码 

2.3.1 Queue.h

2.3.2 Queue.c


1.数组栈的实现

1.1 栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作

进行数据插入和删除操作的一端称为栈顶,另一端称为栈底

栈中的数据元素遵守后进先出LIFO,(Last In First Out)的原则

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

Stack的Push和Pop遵循后进显先出原则

1.2 栈的实现

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

1.2.1 创建栈

我们还是用结构体来作为栈的每一个单独的数据块

1.2.2 初始化

这里我们给top赋什么值得认真考虑,需要给0吗?

如果top初始化为0,那么就会出现歧义:top==0是有一个元素还是空

所以,如果top指向栈顶元素,需要给top=-1才能区分

 如果top指向栈顶元素的下一个位置,那么给top初始化为0就可以了

两种方式在初始化的时候会有区别:

  • 如果top指向栈顶元素,top=-1:
    push:
    ++top;
    a[top]=x;
  • 如果top指向栈顶元素的下一个,top=0:
    push:
    a[top]=x;
    ++top;

我们这里初始化的时候就初始化为0,top就是元素个数:

1.2.3 销毁

1.2.4 入栈

由于top我们初始化为0,这里我们入栈的时候就需要先给值,再++:

1.2.5 出栈

出栈就很简单了:

入栈顺序和出栈顺序是一对多的关系

一种入栈顺序可能会有多种出栈顺序,而一种出栈顺序只对应一种入栈顺序:

1.2.6 返回栈顶元素

1.2.7 判空

或者更简单的写法:

1.2.8 栈的元素个数

1.3 实现代码

1.3.1 Stack.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;//标识栈顶位置
	int capacity;
}ST;
//初始化
void STInit(ST* pst);
//销毁
void STDestroy(ST* pst);
//入栈
void STPush(ST* pst, STDataType x);
//出栈
void STPop(ST* pst);
//返回栈顶元素
STDataType STTop(ST* pst);
//判空
bool STEmpty(ST* pst);
//栈的元素个数
int STSize(ST* pst);

1.3.2 Stack.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
//初始化
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;
}
//销毁
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}
//入栈
void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType * )realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
//出栈
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	pst->top--;
}
//返回栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst -> a[pst->top - 1];
}
//判空
bool STEmpty(ST* pst)
{
	assert(pst);
	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return pst->top == 0;
}
//栈的元素个数
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

2.队列的实现 

2.1 队列的概念及结构

队列:只允许在一端进行插入数据操作在另一端进行删除数据操作特殊线性表,队列具有先进先出 FIFO(First In First Out)

  • 入队列:进行插入操作的一端称为队尾
  • 出队列:进行删除操作的一端称为队头

2.2 队列的实现

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

我们可以用单链表来实现:

2.2.1 创建一个队列

先创建一个结构体封装数据之间的关系

再创建一个结构体封装队列的头和尾

2.2.2 初始化

2.2.3 销毁

2.2.4 入队列

2.2.5 出队列

2.2.6 取队列头数据

2.2.7 取队列尾数据

2.2.8 判空

2.2.9 返回队列有效元素个数

2.2.10 访问

当队列不为空的时候,访问队头数据,访问一个pop一个

2.3 实现代码 

2.3.1 Queue.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
//创建
typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;
//把队列的头尾封装在一个结构体中

//初始化
void QInit(Queue* pq);
//销毁
void QDestroy(Queue* pq);

//入队列
void QPush(Queue* pq, QDataType x);
//出队列
void QPop(Queue* pq);
//取队头数据
QDataType QFront(Queue* pq);
//取队尾数据
QDataType QBack(Queue* pq);
//判空
bool QEmpty(Queue* pq);
//返回队列有效元素个数
int QSize(Queue* pq);

2.3.2 Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
//初始化
void QInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//销毁
void QDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//入队列
void QPush(Queue* pq, QDataType x)
{
	assert(pq);
	//创建newnode
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->val = x;
	newnode->next = NULL;
	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//出队列
void QPop(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	if (pq->phead == NULL)
	{
		pq->ptail = NULL;
		//防止ptail成为野指针
	}
	pq->size--;
}
//取队头数据
QDataType QFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->val;
}
//取队尾数据
QDataType QBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->val;
}
//判空
bool QEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}
//返回队列有效元素个数
int QSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}
  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

醋溜马桶圈

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

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

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

打赏作者

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

抵扣说明:

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

余额充值