数据结构是计算机存储、组织数据的方式。栈和队列是两种常用的线性数据结构,它们在程序设计中扮演着重要角色。
一、栈(Stack)
栈是一种遵循后进先出(Last In First Out, LIFO)原则的数据结构。其主要特点如下:
1. 基本操作:栈的操作主要有两种——压栈(push)和出栈(pop)。
- 压栈:在栈顶插入一个元素。
- 出栈:删除栈顶元素。
2. 栈顶和栈底:栈有一个顶端,称为栈顶,它是栈中元素插入和删除的一端;另一端称为栈底。
3. 受限的插入和删除:只能在栈顶进行插入和删除操作,不能在栈的中间或其他位置进行操作。
4. 应用场景:函数调用、表达式求值、递归、后缀表达式等.
栈的底层结构k可以使用数组,简单来实现栈。
栈的结构:
//定义栈的结构typedef int STDataType;
typedef struct Stack
{
STDataType* arr;
int capacity; //栈的空间大小
int top; //栈顶
}ST;
栈的完整代码 Stack.c 如下:
#include"Stack.h"
//栈的初始化
void STInit(ST* ps)
{
assert(ps);
ps->arr = NULL;
ps->capacity = ps->top = 0;
}
//栈的销毁
void STDestroy(ST* ps)
{
assert(ps);
if (ps->arr)
free(ps->arr);
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
//栈的插入---压栈
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//1.判断空间是否足够
if (ps->capacity == ps->top)
{
int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail!");
exit(1);
}
ps->arr = tmp;
ps->capacity = newCapacity;
}
//空间足够
ps->arr[ps->top++] = x;
}
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
//栈的插入---出栈
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
--ps->top;
}
//取栈顶元素
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->arr[ps->top - 1];
}
//获取栈中有效元素个数
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
一道栈的OJ题 ——有效的括号
解题思想:
- ps 遍历到的字符为左括号,入栈。
- ps 遍历到的字符为有括号,取栈顶元素和 ps 匹配:
- 栈顶元素和*ps 相匹配,栈顶元素出栈,ps++,完全匹配,返回 true,否则返回 false。
- 栈顶元素和*ps 不匹配,返回 false。
代码如下;
bool isValid(char* s) {
ST st;
//初始化
STInit(&st);
//遍历字符串s
char* ps=s;
while(* ps !='\0')
{
//左括号,入栈
if(* ps=='('||* ps=='['||* ps=='{' )
{
StackPush(&st,* ps);
}
else//有括号,和栈顶元素进行匹配
{
// 栈为空,直接返回false
if(StackEmpty(&st))
{
return false;
}
//栈不为空,才可以取栈顶元素
char ch=StackTop(&st);
if((* ps==')'&&ch=='(')||(* ps==']'&&ch=='[')||(* ps=='}'&&ch=='{'))
{
StackPop(&st);
}
else
{
STDestroy(&st);
//不匹配
return false;
}
}
ps++;
}
bool ret=StackEmpty(&st)==true;
//销毁
STDestroy(&st);
return ret;
}
二、队列(Queue)
队列是一种遵循先进先出(First In First Out, FIFO)原则的数据结构。其主要特点如下:
1. 基本操作:队列的操作主要有两种——入队(enqueue)和出队(dequeue)。
- 入队:在队列的尾部插入一个元素。
- 出队:删除队列的头部元素。
2. 队头和队尾:队列有两个端,一端是队头,另一端是队尾。
3. 受限的插入和删除:在队头进行出队操作,在队尾进行入队操作。
4. 应用场景:任务调度、缓冲处理、打印任务管理等。
实现队列,我们可以使用单链表。
队列的结构:
//定义队列结构typedef int QDataType;
typedef struct QueueNode
{
QDataType data;
struct QueueNode* next;
}QueueNode;
队列中单链表的结构:
typedef struct Queue
{
QueueNode* phead;
QueueNode* ptail;
int size; //保存队列有效数据个数
}Queue;
队列的完整代码 Queue.c 如下:
#include"Queue.h"
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
// ⼊队列,队尾
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;
//ptail newnode
if (pq->phead == NULL)
{
//队列为空
pq->phead = pq->ptail = newnode;
}
else
{
//队列不为空
pq->ptail->next = newnode;
pq->ptail = pq->ptail->next;//newnode
}
pq->size++;
}
//队列判空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL && pq->ptail == NULL;
}
// 出队列,队头
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
//只有一个结点的情况,避免ptail变成野指针
if (pq->ptail == pq->phead)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
//删除队头元素、
QueueNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
--pq->size;
}
//取队头数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->phead->data;
}
//取队尾数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->ptail->data;
}
//队列有效元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//销毁队列
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;
}
点赞收藏+关注,进阶大佬不迷路~~~
标签:ps,pq,队列,assert,phead,ptail,数据结构 From: https://blog.csdn.net/2401_83948390/article/details/140574239