深入了解栈与队列:从基础到应用
嘿嘿,家人们,今天咱们来详细剖析数据结构中的栈和队列,好啦,废话不多讲,开干!
1.:栈
1.1:栈的概念与结构
1.2:栈的实现
1.2.1:Stack.h
1.2.2:Stack.c
1.2.2.1:初始化与入栈与出栈与获取栈顶元素
1.2.2.2:获取元素个数与判断栈为空与销毁栈
1.2.3:Test.c
1.2.3.1:测试初始化与入栈与出栈与获取栈顶元素
1.2.3.2:测试获取元素个数与判断栈为空与销毁栈
1.3:栈的总代码
1.3.1:Stack.h
1.3.2:Stack.c
1.3.3:Test.c
2:队列
2.1:队列的概念与结构
2.2:队列的实现
2.2.1:Queue.h
2.2.2:Queue.c
2.2.2.1:初始化与入队列和出队列与获取队列元素个数
2.2.2.2:获取队头与队尾与判断队列为空与销毁队列
2.2.3:Test.c
2.2.3.1:测试初始化与入队列和出队列与获取队列元素个数
2.2.3.2:测试获取队头与队尾与判断队列为空与销毁队列
3:队列的总代码
3.1:Queue.h
3.2:Queue.c
3.3:Test.c
1.:栈
1.1:栈的概念与结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作,进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则.压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶.出栈:栈的删除操作叫做出栈。出数据也在栈顶.
1.2:栈的实现
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小.
1.2.1:Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int STDataType;typedef struct Stack
{STDataType* _arr;//指向栈顶int _top;//容量int _capacity;
}Stack;void StackInit(Stack* pst);
//入栈
void StackPush(Stack* pst, STDataType data);
// 出栈
void StackPop(Stack* pst);// 获取栈顶元素
STDataType StackTop(Stack* ps);// 获取栈中有效元素个数
int StackSize(Stack* pst);// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* pst);// 销毁栈
void StackDestroy(Stack* pst);
1.2.2:Stack.c
1.2.2.1:初始化与入栈与出栈与获取栈顶元素
#define _CRT_SECURE_NO_WARNINGS
#include "Stack.h"void StackInit(Stack* pst)
{assert(pst);pst->_arr = NULL;//指向栈顶,一开始没有元素pst->_top = -1;pst->_capacity = 0;
}void CheckCapacity(Stack * pst)
{assert(pst);if(pst->_top + 1 == pst->_capacity){int NewCapacity = pst->_capacity == 0 ? 4 : pst->_capacity * 2;//如果传了个空指针,就等价于malloc(NewCapacity * sizeof(STDataType))STDataType * Tmp = (STDataType*)realloc(pst->_arr, NewCapacity * sizeof(STDataType));if(Tmp == NULL){perror("realloc fail");exit;}pst->_arr = Tmp;pst->_capacity = NewCapacity;}
}void StackPush(Stack* pst, STDataType data)
{assert(pst);CheckCapacity(pst);//由于top指向的是栈顶,因此先++,在入栈pst->_top++;pst->_arr[pst->_top] = data;
}void StackPop(Stack* pst)
{assert(pst);//确保栈里面有元素assert(pst->_top >= 0);pst->_top--;
}// 获取栈顶元素
STDataType StackTop(Stack* pst)
{assert(pst);assert(pst->_top >= 0);return pst->_arr[pst->_top];
}
1.2.2.2:获取元素个数与判断栈为空与销毁栈
// 获取栈中有效元素个数
int StackSize(Stack* pst)
{assert(pst);//top指向的是栈顶,因此要 + 1,数组下标从0开始return pst->_top + 1;
}// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* pst)
{assert(pst);if (pst->_top == -1)return 1;return 0;}// 销毁栈
void StackDestroy(Stack* pst)
{assert(pst);free(pst->_arr);pst->_arr = NULL;pst->_top = -1;pst->_capacity = 0;
}
1.2.3:Test.c
1.2.3.1:测试初始化与入栈与出栈与获取栈顶元素
#include "Stack.h"void TestPushAndPop(Stack* pst)
{StackInit(pst);StackPush(pst,1);printf("%d\n", StackTop(pst));StackPush(pst,2);printf("%d\n", StackTop(pst));StackPush(pst,3);printf("%d\n", StackTop(pst));StackPush(pst,4);printf("%d\n", StackTop(pst));printf("--------------------------------\n");printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);
}int main()
{Stack pst;TestPushAndPop(&pst);return 0;
}


1.2.3.2:测试获取元素个数与判断栈为空与销毁栈
#include "Stack.h"void TestPushAndPop(Stack* pst)
{StackInit(pst);StackPush(pst,1);printf("%d\n", StackTop(pst));StackPush(pst,2);printf("%d\n", StackTop(pst));StackPush(pst,3);printf("%d\n", StackTop(pst));StackPush(pst,4);printf("%d\n", StackTop(pst));printf("--------------------------------\n");printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);
}void TestOther(Stack * pst)
{StackInit(pst);StackPush(pst, 1);StackPush(pst, 2);StackPush(pst, 3);StackPush(pst, 4);//为空返回非0数字,非空则为0while(!StackEmpty(pst)){printf("%d And Size == %d\n", StackTop(pst), StackSize(pst));StackPop(pst);}StackDestroy(pst);
}int main()
{Stack pst;/*TestPushAndPop(&pst);*/TestOther(&pst);return 0;
}


1.3:栈的总代码
1.3.1:Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int STDataType;typedef struct Stack
{STDataType* _arr;//指向栈顶int _top;//容量int _capacity;
}Stack;void StackInit(Stack* pst);
//入栈
void StackPush(Stack* pst, STDataType data);
// 出栈
void StackPop(Stack* pst);// 获取栈顶元素
STDataType StackTop(Stack* ps);// 获取栈中有效元素个数
int StackSize(Stack* pst);// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* pst);// 销毁栈
void StackDestroy(Stack* pst);
1.3.2:Stack.c
#define _CRT_SECURE_NO_WARNINGS
#include "Stack.h"void StackInit(Stack* pst)
{assert(pst);pst->_arr = NULL;//指向栈顶,一开始没有元素pst->_top = -1;pst->_capacity = 0;
}void CheckCapacity(Stack* pst)
{assert(pst);if (pst->_top + 1 == pst->_capacity){int NewCapacity = pst->_capacity == 0 ? 4 : pst->_capacity * 2;//如果传了个空指针,就等价于malloc(NewCapacity * sizeof(STDataType))STDataType* Tmp = (STDataType*)realloc(pst->_arr, NewCapacity * sizeof(STDataType));if (Tmp == NULL){perror("realloc fail");exit;}pst->_arr = Tmp;pst->_capacity = NewCapacity;}
}void StackPush(Stack* pst, STDataType data)
{assert(pst);CheckCapacity(pst);//由于top指向的是栈顶,因此先++,在入栈pst->_top++;pst->_arr[pst->_top] = data;
}void StackPop(Stack* pst)
{assert(pst);//确保栈里面有元素assert(pst->_top >= 0);pst->_top--;
}// 获取栈顶元素
STDataType StackTop(Stack* pst)
{assert(pst);assert(pst->_top >= 0);return pst->_arr[pst->_top];
}// 获取栈中有效元素个数
int StackSize(Stack* pst)
{assert(pst);//top指向的是栈顶,因此要 + 1,数组下标从0开始return pst->_top + 1;
}// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* pst)
{assert(pst);if (pst->_top == -1)return 1;return 0;}// 销毁栈
void StackDestroy(Stack* pst)
{assert(pst);free(pst->_arr);pst->_arr = NULL;pst->_top = -1;pst->_capacity = 0;
}
1.3.3:Test.c
#include "Stack.h"void TestPushAndPop(Stack* pst)
{StackInit(pst);StackPush(pst,1);printf("%d\n", StackTop(pst));StackPush(pst,2);printf("%d\n", StackTop(pst));StackPush(pst,3);printf("%d\n", StackTop(pst));StackPush(pst,4);printf("%d\n", StackTop(pst));printf("--------------------------------\n");printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);printf("%d\n", StackTop(pst));StackPop(pst);
}void TestOther(Stack * pst)
{StackInit(pst);StackPush(pst, 1);StackPush(pst, 2);StackPush(pst, 3);StackPush(pst, 4);//为空返回非0数字,非空则为0while(!StackEmpty(pst)){printf("%d And Size == %d\n", StackTop(pst), StackSize(pst));StackPop(pst);}StackDestroy(pst);
}int main()
{Stack pst;/*TestPushAndPop(&pst);*/TestOther(&pst);return 0;
}
2:队列
2.1:队列的概念与结构
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低.
2.2:队列的实现
2.2.1:Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int QListDataType;//队列的节点
typedef struct QueueNode
{QListDataType _Value;struct QueueNode* _Next;
}QNode;typedef struct Queue
{//队头QNode* _Front;//队尾QNode* _Tail;int _size;
}Queue;// 初始化队列
void QueueInit(Queue* q);// 队尾入队列
void QueuePush(Queue* q, QListDataType data);// 队头出队列
void QueuePop(Queue* q);// 获取队列头部元素
QListDataType QueueFront(Queue* q);// 获取队列队尾元素
QListDataType QueueBack(Queue* q);// 获取队列中有效元素个数
int QueueSize(Queue* q);// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);// 销毁队列
void QueueDestroy(Queue* q);
2.2.2:Queue.c
2.2.2.1:初始化与入队列和出队列与获取队列元素个数
#define _CRT_SECURE_NO_WARNINGS
#include "Queue.h"// 初始化队列
void QueueInit(Queue* q)
{assert(q);q->_Front = NULL;q->_Tail = NULL;q->_size = 0;
}// 队尾入队列
void QueuePush(Queue* q, QListDataType Value)
{assert(q);QNode* NewNode = (QNode*)malloc(sizeof(QNode));if (NewNode == NULL){perror("malloc fail");exit(-1);}NewNode->_Next = NULL;NewNode->_Value = Value;//队头和队尾指向一致时if (q->_Front == NULL){q->_Front = NewNode;q->_Tail = NewNode;}else{//链接新节点q->_Tail->_Next = NewNode;//队尾指向新节点q->_Tail = NewNode;}q->_size++;
}// 队头出队列
void QueuePop(Queue* q)
{assert(q);assert(q->_Front && q->_Tail);if(q->_Front == q->_Tail){free(q->_Front);q->_Front = q->_Tail = NULL;}else{//保留下一个节点QNode* Temp = q->_Front->_Next;//释放旧节点free(q->_Front);//指向新节点q->_Front = Temp;}q->_size--;
}// 获取队列中有效元素个数
int QueueSize(Queue* q)
{return q->_size;
}
2.2.2.2:获取队头与队尾与判断队列为空与销毁队列
#define _CRT_SECURE_NO_WARNINGS
#include "Queue.h"// 获取队列中有效元素个数
int QueueSize(Queue* q)
{return q->_size;
}// 获取队列头部元素
QListDataType QueueFront(Queue* q)
{assert(q && q->_Front);return q->_Front->_Value;
}// 获取队列队尾元素
QListDataType QueueBack(Queue* q)
{assert(q && q->_Tail);return q->_Tail->_Value;
}// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{return q->_size == 0 ? true : false;
}// 销毁队列
void QueueDestroy(Queue* q)
{QNode* Current = q->_Front;while (Current != NULL){//保留下一个节点QNode* Temp = Current->_Next;free(Current);Current = Temp;}q->_Front = NULL;q->_Tail = NULL;q->_size = 0;}
2.2.3:Test.c
2.2.3.1:测试初始化与入队列和出队列与获取队列元素个数
#include "Queue.h"void TestPushAndPop(Queue * q)
{QueueInit(q);QueuePush(q, 2);QueuePush(q, 3);QueuePush(q, 4);QueuePush(q, 5);printf("size == %d\n", QueueSize(q));QueuePop(q);QueuePop(q);QueuePop(q);QueuePop(q);printf("size == %d\n", QueueSize(q));
}int main()
{Queue q;TestPushAndPop(&q);return 0;
}

2.2.3.2:测试获取队头与队尾与判断队列为空与销毁队列
#include "Queue.h"void TestOther(Queue* q)
{QueueInit(q);QueuePush(q, 2);QueuePush(q, 3);QueuePush(q, 4);QueuePush(q, 5);printf("size == %d And Front == %d And Tail == %d\n", QueueSize(q),QueueFront(q),QueueBack(q));QueuePop(q);printf("size == %d And Front == %d And Tail == %d\n", QueueSize(q), QueueFront(q), QueueBack(q));QueuePop(q);printf("size == %d And Front == %d And Tail == %d\n", QueueSize(q), QueueFront(q), QueueBack(q));QueueDestroy(q);
}int main()
{Queue q;TestOther(&q);return 0;
}


3:队列的总代码
3.1:Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int QListDataType;//队列的节点
typedef struct QueueNode
{QListDataType _Value;struct QueueNode* _Next;
}QNode;typedef struct Queue
{//队头QNode* _Front;//队尾QNode* _Tail;int _size;
}Queue;// 初始化队列
void QueueInit(Queue* q);// 队尾入队列
void QueuePush(Queue* q, QListDataType data);// 队头出队列
void QueuePop(Queue* q);// 获取队列头部元素
QListDataType QueueFront(Queue* q);// 获取队列队尾元素
QListDataType QueueBack(Queue* q);// 获取队列中有效元素个数
int QueueSize(Queue* q);// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);// 销毁队列
void QueueDestroy(Queue* q);
3.2:Queue.c
#define _CRT_SECURE_NO_WARNINGS
#include "Queue.h"// 初始化队列
void QueueInit(Queue* q)
{assert(q);q->_Front = NULL;q->_Tail = NULL;q->_size = 0;
}// 队尾入队列
void QueuePush(Queue* q, QListDataType Value)
{assert(q);QNode* NewNode = (QNode*)malloc(sizeof(QNode));if (NewNode == NULL){perror("malloc fail");exit(-1);}NewNode->_Next = NULL;NewNode->_Value = Value;//队头和队尾指向一致时if (q->_Front == NULL){q->_Front = NewNode;q->_Tail = NewNode;}else{//链接新节点q->_Tail->_Next = NewNode;//队尾指向新节点q->_Tail = NewNode;}q->_size++;
}// 队头出队列
void QueuePop(Queue* q)
{assert(q);assert(q->_Front && q->_Tail);if(q->_Front == q->_Tail){free(q->_Front);q->_Front = q->_Tail = NULL;}else{//保留下一个节点QNode* Temp = q->_Front->_Next;//释放旧节点free(q->_Front);//指向新节点q->_Front = Temp;}q->_size--;
}// 获取队列中有效元素个数
int QueueSize(Queue* q)
{return q->_size;
}// 获取队列头部元素
QListDataType QueueFront(Queue* q)
{assert(q && q->_Front);return q->_Front->_Value;
}// 获取队列队尾元素
QListDataType QueueBack(Queue* q)
{assert(q && q->_Tail);return q->_Tail->_Value;
}// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{return q->_size == 0 ? true : false;
}// 销毁队列
void QueueDestroy(Queue* q)
{QNode* Current = q->_Front;while (Current != NULL){//保留下一个节点QNode* Temp = Current->_Next;free(Current);Current = Temp;}q->_Front = NULL;q->_Tail = NULL;q->_size = 0;}
3.3:Test.c
#include "Queue.h"void TestPushAndPop(Queue * q)
{QueueInit(q);QueuePush(q, 2);QueuePush(q, 3);QueuePush(q, 4);QueuePush(q, 5);printf("size == %d\n", QueueSize(q));QueuePop(q);QueuePop(q);QueuePop(q);QueuePop(q);
}void TestOther(Queue* q)
{QueueInit(q);QueuePush(q, 2);QueuePush(q, 3);QueuePush(q, 4);QueuePush(q, 5);printf("size == %d And Front == %d And Tail == %d\n", QueueSize(q),QueueFront(q),QueueBack(q));QueuePop(q);printf("size == %d And Front == %d And Tail == %d\n", QueueSize(q), QueueFront(q), QueueBack(q));QueuePop(q);printf("size == %d And Front == %d And Tail == %d\n", QueueSize(q), QueueFront(q), QueueBack(q));QueueDestroy(q);
}int main()
{Queue q;//TestPushAndPop(&q);TestOther(&q);return 0;
}
好啦,uu们,栈和队列的这部分滴详细内容博主就讲到这里啦,如果uu们觉得博主讲的不错的话,请动动你们滴小手给博主点点赞,你们滴鼓励将成为博主源源不断滴动力,同时也欢迎大家来指正博主滴错误~

