一、栈
1.栈的概念及结构
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。进出数据的一端被称为栈顶,相对地,把另一端称为栈底。遵循后进先出(又称 先进后出)的原则
2、栈的实现
栈可以用顺序表或链表来实现,只要满足“先进后出”的原则即可,两者实现的差异不是很大,这里提一下链表的实现,以单链表为例,要将链表的头节点当作栈顶,这样在出栈时就不用去找前一个元素,直接让头节点指向下一个结点就行,否则我们就需要遍历整个单链表找到尾节点的前一个结点
这里选用顺序表的方式,代码如下
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack {
STDataType* data;
int top;
int capacity;
}Stack;
// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType x);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);
// 初始化栈
void StackInit(Stack* ps)
{
assert(ps);
ps->data = NULL;
ps->top = 0;//这里代表指向栈顶元素的下一个位置,也可以赋值为-1,代表指向当前栈顶元素,但是后面函数实现会有些许差别
ps->capacity = 0;
}
// 入栈
void StackPush(Stack* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->data, sizeof(STDataType) * newcapacity);
if (tmp == NULL)
{
perror("malloc");
return;
}
ps->data = tmp;
ps->capacity = newcapacity;
}
ps->data[ps->top++] = x;
}
// 出栈
void StackPop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->data[ps->top - 1];
}
// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
assert(ps);
return ps->top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps)
{
assert(ps);
return ps->top == 0;
}
// 销毁栈
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->data);
ps->data = NULL;
ps->top = ps->capacity = 0;
}
二、队列
1.队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出,进行插入操作的一端称为队尾 ,进行删除操作的一端称为队头
2.队列的实现
队列同样可以用顺序表和链表来实现,我们来看看哪种结构更适合队列,很显然顺序表的出队列操作,会导致后面的元素整体往前移动,效率很低,而链表只需要删除头节点就行,为了方便,这里选用链表实现
代码如下
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
typedef struct QNode {
QDataType data;
struct QNode* next;
}QNode;
typedef struct Queue {
QNode* head;
QNode* tail;
int size;
}Queue;
//初始化
void QueueInit(Queue* p);
//销毁
void QueueDestroy(Queue* p);
//入队列
void QueuePush(Queue* p, QDataType x);
//出队列
void QueuePop(Queue* p);
//队头元素
QDataType QueueFront(Queue* p);
//队尾元素
QDataType QueueBack(Queue* p);
//判断是否为空
bool QueueEmpty(Queue* p);
//队列元素
int QueueSize(Queue* p);
void QueueInit(Queue* p)
{
assert(p);
p->head = p->tail = NULL;
p->size = 0;
}
void QueueDestroy(Queue* p)
{
assert(p);
QNode* cur = p->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
p->head = p->tail = NULL;
p->size = 0;
}
void QueuePush(Queue* p, QDataType x)
{
assert(p);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
assert(newnode);
newnode->next = NULL;
newnode->data = x;
if (p->head == NULL)
{
p->head = p->tail = newnode;
}
else
{
p->tail->next = newnode;
p->tail = newnode;
}
p->size++;
}
void QueuePop(Queue* p)
{
assert(p);
assert(!QueueEmpty(p));
if (p->head == p->tail)
{
free(p->head);
p->head = p->tail = NULL;
}
else
{
QNode* next = p->head->next;
free(p->head);
p->head = next;
}
p->size--;
}
QDataType QueueFront(Queue* p)
{
assert(p);
assert(!QueueEmpty(p));
return p->head->data;
}
QDataType QueueBack(Queue* p)
{
assert(p);
assert(!QueueEmpty(p));
return p->tail->data;
}
bool QueueEmpty(Queue* p)
{
assert(p);
return p->size == 0;
}
int QueueSize(Queue* p)
{
assert(p);
return p->size;
}
这里留下两个问题,供读者思考
1.如何用栈实现队列---题目链接---232. 用栈实现队列 - 力扣(LeetCode)
2.如何用队列实现栈---题目链接---225. 用队列实现栈 - 力扣(LeetCode)