【数据结构】栈和队列

栈和队列

**栈:**一种特殊的数据结构,其只允许在固定的一段进行插入和删除元素的操作。进行数据插入和删除的一端叫栈顶,另一端叫栈底。栈中元素遵循后进先出的原则

栈在逻辑上是线性的物理 结构上也是线性的,属于线性表的一种

压栈:栈的插入数据操作叫做压栈,进栈,入栈,从栈顶进入

出栈:栈删除数据操作叫做出栈,从栈顶出

栈一般可以由数组和链表实现,相对而言,选用数组会比使用链表的代价小

选用数组来实现栈:

选择用双向链表来实现栈:相比较单链表,双向链表多出一个指针,在不同的操作系统下,指针的大小是不同的,32位:4字节,64位:8字节,而这些空间的消耗其实是没必要的。

选用单链表实现栈:相比于双向链表,单链表节省了的空间,但是,用单链表实现栈,在每次插入或者删除数据时,都需要进行内存的申请与释放操作,频繁的申请空间释放空间是会降低程序的效率的。

选用数组实现栈:用数组实现栈既解决了双向链表不必要的空间消耗问题也解决了频繁申请与释放空间的问题,虽然数组存在性能的消耗,但是相比较另外两种实现方式,这是最优的选择。

栈里面的数据不能被遍历也不能被随机访问,这是由栈的特性决定的(后进先出,只能在一端进行插入与删除操作)

栈的实现

首先,创建两个文件,一个是Stack.c文件,用来实现函数,一个是Stack.h文件,这里存放对应的头文件、栈的定义与函数的定义。

栈的定义

c 复制代码
typedef int STDataType;//当后面需求变更时,只需要修改int就行,比如要存储字符型,只需要把Int改成char就行。

typedef struct Stack
{
	STDataType* arr;
	int capacity;//栈空间的大小
	int top;//栈顶
}ST;

栈的初始化

c 复制代码
//.h文件下
void StackInit(ST*ps);//初始化栈
c 复制代码
//.c文件下
void StackInit(ST* ps)//初始化栈
{
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

栈的销毁

c 复制代码
//.h文件下
void StackDestroy(ST*ps);//栈的销毁
c 复制代码
//.c文件下
void StackDestroy(ST* ps)//栈的销毁
{
	assert(ps);
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

入栈

c 复制代码
//.h
void StackPush(ST*ps,STDataType x);//入栈
c 复制代码
void StackPush(ST* ps, STDataType x)//入栈
{
	assert(ps);
	if (ps->capacity==ps->top)//空间不足
	{//当空间大小与有效数据个数相同时表示栈空间用完了
		int newnode = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr,newnode*sizeof(STDataType));
		assert(tmp);
		ps->arr = tmp;
		ps->capacity = newnode; 
	}
	ps->arr[ps->top++] = x;
}

出栈

c 复制代码
//.h
bool StackEmpty(ST*ps);//判断栈是否位空]
void StackPop(ST*ps);//出栈
c 复制代码
//.c
bool StackEmpty(ST* ps)//判断栈是否位空
{
	assert(ps);
	return ps->top == 0;
}
void StackPop(ST* ps)//出栈
{
	assert(ps);
	assert(!StackEmpty(ps));//判断栈是否为空

	--ps->top;
}

获取栈顶元素与栈中有效元素个数

c 复制代码
//.h
STDataType StackTop(ST*ps);//获取栈顶元素

STDataType STSize(ST*ps);//获取有效元素个数
c 复制代码
//.h
STDataType StackTop(ST* ps)//获取栈顶元素
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->arr[ps->top-1];
}

STDataType STSize(ST* ps)//获取有效元素个数
{
	assert(ps);
	return ps->top;
}

完整代码

c 复制代码
//.h文件
#pragma once
#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 StackInit(ST*ps);//初始化栈
void StackDestroy(ST*ps);//栈的销毁

void StackPush(ST*ps,STDataType x);//入栈
void StackPop(ST*ps);//出栈
bool StackEmpty(ST*ps);//判断栈是否位空]

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

STDataType STSize(ST*ps);//获取有效元素个数
c 复制代码
//.c文件
#include"Stack.h"

void StackInit(ST* ps)//初始化栈
{
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

void StackDestroy(ST* ps)//栈的销毁
{
	assert(ps);
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}


void StackPush(ST* ps, STDataType x)//入栈
{
	assert(ps);
	if (ps->capacity==ps->top)//空间不足
	{
		int newnode = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr,newnode*sizeof(STDataType));
		assert(tmp);
		ps->arr = tmp;
		ps->capacity = newnode; 
	}
	ps->arr[ps->top++] = x;
}

void StackPop(ST* ps)//出栈
{
	assert(ps);
	assert(!StackEmpty(ps));

	--ps->top;
}

bool StackEmpty(ST* ps)//判断栈是否位空
{
	assert(ps);
	return ps->top == 0;
}

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

STDataType STSize(ST* ps)//获取有效元素个数
{
	assert(ps);
	return ps->top;
}

队列

队列:只允许在一段进行插入数据,在另一端进行插入数据的特殊线性表,队列,先进先出

底层由链表来实现,虽然数=数组也可以,但是数组效率低。完整代码如下:

c 复制代码
.c
#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);//队列插入数据
bool QueueEmpty(Queue*pq);//判断队列是否为空
void QueuePop(Queue*pq);//删除队列数据
QDataType QueueFront(QueueNode*pq);//取对头数据
QDataType QueueAfter(Queue* pq);//取队尾数据

int QueueSize(Queue*pq);//取有效数据个数

void QueueDestroy(Queue*pq);//队列的销毁
c 复制代码
.c
#include"Queue.h"

void QueueInit(Queue* pq)//队列初始化
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)//队列插入数据
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	assert(newnode);
	newnode->data = x;
	newnode->next = NULL;
	if (pq->phead==NULL)//队列为空
	{
		pq->phead = pq->ptail = newnode;
	}
	else//队列不为空
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

bool QueueEmpty(Queue* pq)//判断队列是否为空
{
	assert(pq);
	return pq->phead == NULL;
}
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;
}

QDataType QueueFront(Queue* pq)//取队头数据
{
	assert(pq);
	assert(!QueueEmpty(&pq));

	return pq->phead->data;
}

QDataType QueueAfter(Queue* pq)//取队尾数据
{
	assert(pq);
	assert(!QueueEmpty(&pq));

	return pq->ptail->data;
}

int QueueSize(Queue* pq)//取有效数据个数
{
	assert(pq);
	return pq->size;
}

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;
}
相关推荐
是小Y啦8 分钟前
leetcode 106.从中序与后续遍历序列构造二叉树
数据结构·算法·leetcode
万河归海42825 分钟前
C语言——二分法搜索数组中特定元素并返回下标
c语言·开发语言·数据结构·经验分享·笔记·算法·visualstudio
秋夫人2 小时前
B+树(B+TREE)索引
数据结构·算法
代码雕刻家2 小时前
数据结构-3.1.栈的基本概念
c语言·开发语言·数据结构
AlexMercer10123 小时前
【C++】二、数据类型 (同C)
c语言·开发语言·数据结构·c++·笔记·算法
^^为欢几何^^5 小时前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
ahauedu6 小时前
案例分析-Stream List 中取出值最大的前 5 个和最小的 5 个值
数据结构·list
X同学的开始7 小时前
数据结构之二叉树遍历
数据结构
AIAdvocate11 小时前
Pandas_数据结构详解
数据结构·python·pandas
jiao0000111 小时前
数据结构——队列
c语言·数据结构·算法