【数据结构初阶】一文详解顺序栈和链队列的基本操作
2023-06-13 09:16:43 时间
目录
1.栈的概念
栈,一种特殊的线性表,特殊在于只允许在固定的一端进行插入删除数据,插入和删除数据的一端是栈顶,另一端是栈底,已经在栈中的数据满足Fist In Last Out的原则。
压栈:栈顶插入数据 出栈:栈顶弹出数据
2.栈的结构
总体而言,用顺序表和链表实现都可以,但是由于栈只支持在栈顶插入删除数据,且要满足后进先出,而顺序表尾插尾删的效率比链表高,(顺序表唯一的缺点在这就是扩容有性能和空间的消耗)同时也满足后进先出的原则,所以选择顺序表实现好!
有人可能会说用链表,然后定义一个尾指针,这样尾插效率不是也很高吗?
答:定义一个尾指针,链表的插入时很方便,但是尾删呐??
其实顺序表,双向循环链表,头上操作单链表都行,但是由于顺序表命中率高的优点,还是选择顺序表。
3.实现栈的基本操作
3.1栈的初始化
- 选择哪一个方式初始化top都可以,但是记得做到和后面的push等做到统一。
- 建议再主函数内判空操作不直接自己if(ps->top==0)等,因为这个内部怎么实现的不一定是初始化为ps->top=0,而是建议调用函数去判空if(StackEmpty(&ST))
void StackInit(Stack* ps)
{
assert(ps);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
3.2压栈
void StackPush(Stack* ps, STDateType x)
{
assert(ps);
if(ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;
STDateType* temp = (STDateType*)realloc(ps->a, sizeof(STDateType)*newcapacity);
if (temp == NULL)
{
perror("malloc fail.\n");
exit(-1);
}
ps->capacity = newcapacity;
ps->a = temp;
}
ps->a[ps->top] = x;
ps->top++;
}
3.3出栈
void StackPop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
3.4 取栈顶元素
STDateType StackTop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
3.5 计算栈内元素个数
int StackSize(Stack* ps)
{
assert(ps);
return ps->top;
}
3.6栈的判空
bool StackEmpty(Stack* ps)
{
assert(ps);
return ps->top == 0;
}
3.7栈的销毁
void StackDestory(Stack* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
4.源代码
4.1stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"
void StackInit(Stack* ps)
{
assert(ps);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
void StackPush(Stack* ps, STDateType x)
{
assert(ps);
if(ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;
STDateType* temp = (STDateType*)realloc(ps->a, sizeof(STDateType)*newcapacity);
if (temp == NULL)
{
perror("malloc fail.\n");
exit(-1);
}
ps->capacity = newcapacity;
ps->a = temp;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
STDateType StackTop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
int StackSize(Stack* ps)
{
assert(ps);
return ps->top;
}
bool StackEmpty(Stack* ps)
{
assert(ps);
return ps->top == 0;
}
void StackDestory(Stack* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
4.2stack.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int STDateType;
typedef struct Stack
{
STDateType* a;
int top;
int capacity;
}Stack;
void StackInit(Stack* ps);
void StackPush(Stack* ps,STDateType x);
void StackPop(Stack* ps);
STDateType StackTop(Stack* ps);
bool StackEmpty(Stack* ps);
int StackSize(Stack* ps);
void StackDestory(Stack* ps);
4.3test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"
int main()
{
Stack ST;
StackInit(&ST);
StackPush(&ST, 1);
StackPush(&ST, 2);
StackPush(&ST, 3);
StackPush(&ST, 4);
STDateType top = StackTop(&ST);
printf("top:%d\n", top);
StackPop(&ST);
top = StackTop(&ST);
printf("top:%d\n", top);
int size = StackSize(&ST);
printf("size:%d\n", size);
StackDestory(&ST);
return 0;
}
4.4效果图
1.队列的概念
队列是一种特殊的线性表,特殊在只能从一端进行插入操作,另一端进行删除操作,队列具有Fist In First Out的原则。 队尾:进行插入操作的一端,这个过程叫做入队列 队头:进行删除操作的一端,这个过程叫做出队列
抽号机:先来先服务,先给号码排队 (涉及嵌入式)
2.队列的结构
队列我们采用链表实现:顺序表在满了要扩容,删完了后再入队列的时候还得扩容 链表的话,入队列就是尾插,定义一个尾指针。出队列就是头删,定义一个头指针
3.实现队列的基本操作
3-1结构体定义
typedef int QDateType;
typedef struct QueueNode
{
struct QueueNode* next;
QDateType val;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
3-2队列的初始化
这里的链表队列我并没有带头,没有带头就要在入队列和出队列时有一点特殊情况的考虑
void QueueInit(Queue* ps)
{
assert(ps);
ps->head = ps->tail = NULL;
}
3-3入队列
相当于尾插,考虑特殊情况:队列为空的情况
//入队列:尾插
void QueuePush(Queue* ps,QDateType x)
{
assert(ps);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
newnode->next = NULL;
newnode->val = x;
if (newnode == NULL)
{
perror("malloc fail.");
exit(-1);
}
if (ps->tail == NULL)
{
ps->head = ps->tail = newnode;
}
else
{
ps->tail->next = newnode;
ps->tail = ps->tail->next;
}
}
3-4出队列
相当于头删,考虑特殊情况:只有一个结点的情况,出队列后要改变ps->tail
void QueuePop(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
if (ps->head->next == NULL)
{
free(ps->head);
ps->head = ps->tail = NULL;
}
else
{
QueueNode* next = ps->head->next;
free(ps->head);
ps->head = next;
}
}
3-5取队头元素
QDateType QueueFront(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
return ps->head->val;
}
3-6取队尾元素
QDateType QueueBack(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
return ps->tail->val;
}
3-7队列判空
bool QueueEmpty(Queue* ps)
{
assert(ps);
return ps->tail == NULL;
}
3-8队列长度
int QueueSize(Queue* ps)
{
assert(ps);
int size = 0;
QueueNode* cur = ps->head;
while(cur)
{
++size;
cur = cur->next;
}
return size;
}
3-9队列销毁
void QueueDestory(Queue* ps)
{
assert(ps);
QueueNode* cur = ps->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
ps->head = ps->tail = NULL;
}
4.源代码
4-1queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"queue.h"
void QueueInit(Queue* ps)
{
assert(ps);
ps->head = ps->tail = NULL;
}
void QueueDestory(Queue* ps)
{
assert(ps);
QueueNode* cur = ps->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
ps->head = ps->tail = NULL;
}
//入队列:尾插
void QueuePush(Queue* ps,QDateType x)
{
assert(ps);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
newnode->next = NULL;
newnode->val = x;
if (newnode == NULL)
{
perror("malloc fail.");
exit(-1);
}
if (ps->tail == NULL)
{
ps->head = ps->tail = newnode;
}
else
{
ps->tail->next = newnode;
ps->tail = ps->tail->next;
}
}
void QueuePop(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
if (ps->head == ps->tail)
{
free(ps->head);
ps->head = ps->tail = NULL;
}
else
{
QueueNode* next = ps->head->next;
free(ps->head);
ps->head = next;
}
}
QDateType QueueFront(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
return ps->head->val;
}
QDateType QueueBack(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
return ps->tail->val;
}
bool QueueEmpty(Queue* ps)
{
assert(ps);
return ps->tail == NULL;
}
int QueueSize(Queue* ps)
{
assert(ps);
int size = 0;
QueueNode* cur = ps->head;
while(cur)
{
++size;
cur = cur->next;
}
return size;
}
4.2queue.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int QDateType;
typedef struct QueueNode
{
struct QueueNode* next;
QDateType val;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
void QueueInit(Queue* ps);
void QueuePush(Queue* ps, QDateType x);
void QueuePop(Queue* ps);
QDateType QueueFront(Queue* ps);
QDateType QueueBack(Queue* ps);
bool QueueEmpty(Queue* ps);
int QueueSize(Queue* ps);
void QueueDestory(Queue* ps);
4.3test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"queue.h"
int main()
{
Queue Q;
QueueInit(&Q);
QueuePush(&Q, 1);
QueuePush(&Q, 2);
QueuePush(&Q, 3);
QueuePush(&Q, 4);
QueuePush(&Q, 5);
QDateType ret1 = QueueFront(&Q);
printf("QueueFront:%d\n", ret1);
QDateType ret2 = QueueBack(&Q);
printf("QueueBack:%d\n", ret2);
int size = QueueSize(&Q);
printf("size:%d\n", size);
while (!QueueEmpty(&Q))
{
printf("%d", QueueFront(&Q));
QueuePop(&Q);
}
QueueDestory(&Q);
return 0;
}
4.4效果图
制作不易,敬请三连
相关文章
- 数据结构:循环队列(C语言实现)[通俗易懂]
- 【Java】Java双端队列Deque使用详解
- RabbitMQ中延迟队列的全方位解析
- 算法与数据结构之优先级队列
- 数组模拟队列思路
- 云计算服务架构任务池与指令池的搭建和使用,RabbitMQ消息队列
- 16-RabbitMQ高级特性-延迟队列
- 【数据结构初阶】数组栈和链式队列的实现
- 【数据结构】优先级队列(堆)
- 数据结构学习—队列
- 异步redis队列实现 数据入库的方法
- 如何查看Redis中的队列信息(怎么查询redis的队列)
- Redis队列调控订单库存,实现效率管理(订单库存redis队列)
- 基于Redis的队列数据结构研究(redis队列的数据结构)
- 实现方式红色传送带五种Redis队列实现方法(redis队列的五种)
- PHP操作Redis队列实现数量控制(redis队列数量php)
- 红色舞台上的卡夫卡精致的Redis队列(redis队列和卡夫卡)
- 的处理处理Redis队列中取出来的数据(redis队列取出来后)
- 级实现Redis队列优先级处理机制(redis队列优先)
- jquery队列queue与原生模仿其实现方法分享