数据结构之栈和队列及其实现

1.栈

  • 概念:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作,进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守先进后出原则。
  • 入栈和出栈示意图
    在这里插入图片描述
    在这里插入图片描述

(1.)实现栈需要的接口

// 静态栈的结构
typedef int STDataType;
#define N 10
typedef struct Stack
{
	STDataType _a[N];
	int _top;
}Stack;


// 动态栈的结构
typedef int STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top;
	int _capacity;
}Stack;
// 实现栈需要的接口
typedef int STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top;
	int _capacity;
}Stack;

void StackInit(Stack* ps);// 栈的初始化
void StackDestory(Stack* ps);// 栈的销毁

void StackPush(Stack* ps, STDataType x);// 数据的压栈
void StackPop(Stack* ps);// 出栈

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

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

size_t StackSize(Stack* ps);// 获取栈的大小
// 栈接口的实现

void StackInit(Stack* ps)
{
	// 栈的初始化
	assert(ps);
	ps->_a = NULL;
	ps->_top = 0;
	ps->_capacity = 0;
}
void StackDestory(Stack* ps)
{
	// 栈的销毁
	assert(ps);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
	free(ps->_a);
	ps = NULL;
}

void StackPush(Stack* ps, STDataType x)
{
	// 数据的压栈
	assert(ps);
	if (ps->_top == ps->_capacity)
	{
		int newcapacity = (ps->_capacity == 0) ? 2 : (ps->_capacity * 2);
		ps->_a = (STDataType*)realloc(ps->_a, newcapacity * sizeof(STDataType));
		ps->_capacity = newcapacity;
	}
	ps->_a[ps->_top] = x;
	++ps->_top;
}
void StackPop(Stack* ps)
{
	// 出栈
	assert(ps && ps->_top > 0);
	--ps->_top;
}

STDataType StackTop(Stack* ps)
{
	// 获取栈顶元素
	assert(ps && ps->_top > 0);
	return ps->_a[ps->_top - 1];
}

bool StackEmpty(Stack* ps)
{
	// 判断栈是否为空
	assert(ps);
	return ps->_top == 0;
}

size_t StackSize(Stack* ps)
{
	// 获取栈的大小
	assert(ps);
	return ps->_top;
}

2.队列

  • 概念:只允许一端进行插入数据操作,在另一端进行删除操作的特殊线性表,队列具有先进先出的原则。
  • 队尾:进行插入数据的操作。
  • 队头:进行删除数据的操作。
  • 队列可以用数组和链表的结构实现,但是用链表结构实现更优一些,因为如果使用数组结构,出队列在数组首部上出数据,效率会比较高。
  • 入队和出队示意图
    在这里插入图片描述

(1.)实现队列需要的接口

// 队列的结构
typedef int QUDataType;

// 队列结点的结构(链表)
typedef struct QueueNode
{
	struct QueueNode* _next;
	QUDataType _data;
}QueueNode;

typedef struct Queue
{
	QueueNode* _front;// 队头
	QueueNode* _rear;// 队尾
}Queue;
// 实现队列需要的接口
void QueueInit(Queue* pq);// 队列的初始化
void QueueDestory(Queue* pq);// 队列的销毁

QueueNode* BuyQueueNode(QUDataType x);// 创建一个新的结点
void QueuePush(Queue* pq, QUDataType x);// 入队(从队头入队)
void QueuePop(Queue* pq);// 出队(从队尾出队)

QUDataType QueueFront(Queue* pq);// 取队头元素
QUDataType QueueRear(Queue* pq);// 取队尾元素

bool QueueEmpty(Queue* pq);// 判断队列是否为空

int QueueSize(Queue* pq);// 获取队列的大小

(2.)队列接口的实现

// 队列接口的实现
void QueueInit(Queue* pq)
{
	// 队列的初始化
	assert(pq);
	pq->_front = pq->_rear = NULL;
}
void QueueDestory(Queue* pq)
{
	// 队列的销毁
	assert(pq);
	QueueNode* cur = pq->_front;
	while (cur)
	{
		QueueNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	pq->_front = pq->_rear = NULL;
}

QueueNode* BuyQueueNode(QUDataType x)
{
	// 创建一个新的结点
	QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
	node->_next = NULL;
	node->_data = x;

	return node;
}
void QueuePush(Queue* pq, QUDataType x)
{
	// 入队(从队尾入队)
	assert(pq);
	QueueNode* node = BuyQueueNode(x);
	if (pq->_rear == NULL)
	{
		pq->_front = pq->_rear = node;
	}
	else
	{
		pq->_rear->_next = node;
		pq->_rear = node;
	}
}
void QueuePop(Queue* pq)
{
	// 出队(从队头出队)
	assert(pq && pq->_front != NULL);
	QueueNode* next = pq->_front->_next;
	free(pq->_front);
	pq->_front = next;
	if (pq->_front == NULL)
		pq->_rear = NULL;
}

QUDataType QueueFront(Queue* pq)
{
	// 取队头元素
	assert(pq && pq->_front != NULL);
	return pq->_front->_data;
}
QUDataType QueueRear(Queue* pq)
{
	// 取队尾元素
	assert(pq && pq->_rear != NULL);
	return pq->_rear->_data;
}

bool QueueEmpty(Queue* pq)
{
	// 判断队列是否为空
	assert(pq);
	return pq->_front == NULL;
}

int QueueSize(Queue* pq)
{
	// 获取队列的大小
	assert(pq);
	QueueNode* cur = pq->_front;
	size_t size = 0;
	while (cur)
	{
		++size;
		cur = cur->_next;
	}

	return size;
}

3.环形队列

  • 环形队列就是一种循环队列,可以用数组实现。
    在这里插入图片描述

  • 循环队列判空的条件:Q.rear == Q.front

  • 循环队列判满的条件:Q.rear + 1 == Q.front

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值