【数据结构】栈和队列

栈和队列

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

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

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

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

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

选用数组来实现栈:

选择用双向链表来实现栈:相比较单链表,双向链表多出一个指针,在不同的操作系统下,指针的大小是不同的,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;
}
相关推荐
ALISHENGYA10 分钟前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
武昌库里写JAVA3 小时前
浅谈怎样系统的准备前端面试
数据结构·vue.js·spring boot·算法·课程设计
S-X-S3 小时前
代码随想录刷题-数组
数据结构·算法
l138494274513 小时前
每日一题(4)
java·数据结构·算法
kyrie_sakura3 小时前
c++数据结构算法复习基础--13--基数算法
数据结构·c++·算法
XWXnb64 小时前
数据结构:顺序表
数据结构·算法
橘颂TA4 小时前
【C++】数据结构 顺序表的实现(详解)
开发语言·数据结构·c++·算法
R_.L4 小时前
数据结构:双向循坏链表
数据结构·链表
青春男大5 小时前
java哈希存储--数据结构
java·开发语言·数据结构·学习·算法·eclipse·哈希算法
ha20428941946 小时前
认识数据结构之——排序
数据结构·算法·排序算法