一.栈
栈:⼀种特殊的线性表,其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作 的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。栈和顺序表具有很高的相似性,因此这里不进行详细的讲解。
补充
栈和顺序表虽然很相似但是栈的出栈不能通过遍历,因为栈的出栈是从栈顶到栈底的,需要依次出栈顶元素。
while (!StEmpty(&st))
{
typedate data = StTop(&st);
printf("%d ", data);
StPop(&st);
}
二.队列
队列:只允许在⼀端进⾏插⼊数据操作,在另⼀端进⾏删除数据操作的特殊线性表,队列具有先进先 出FIFO(First Inc First Out)。
数组与链表在队列中的优越性:使⽤链表的结构实现更优⼀些,因为如果使⽤数组的结构,出队 列在数组头上出数据,效率会⽐较低。
三.后附代码
栈
stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int typedate;
typedef struct stack
{
typedate * arr;
int capacity;
int top;//相当于顺序的size
}ST;
//初始化
void StInit(ST*st);
// 插入
void StPush(ST* st,typedate x);
//判断是否为空
bool StEmpty(ST* st);
// 出栈
void StPop(ST* st);
//取栈顶元素
typedate StTop(ST* st);
//销毁
void StDestory(ST* st);
stack.c
#include"Stack.h"
void StInit(ST* st)
{
assert(st);
st->arr = NULL;
st->capacity = st->top = 0;
}
// 插入
void StPush(ST* st, typedate x)
{
assert(st);
//判断空间是否满足
if (st->capacity == st->top)
{
int newcapacity = st->capacity == 0 ? 4 : 2 * st->capacity;
typedate*temp = (typedate*)realloc(st->arr,sizeof(typedate)*newcapacity);
if (temp == NULL)
{
perror("fail!!!");
exit(1);
}
st->arr = temp;
st->capacity = newcapacity;
}
st->arr[st->top++] = x;
}
//判断是否为空
bool StEmpty(ST* st)
{
assert(st);
return st->top == 0;
}
// 出栈
void StPop(ST* st)
{
assert(st);
assert(!StEmpty(st));
--st->top;
}
//取栈顶元素
typedate StTop(ST* st)
{
assert(st);
assert(!StEmpty(st));
return st->arr[st->top - 1];
}
//销毁
void StDestory(ST* st)
{
assert(st);
if (st->arr)
{
free(st->arr);
}
st->arr = NULL;
st->capacity = st->top = 0;
}
test.c
#include"Stack.h"
void test()
{
ST st;
StInit(&st);
//初始化
StInit(&st);
// 插入
StPush(&st, 1);
StPush(&st, 2);
StPush(&st, 3);
StPush(&st, 4);
StPush(&st, 5);
//打印
while (!StEmpty(&st))
{
typedate data = StTop(&st);
printf("%d ", data);
StPop(&st);
}
//销毁
StDestory(&st);
}
int main()
{
test();
return 0;
}
队列
Queue.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//指向节点的
typedef int typedate;
typedef struct QueueNode
{
typedate date;
struct QueueNode* next;
}QNode;
//指向队列的两个指针
typedef struct Queue
{
QNode* pphead;
QNode* tail;
int size;
}Qu;
//队列初始化
void QueueInit(Qu* pq);
//销毁队列
void QueueDestory(Qu* pq);
//判断是否为空
bool QueueEmpty(Qu* pq);
//入队列
void QueuePush(Qu* pq, typedate x);
//出队
void QueuePop(Qu* pq);
//取队顶元素
typedate QueueTop(Qu* pq);
//取队尾数据
typedate QueueBack(Qu* pq);
//队列有效元素个数
int QueueSize(Qu* pq);
//销毁队列
void QueueDestroy(Qu* pq);
Queue.c
#include"Queue.h"
//队列初始化
void QueueInit(Qu* pq)
{
assert(pq);
pq->pphead = pq->tail = NULL;
pq->size = 0;
}
//入队列
void QueuePush(Qu* pq, typedate x)
{
assert(pq);
//申请节点
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail!!!");
exit(1);
}
newnode->date = x;
newnode->next = NULL;
//第一种情况没有元素的情况
if (pq->pphead == NULL)
{
pq->pphead = pq->tail = newnode;
}
else
{
pq->tail->next=newnode;
pq->tail = pq->tail->next;
}
}
//判断是否为空
bool QueueEmpty(Qu* pq)
{
assert(pq);
return pq->pphead ==NULL && pq->tail == NULL;
}
//出队
void QueuePop(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
//两种情况
if (pq->pphead == pq->tail)
{
free(pq->pphead);
pq->pphead = pq->tail = NULL;
}
else
{
QNode* next = pq->pphead->next;
free(pq->pphead);
pq->pphead = next;
}
--pq->size;
}
//取队顶元素
typedate QueueTop(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->pphead->date;
}
//取队尾数据
typedate QueueBack(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->date;
}
//队列有效元素个数
int QueueSize(Qu* pq)
{
assert(pq);
return pq->size;
}
//销毁队列
void QueueDestroy(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QNode* pcur = pq->pphead;
while (pcur)
{
QNode* next = pcur->next;
free(pcur);
pcur = next;
}
pq->pphead = pq->tail = NULL;
pq->size = 0;
}
test.c
#include"Queue.h"
void Queuetest()
{
Qu q;
//队列初始化
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePop(&q);
printf("head:%d\n", QueueTop(&q));
printf("tail:%d\n", QueueBack(&q));
printf("size:%d\n", QueueSize(&q));
QueueDestroy(&q);
}
int main()
{
Queuetest();
return 0;
}
总结
栈适用于后进先出方式处理数据,并且允许在任何时候只能访问或修改位于其顶端项。队列适用于先进先出方式处理数据,并且允许在任何时候只能访问或修改排在其前端各项。虽然它们有不同之处,但都是非常重要且应用广泛。最后期待各位大佬的指正,留下一键三连(点赞,收藏,关注)。