c语言数据结构之栈和队列

c语言数据结构之栈和队列

1.栈的表示和实现

1.1 栈的概念及结构

:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除
操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)
的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
在这里插入图片描述
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/668aeef0131b40c1b7d7ff0c3d870b21.png pic_center
)

1.2 栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上
插入数据的代价比较小。
在这里插入图片描述
在这里插入图片描述
链式表:
如果用尾做栈顶,尾插尾删,要设计成双向链表,否则删除数据效率低.
如果用头做栈顶,头插头删,就可以设计成单链表。

1.3 代码实现

// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶
int _capacity;  // 容量 
}Stack;
// 初始化栈 
void StackInit(Stack* ps); 
// 入栈 
void StackPush(Stack* ps, STDataType data); 
// 出栈 
void StackPop(Stack* ps); 
// 获取栈顶元素 
STDataType StackTop(Stack* ps); 
// 获取栈中有效元素个数 
int StackSize(Stack* ps); 
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps); 
// 销毁栈 
void StackDestroy(Stack* ps); 

2.队列的表示和实现

2.1 队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先
进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一
端称为队头
在这里插入图片描述

2.2 队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,
出队列在数组头上出数据,效率会比较低。
在这里插入图我片描述

2.3 代码实现

typedef int QDataType;
// 链式结构:表示队列 
typedef struct QueueNode 
{ 
struct QListNode* next; 
QDataType data; 
}QNode; 
// 队列的结构 
typedef struct Queue 
{ 
QNode* head;  // 头部
QNode* tail;   // 尾部 
}Queue; 
// 初始化队列 
void QueueInit(Queue* pq); 
// 队尾入队列 
void QueuePush(Queue* pq, QDataType x); 
// 队头出队列 
void QueuePop(Queue* pq);

3.栈和队列相关的题

3.1 用队列实现栈

问题:
在这里插入图片描述
解决问题思路:

  • 首先明白栈是后进先出,队列是先进先出。
  • 有两个队列,入数据时,往不为空的队列入,保持另一个队列为空。
  • 出数据的时候,依次出队头的数据,转移到另一个队列保存。当本来不为空的队列只剩一个数据时,Pop掉。
    代码

代码实现:

// 用队列实现栈
typedef struct {
	Queue q1;
	Queue q2;
} MyStack;

MyStack* myStackCreate() {
	MyStack* st = (MyStack*)malloc(sizeof(MyStack));
	QueuInit(&st->q1);
	QueueInit(&st->q2);
	return st;
}

void myStackPush(MyStack* obj, int x) {
	if (!QueueEmpty(&obj->q1)) // 判断是否为空队列
	{
		QueuePush(&obj->q1, x);   // 往不为空的队列插入数据
	}
	else
	{
		QueuePush(&obj->q2, x);
	}
}

int myStackPop(MyStack* obj) {
	Queue* emptyQ = &obj->q1;     // 假设q1为空队列
	Queue* nonemptyQ = &obj->q2;
	if (!QueueEmpty(&obj->q1))   // 假设不成立时在重新赋值
	{
		emptyQ = &obj->q2;
		nonemptyQ = &obj->q1;
	}
	while (QueueSize(nonemptyQ) > 1)
	{
		QueuePush(emptyQ, QueueFront(nonemptyQ));
		QueuePop(nonemptyQ);
	}
	int top = QueueFront(nonemptyQ);
	QueueDestory(nonemptyQ);

	return top;
}

int myStackTop(MyStack* obj) {
	if (!QueueEmpty(&obj->q1))
	{
		return QueueBack(&obj->q1);
	}
	else
	{
		return QueueBack(&obj->q2);
	}
}

bool myStackEmpty(MyStack* obj) {
	return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) {
	QueueDestory(&obj->q1);
	QueueDestory(&obj->q2);
	free(obj);
}

3.2 用栈实现队列

问题:
在这里插入图片描述
解决问题思路:

  • 首先明白栈是后进先出,队列是先进先出。
  • 两个栈一个是pushST(存放数据),一个是popST来删除数据,把pushST栈中的数据全部移入到popST栈,就可以实现队列先进先出的删除了。同时返回popST中的栈顶数据。
    *实现peek函数, 如果popST栈中有数据返回popST中栈顶数据,如果没数据将pushST栈中的数据全部放到popST栈中后,再返回popST栈中栈顶的数据。

代码实现:

typedef struct {
	ST pushST;
	ST popST;
}MyQueue;

MyQueue* myQueueCreate() {
	MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
	StackInit(&q->popST);
	StackInit(&q->pushST);
	return q;
}

void myQueuePush(MyQueue* obj, int x) {
	StackPush(&obj->pushST,x);

}

int myQueuePop(MyQueue* obj) {
	if (StackEmpty(&obj->popST))  //如果popst中没有数>据,将pushst的数据导过去。
	{
		while (!StackEmpty(&obj->pushST))  
		{
			StackPush(&obj->popST, StackTop(&obj->pushST));
			StackPop(&obj->pushST);
		}
	}
	int front = StackTop(&obj->popST);
	StackPop(&obj->pushST);
	return front;
}

int myQueuePeek(MyQueue* obj) {
	if (StackEmpty(&obj->popST))  //如果popst中没有数>据,将pushst的数据导过去。
	{
		while (!StackEmpty(&obj->pushST))
		{
			StackPush(&obj->popST, StackTop(&obj->pushST));
			StackPop(&obj->pushST);
		}
	}
	return StackTop(&obj->popST);
}

bool myQueueEmpty(MyQueue* obj) {
	return StackEmpty(&obj->popST) && >StackEmpty(&obj->pushST);
}

void myQueueFree(MyQueue* obj) {
	StackDestory(&obj->popST);
	StackDestory(&obj->pushST);
	free(obj);
}

最后,这是我在学习c语言数据结构之栈和队列时的笔记,如果有错误的地方希望大家指正。大家一起努力!

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值