数据结构——栈和队列

目录

一、栈的概念和结构

(1)栈

(2)压栈

(3)出栈

(4)栈的底层结构

二、栈的实现

1.Stack.h

2.Stack.c

(1)初始化

(2)销毁

(3)判断栈是否为空

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

(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

#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)初始化

void STinit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

(2)销毁

void STDestroy(ST* ps)
{
	assert(ps);
    //释放之前判断不为空
	if (ps->arr)
	{
		free(ps->arr);
	}
    //释放之后要将指针置为空,否则再次使用会成为野指针
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

(3)判断栈是否为空

bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;//栈的有效数据为0,即栈为空
}

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

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) 取栈顶元素

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

(6)栈有效元素的个数

int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

3.text.c

#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

#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)初始化

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

(2)队列判空

bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}

(3)从队尾入队列

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)从队头出队列

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)取队头数据

QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));//队列不能为空!
	return pq->phead->data;
}

(6)取队尾数据

QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));//队列不能为空!
	return pq->ptail->data;
}

(7)队列有效元素个数

int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

(8)销毁队列

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;
}

五、写在最后

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

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

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值