目录
1.栈的概念
编辑
2.栈的作用
1.函数递归
2.表达式求值
3.栈的模拟实现
Stack.h
Stack.c
4.队列的概念
5.队列的模拟实现
Queue.h
Queue.c
6.例题
1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是(B )。
2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C)
3.以下( B)不是队列的基本运算?
1.栈的概念
栈:是一种特殊的线性表,只允许固定的一端进行插入和删除操作。进行插入和删除的一端叫做栈顶,另一端叫做栈顶。栈中的数据元素遵守后进先出原则LIFO(Lats In Fast Out)。
压栈:栈的插入操作,也叫入栈/进栈,压栈操作在栈顶进行的。
出栈:栈的删除操作,也叫弹栈,出栈操作也是在栈底进行的。
2.栈的作用
1.函数递归
2.表达式求值
这里知识简单罗列出栈的简单应用,大家可以去B站上看相关视频,会比文章学起来更加轻松。
21_2.2.4 堆栈应用_表达式求值_哔哩哔哩_bilibili
第05周11--3.4栈和递归_哔哩哔哩_bilibili
3.栈的模拟实现
栈的实现可以是链式栈,也可以是顺序栈,相对而言顺序结构的实现更优一些,所以本文是基于顺序栈来实现的。
Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//初始化
void StackInit(ST* pst);
//销毁
void StackDestroy(ST* pst);
//添加
void StackPush(ST* pst, STDataType x);
//删除
void StackPop(ST* pst);
//top值
STDataType StackTop(ST* pst);
//有效元素个数
int StackSize(ST* pst);
//判断是否为空
bool StackEmpty(ST* pst);
Stack.c
#include "Stack.h"
//初始化
void StackInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->top = 0;
pst->capacity = 0;
}
//销毁
void StackDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = 0;
pst->top = 0;
}
//添加
void StackPush(ST* pst, STDataType x)
{
assert(pst);
if (pst->top == pst->capacity)
{
int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
STDataType* temp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
if (temp == NULL)
{
perror("realloc");
return;
}
pst->a = temp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x;
pst->top++;
}
//删除
void StackPop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
pst->top--;
}
//top值
STDataType StackTop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
return pst->a[pst->top - 1];
}
//有效元素个数
int StackSize(ST* pst)
{
assert(pst);
return pst->top;
}
//判断是否为空
bool StackEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
4.队列的概念
队列:也是一种特殊的线性表,要求只能一端进行插入操作,另一端进行删除操作,遵循先入先出原则FIFO(First In First Out)。
入队列:进行插入的一端叫做队头。
出队列:进行删除的一端叫队尾。
5.队列的模拟实现
队列的实现也可以基于链式结构或顺序结构,但是用链式结构效率更高,使用顺序结构,进行插入操作效率较低。本文基于链式结构实现队列。
Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int QNDataType;
typedef struct QueueNode
{
QNDataType data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
//初始化
void QueueInit(Queue* pq);
//插入
void QueuePush(Queue* pq, QNDataType x);
//删除
void QueuePop(Queue* pq);
//获取头部元素
QNDataType QueueFront(Queue* pq);
//获取尾部元素
QNDataType QueueBack(Queue* pq);
//元素个数
int QueueSize(Queue* pq);
//判断是否为空
bool QueueEmpty(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
Queue.c
#include "Queue.h"
//初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
//插入
void QueuePush(Queue* pq, QNDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("mallloc");
return;
}
newnode->data = x;
newnode->next = NULL;
if (pq->ptail == NULL)
{
pq->ptail = pq->phead = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
//删除
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->phead);
QNode* del = pq->phead;
pq->phead = pq->phead->next;
free(del);
del = NULL;
pq->size--;
if (pq->phead == NULL)
{
pq->ptail = NULL;
}
}
//获取头部元素
QNDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->phead->data;
}
//获取尾部元素
QNDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->ptail->data;
}
//元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//判断是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL;
}
//销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
/*while (!QueueEmpty(pq))
{
QueuePop(pq);
}*/
QNode* cur = pq->phead;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
6.例题
1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是(B )。
A 12345ABCDE
B EDCBA54321
C ABCDE12345
2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C)
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1
解析:这道题是对上面那道题的一点小小升级,结题方法就是依次试试,经过验证,对于C选项,如果1想出栈,那么2,4必须先出栈。
3.以下( B)不是队列的基本运算?
A 从队尾插入一个新元素
B 从队列中删除第i个元素
C 判断一个队列是否为空
D 读取队头元素的值
解析:这道就是一个非常经典的概念题,把握好概念,队列只能一端进行插入,另一端进行删除,不支持随机访问,想要访问i节点,必须把i之前的节点出队列。