Lesson4–栈和队列
【本节目标】
1.栈
2.队列
3.栈和队列面试题
一. 栈
1.1栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的的一端进行插入和删除操作的一端称为栈顶,另一端称为栈底
遵循:“先进后出的原则”
压栈:栈的插入数据叫做进栈/压栈,入数据在栈顶
出栈:栈的删除叫做出栈。出数据也在栈顶
1.2 栈的实现
栈的实现一般可以使用数组或者链表来实现,但是相对而言数组的结构实现更优一点。因为数组再尾部插入数据的代价比较小
//Stack.h
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
//这里也分静态栈和动态栈,但是这里我们以动态栈为主要
typedef int STDataType;
typedef struct stack
{
int* a; //这里我们的栈是用数组实现的
int top; //栈底
int capacity;//栈中的真实数据
}ST;//给结构体重新命名
void STInit(ST*ps);//向栈插入数据
void STDestory(ST* ps);//重置
void STPush(ST* ps,STDataType x);//插入数据
void STPop(ST* ps);//删除数据
int STsize(ST* ps);//栈中数据个数
bool STEmpty(ST* ps); //栈中数据是不是为空
STDataType STTop(ST* ps);//栈顶数据
//Stack.c
#define _CRT_SECURE_NO_WARNINGS
#include"Stack.h"
void STInit(ST* ps)//向栈插入数据
{
//这里我们先栈中插入元素,需要保证栈不是NULL;
assert(ps);
ps->a = (STDataType *)malloc(sizeof(STDataType) * 4);//开辟四个整形的空间
if (ps->a==NULL)
{
perror("malloc fail");
}
ps->capacity = 4;
ps->top = 0;//top 是指向栈顶元素的下一个位置
//ps->top = -1 top 是栈顶元素位置
}
void STDestory(ST* ps)//重置(销毁栈)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)//插入数据
{
assert(ps);
//我们在头插的时候需要考虑扩容的问题
if (ps->top == ps->capacity)
{
STDataType* tmp = (STDataType *)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc fail");
//exit(-1);
return ;
}
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
void STPop(ST* ps)//删除数据
{
assert(ps);
assert(!STEmpty(ps));//不等于空就删,等于空就停止
//if (ps->top == NULL)
//{
// return 0;
//}
//else
//{
// ps->top--;//这里我们就遵从了栈的后进先出
//}
ps->top--;//这里我们就遵从了栈的后进先出
}
int STsize(ST* ps)//栈中数据个数
{
assert(ps);
return ps->top;
}
bool STEmpty(ST* ps) //栈中数据是不是为空
{
assert(ps);
return ps->top == 0;
}
STDataType STTop(ST* ps)//返回栈顶数据
{
assert(ps);
assert(!(STEmpty(ps)));//为空就不能访问了
return ps->a[ps->top - 1];
}
//text.c
#define _CRT_SECURE_NO_WARNINGS
#include"Stack.h"
void test1()
{
ST st;//创建栈
STInit(&st);//初始化栈
STPush(&st, 1);
STPush(&st, 2);
STPush(&st, 3);
STPush(&st, 4);
STPush(&st, 5); //插入数据
//while (ps.top!=0)
while (!STEmpty(&st))//不为空的时候我们才来访问
{
printf("%d ", STTop(&st)); //访问栈区中的元素
STPop(&st); //删除头元素
}
STDestory(&st); //删除栈
}
void test2()
{
ST st;//创建栈
STInit(&st);//初始化栈
STPush(&st, 1);
printf("%d\n", STTop(&st)); //访问栈区中的元素
STPop(&st); //删除头元素
STPush(&st, 2);
printf("%d\n", STTop(&st)); //访问栈区中的元素
STPop(&st); //删除头元素
STPush(&st, 3);
printf("%d\n", STTop(&st)); //访问栈区中的元素
STPush(&st, 4);
printf("%d\n", STTop(&st)); //访问栈区中的元素
STPop(&st); //删除头元素
STPush(&st, 5); //插入数据
printf("%d\n", STTop(&st)); //访问栈区中的元素
}
int main()
{
test1();// 顺序插入,倒叙删除
//test2();//插入一个删除一个,或者插入两个删除
return 0;
}
二、队列
//queue.h
#pragma once
//这里我们来实现队列的
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef char QDatatype;
typedef struct QueueNode //链表
{
struct QueueNode* next;//说明其本质是指向吸引一个结构体的指针
QDatatype data;
}QNode;
typedef struct queue
{
QNode* head;//定义就是为了方便后期的操作
QNode* tail;//
int size;//确定队列中的元素
}Queue;
void QueueInit(Queue * pq);//初始化
void QueueDestory(Queue* pq);//重制
void QueuePush(Queue* pq,QDatatype x);//插入
void Queuepop(Queue* pq);//删除
int QueueSize(Queue* pq);//队列中的个数
bool QueueEmpty(Queue* pq);//判断队列是否为空
QDatatype QueueFront(Queue* pq);//头数值
QDatatype QueueBack(Queue* pq);//尾数值
//queue.c
#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"
void QueueInit(Queue* pq)//初始化
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueueDestory(Queue* pq)//重制
{
assert(pq);
QNode* cur = pq->head;//保存一下头指针
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->size = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq ,QDatatype x)//插入
{
//插入一个结点我们就需要来malloc
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return ;
}
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
//起始结点为NULL
assert(pq->tail == NULL);
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;//尾插
pq->tail = newnode;//更新尾节点
}
pq->size++;
}
void Queuepop(Queue* pq)//删除
{
assert(pq);
assert(pq->head != NULL);//判断是后为空,不为空才有删的必要
if (pq->head->next == NULL)
{
//只有一个结点
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
int QueueSize(Queue* pq)//队列中的个数
{
assert(pq);
return pq->size;
}
bool QueueEmpty(Queue* pq)//判断队列是否为空
{
assert(pq);
return pq->size == 0;
}
QDatatype QueueFront(Queue* pq)//头数值
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
QDatatype QueueBack(Queue* pq)//尾数值
{
assert(pq);
//这里我们就可以很好的利用了我们创建尾结点的作用
return pq->tail->data;
}
//text.c
#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"
int main()
{
Queue q;//创建一个点
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
QueuePush(&q, 6);
printf("%d\n", QueueFront(&q));//拿出头
printf("%d\n", QueueBack(&q));//拿出尾
printf("%d\n", QueueSize(&q));//拿出队列中的个数
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));//拿出头
Queuepop(&q); //删除
}
printf("\n");
printf("%d\n", QueueSize(&q));
return 0;
}
//以上就是对列的实现