前言
- 栈是一种特殊的线性表,它只允许在一端进行插入和删除操作。这一端被称为栈顶,另一端被称为栈底。栈的特点是后进先出(LIFO),即最后进入的元素最先被移除。
- 队列是另一种特殊的线性表,它允许在一端进行插入操作,在另一端进行删除操作。插入操作的一端称为队尾,删除操作的一端称为队头。队列的特点是先进先出(FIFO),即最先进入的元素最先被移除。
栈和队列有各自的特点,严格讲用顺序表还是链表的实现都可以。但我们根据结构特点选择一个更加适合的结构进行是实现。
一、栈和队列的理解
对于栈的理解:
栈如同这个图一样,要是想拿出数据,必须从上面一个一个往下面拿。这也正是 LIFO 的体现。
对于队列的理解:
队列如同这个图一样,要是想拿出数据,必须前面一个一个往向后面拿。这也正是 FIFO 的体现。
二、栈的实现(顺组表)
2.1 栈的功能
//初始化 void STInit(ST* ps); //压栈 void STpush(ST* ps, STDataType x); //删除 void STPop(ST* ps); //大小 int STSize(ST* ps); //判空 bool STEmpty(ST* ps); //出栈 STDataType STTop(ST* ps); //检查容量 void CheckCapacity(ST* ps); //销毁 void STDestroy(ST* ps);
2.2 栈结构体的定义及其初始化
结构体的定义
typedef int STDataType; typedef struct stack { STDataType* a; int top; int capacity; }ST;
初始化(开辟空间)
void STInit(ST* ps) { assert(ps); ps->a = (STDataType*)malloc(sizeof(STDataType)*4); if (ps->a == NULL) { perror("malloc fail"); return; } ps->capacity = 4; ps->top = 0; }
2.3 压栈(存储数据)
//压栈 void STpush(ST* ps,STDataType x) { assert(ps); ps->a[ps->top] = x; ps->top++; }
2,4 删除数据
在这里面删除数据是配合,栈顶出栈。每次拿出一个数据,就要减少一个数据。
void STPop(ST* ps) { assert(ps); assert(!STEmpty(ps)); ps->top--; }
2.5 计算栈内元个数
//大小 int STSize(ST* ps) { assert(ps); return ps->top; }
2.6 判断栈内是否为空
这里运用 bool 类型直接返回,比较方便。
bool STEmpty(ST* ps) { assert(ps); return ps->top == 0; }
2.7 出栈
//出栈 STDataType STTop(ST* ps) { assert(ps); return ps->a[ps->top-1]; }
2.8 增加容量
//检查容量 void CheckCapacity(ST*ps) { assert(ps); if (ps->top == ps->capacity) { ST* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * (ps->capacity) * 2); if (tmp == NULL) { perror("malloc fail"); return; } ps->capacity *= 2; ps->a = tmp; } }
2.9 销毁栈
//销毁 void STDestroy(ST* ps) { assert(ps); free(ps->a); ps->a = NULL; ps->capacity = 0; ps->top = 0; }
三、队列的实现(单链表)
3.1 队列的功能
//初始化 void QueueInit(Queue* ps); //销毁 void QueueDestroy(Queue* ps); //入队 void QueuePush(Queue* ps, QDataType x); //删除 void QueuePop(Queue* ps); //大小 int QueueSize(Queue* ps); //判空队 bool QueueEmpty(Queue* ps); //出队头 QDataType QueueTop(Queue* ps); //出队尾 QDataType QueueBack(Queue* ps);
3.2 队列的结构体定义以及初始化
结构体定义
定义两个结构体,第一个为存放数据,第二个结构体为两个指针,分别指向头和尾
typedef int QDataType; typedef struct QNode { struct QNode* next; QDataType data; }QNode; typedef struct Queue { QNode*head; QNode*tail; int szie; }Queue;
初始化
//初始化 void QueueInit(Queue* ps) { assert(ps); ps->head = ps->tail = NULL; ps->szie = 0; }
3.3 队列销毁
//销毁 void QueueDestroy(Queue* ps) { assert(ps); QNode* cur = ps->head; while (cur) { QNode* next = cur->next; free(cur); cur = next; } ps->head = ps->tail = NULL; ps->szie = 0; }
3.4 入队(插入数据)
//入队 void QueuePush(Queue* ps,QDataType x) { assert(ps); QNode* newcode = (QNode*)malloc(sizeof(QNode)); if (newcode == NULL) { perror("malloc fail"); return ; } newcode->next = NULL; newcode->data = x; if (ps->head == NULL) { ps->head = ps->tail = newcode; } else { ps->tail->next = newcode; ps->tail = newcode; } ps->szie++; }
3.5 删除数据(头删)
//删除 void QueuePop(Queue* ps) { assert(ps); assert(ps->head != NULL); assert(!QueueEmpty(ps)); if (ps->head->next == NULL) { free(ps->head); ps->head = ps->tail = NULL; } else { QNode* next = ps->head->next; free(ps->head); ps->head = next; } ps->szie--; }
3.6 计算队列元素个数
//大小 int QueueSize(Queue* ps) { assert(ps); return ps->szie; }
3.7 判断是否队列为空
//判空队 bool QueueEmpty(Queue* ps) { assert(ps); return ps->szie == 0; }
3.8 出队(头)
//出队头 QDataType QueueTop(Queue* ps) { assert(ps); assert(!QueueEmpty(ps)); return ps->head->data; }
3.9 出队(尾)
//出队尾 QDataType QueueBack(Queue* ps) { assert(ps); return ps->tail->data; }
四、栈和队列的源码
栈
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 STInit(ST* ps); //压栈 void STpush(ST* ps, STDataType x); //删除 void STPop(ST* ps); //大小 int STSize(ST* ps); //判空 bool STEmpty(ST* ps); //出栈 STDataType STTop(ST* ps); //检查容量 void CheckCapacity(ST* ps); //销毁 void STDestroy(ST* ps);
Stack.c
#define _CRT_SECURE_NO_WARNINGS #include "stack.h" //初始化 void STInit(ST* ps) { assert(ps); ps->a = (STDataType*)malloc(sizeof(STDataType*)*4); if (ps->a == NULL) { perror("malloc fail"); return; } ps->capacity = 4; ps->top = 0; } //销毁 void STDestroy(ST* ps) { assert(ps); free(ps->a); ps->a = NULL; ps->capacity = 0; ps->top = 0; } //检查容量 void CheckCapacity(ST*ps) { assert(ps); if (ps->top == ps->capacity) { ST* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * (ps->capacity) * 2); if (tmp == NULL) { perror("malloc fail"); return; } ps->capacity *= 2; ps->a = tmp; } } //压栈 void STpush(ST* ps,STDataType x) { assert(ps); ps->a[ps->top] = x; ps->top++; } //删除 void STPop(ST* ps) { assert(ps); assert(!STEmpty(ps)); ps->top--; } //判空 bool STEmpty(ST* ps) { assert(ps); return ps->top == 0; } //出栈 STDataType STTop(ST* ps) { assert(ps); return ps->a[ps->top-1]; } //大小 int STSize(ST* ps) { assert(ps); return ps->top; }
test.c
#define _CRT_SECURE_NO_WARNINGS #include "stack.h" void teststack() { ST st; STInit(&st); STpush(&st, 1); STpush(&st, 2); STpush(&st, 3); STpush(&st, 4); STpush(&st, 5); printf("%d", STSize(&st)); printf("\n"); while (!STEmpty(&st)) { printf("%d ", STTop(&st)); STPop(&st); } printf("\n"); printf("%d", STSize(&st)); STDestroy(&st); } int main() { teststack(); return 0; }
队列
Queue.h
#pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <stdbool.h> typedef int QDataType; typedef struct QNode { struct QNode* next; QDataType data; }QNode; typedef struct Queue { QNode*head; QNode*tail; int szie; }Queue; //单链表的实现,FIFO //初始化 void QueueInit(Queue* ps); //销毁 void QueueDestroy(Queue* ps); //入队 void QueuePush(Queue* ps, QDataType x); //删除 void QueuePop(Queue* ps); //大小 int QueueSize(Queue* ps); //判空队 bool QueueEmpty(Queue* ps); //出队头 QDataType QueueTop(Queue* ps); //出队尾 QDataType QueueBack(Queue* ps);
Queue.c
#define _CRT_SECURE_NO_WARNINGS #include "queue.h" //初始化 void QueueInit(Queue* ps) { assert(ps); ps->head = ps->tail = NULL; ps->szie = 0; } //销毁 void QueueDestroy(Queue* ps) { assert(ps); QNode* cur = ps->head; while (cur) { QNode* next = cur->next; free(cur); cur = next; } ps->head = ps->tail = NULL; ps->szie = 0; } //入队 void QueuePush(Queue* ps,QDataType x) { assert(ps); QNode* newcode = (QNode*)malloc(sizeof(QNode)); if (newcode == NULL) { perror("malloc fail"); return ; } newcode->next = NULL; newcode->data = x; if (ps->head == NULL) { ps->head = ps->tail = newcode; } else { ps->tail->next = newcode; ps->tail = newcode; } ps->szie++; } //删除 void QueuePop(Queue* ps) { assert(ps); assert(ps->head != NULL); assert(!QueueEmpty(ps)); if (ps->head->next == NULL) { free(ps->head); ps->head = ps->tail = NULL; } else { QNode* next = ps->head->next; free(ps->head); ps->head = next; } ps->szie--; } //大小 int QueueSize(Queue* ps) { assert(ps); return ps->szie; } //判空队 bool QueueEmpty(Queue* ps) { assert(ps); return ps->szie == 0; } //出队头 QDataType QueueTop(Queue* ps) { assert(ps); assert(!QueueEmpty(ps)); return ps->head->data; } //出队尾 QDataType QueueBack(Queue* ps) { assert(ps); return ps->tail->data; }
test.c
#define _CRT_SECURE_NO_WARNINGS #include "queue.h" void testQueue() { Queue s; QueueInit(&s); QueuePush(&s, 1); QueuePush(&s, 2); QueuePush(&s, 3); QueuePush(&s, 4); //printf("%d ", QueueTop(&s)); //QueuePop(&s); //printf("%d ", QueueTop(&s)); //QueuePop(&s); //printf("%d ", QueueTop(&s)); //QueuePop(&s); //printf("%d ", QueueTop(&s)); //QueuePop(&s); //printf("\n"); while (!(QueueEmpty(&s))) { printf("%d ", QueueTop(&s)); QueuePop(&s); } QueueDestroy(&s); } int main() { testQueue(); return 0; }