数据结构——栈和队列

目录

一、栈的概念和结构

(1)栈

(2)压栈

(3)出栈

(4)栈的底层结构

二、栈的实现

1.Stack.h

2.Stack.c

(1)初始化

(2)销毁

(3)判断栈是否为空

(4)从栈顶入数据、出数据

[(5) 取栈顶元素](#(5) 取栈顶元素)

(6)栈有效元素的个数

3.text.c

三、队列的概念和结构

(1)队列

(2)入队列

(3)出队列

(4)队列的底层结构

四、队列的实现

1.Queue.h

2.Queue.c

(1)初始化

(2)队列判空

(3)从队尾入队列

(4)从队头出队列

(5)取队头数据

(6)取队尾数据

(7)队列有效元素个数

(8)销毁队列

五、写在最后


一、栈的概念和结构

(1)栈

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

进行插入和删除操作的一端为栈顶 ,另外一端为栈底;

栈中的数据元素遵守先进后出的原则。

(2)压栈

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

(3)出栈

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

(4)栈的底层结构

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

二、栈的实现

1.Stack.h

cpp 复制代码
#include <stdio.h>
#include <stdlib.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);

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

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

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

//栈有效元素的个数
int StackSize(ST* ps);

2.Stack.c

(1)初始化

cpp 复制代码
void STinit(ST* ps)
{
	assert(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 复制代码
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;//栈的有效数据为0,即栈为空
}

(4)从栈顶入数据、出数据

cpp 复制代码
void StackPush(ST* ps, STDatatype x)
{
	assert(ps);
	//判断空间是否足够
	if (ps->capacity == ps->top)
	{
		//不足,扩容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
        //创建中间变量,避免申请空间不成功
		STDatatype* tmp = (STDatatype*)realloc(ps->arr, sizeof(STDatatype) * newCapacity);
		//若申请不成功
        if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	ps->arr[ps->top] = x;
    //记得更改top
	ps->top++;
}

void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	--ps->top;
}

(5) 取栈顶元素

cpp 复制代码
STDatatype StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}

(6)栈有效元素的个数

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

3.text.c

cpp 复制代码
#include "Stack.h"
int main()
{
	ST st;
	STinit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	while (!StackEmpty(&st))
	{
		//打印栈顶元素
		STDatatype data = StackTop(&st);
		printf("%d ", data);
		//出栈
		StackPop(&st);
	}
	printf("size:%d\n", StackSize(&st));
	return 0;
}

三、队列的概念和结构

(1)队列

队列是一种特殊的线性表,只允许一端进行插入数据的操作,在另一端进行删除数据的操作;

队列的数据元素遵守先进先出的原则。

(2)入队列

进行插入操作的一端称为队尾

(3)出队列

进行删除操作的一端称为队头

(4)队列的底层结构

队列的实现可以使用数组或者链表,相对而言,链表的结构更优一些(因为如果使用数组的话,出队列在数组头上出数据,效率较低)。

四、队列的实现

1.Queue.h

cpp 复制代码
#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);
//队列判空
bool QueueEmpty(Queue* pq);
//从队尾入队列
void QueuePush(Queue* pq, QDatatype x);
//从队头出队列
void QueuePop(Queue* pq);
//取队头数据
QDatatype QueueFront(Queue* pq);
//取队尾数据
QDatatype QueueBack(Queue* pq);
//队列有效元素个数
int QueueSize(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);

2.Queue.c

(1)初始化

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

(2)队列判空

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

(3)从队尾入队列

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)
	if (QueueEmpty(pq))
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	++pq->size;
}

(4)从队头出队列

cpp 复制代码
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//如果只有一个数据
	if (pq->phead == pq->ptail)
	{
		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;
}

五、写在最后

当爱学习的你看到这里,肯定已经学会了栈和队列的实现,那么如何应用到题目中呢?

敬请期待:栈和队列的算法题~

相关推荐
小刘|11 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
jjyangyou16 分钟前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
van叶~32 分钟前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
简简单单做算法33 分钟前
基于Retinex算法的图像去雾matlab仿真
算法·matlab·图像去雾·retinex
云卓SKYDROID1 小时前
除草机器人算法以及技术详解!
算法·机器人·科普·高科技·云卓科技·算法技术
半盏茶香1 小时前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
徐子童1 小时前
双指针算法习题解答
算法
想要打 Acm 的小周同学呀1 小时前
LRU缓存算法
java·算法·缓存
劲夫学编程2 小时前
leetcode:杨辉三角
算法·leetcode·职场和发展
毕竟秋山澪2 小时前
孤岛的总面积(Dfs C#
算法·深度优先