目录
[(5) 取栈顶元素](#(5) 取栈顶元素)
一、栈的概念和结构
(1)栈
栈是一种特殊的线性表,只允许在固定的一端进行插入和删除操作;
进行插入和删除操作的一端为栈顶 ,另外一端为栈底;
栈中的数据元素遵守先进后出的原则。
(2)压栈
栈的插入操作叫做:进栈/压栈/入栈,入数据在栈顶。
(3)出栈
栈的删除操作叫做出栈,出数据也在栈顶。
(4)栈的底层结构
栈的实现可以使用数组或者链表,相对而言,数组的结构更优一些(因为数组尾插数据的代价比较小)。
二、栈的实现
1.Stack.h
cpp
#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)初始化
cpp
void STinit(ST* ps)
{
assert(ps);
ps->arr = NULL;
ps->capacity = ps->top = 0;
}
(2)销毁
cpp
void STDestroy(ST* ps)
{
assert(ps);
//释放之前判断不为空
if (ps->arr)
{
free(ps->arr);
}
//释放之后要将指针置为空,否则再次使用会成为野指针
ps->arr = NULL;
ps->capacity = ps->top = 0;
}
(3)判断栈是否为空
cpp
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;//栈的有效数据为0,即栈为空
}
(4)从栈顶入数据、出数据
cpp
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) 取栈顶元素
cpp
STDatatype StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->arr[ps->top - 1];
}
(6)栈有效元素的个数
cpp
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
3.text.c
cpp
#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
cpp
#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)初始化
cpp
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
(2)队列判空
cpp
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL;
}
(3)从队尾入队列
cpp
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)从队头出队列
cpp
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)取队头数据
cpp
QDatatype QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));//队列不能为空!
return pq->phead->data;
}
(6)取队尾数据
cpp
QDatatype QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));//队列不能为空!
return pq->ptail->data;
}
(7)队列有效元素个数
cpp
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
(8)销毁队列
cpp
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;
}
五、写在最后
当爱学习的你看到这里,肯定已经学会了栈和队列的实现,那么如何应用到题目中呢?
敬请期待:栈和队列的算法题~