目标10分钟写出栈和队列
重点在注释
栈:
Stack.h
//Stack.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
STDataType* a; //a是数组,这里用指针和方括号都可以
int top; // 栈顶
int capacity; // 容量
}Stack;
// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);
Stack.c
//Stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
void StackInit(Stack* ps) // 初始化栈
{
assert(ps); //不能是空指针
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4); //为数组申请空间
if (ps->a == NULL) //申请失败
{
perror("malloc fail");
exit(-1);
}
ps->top = 0;
ps->capacity = 4;
}
void StackPush(Stack* ps, STDataType x) // 入栈
{
assert(ps);
if (ps->top == ps->capacity) //容量满了需要扩容
{
STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType)); //容量翻倍
if (tmp == NULL) //申请失败报错
{
perror("realloc fail");
exit(-1);
}
ps->a = tmp; //有可能在原空间扩容,也有可能新开辟空间,需要指向新指针
ps->capacity *= 2; //容量乘二
}
ps->a[ps->top] = x; //在相应位置存放数据 a[top]
ps->top++; //top加1
}
void StackPop(Stack* ps) // 出栈
{
assert(ps);
assert(!StackEmpty(ps)); //栈不能为空
ps->top--;
}
STDataType StackTop(Stack* ps) // 获取栈顶元素
{
assert(ps);
assert(!StackEmpty(ps)); //为空的时候top已经为0了,再减一就访问a[-1]了,越界了,所以要断言
return ps->a[ps->top - 1]; //入栈时候先存储再加1,需要减1
}
int StackSize(Stack* ps) // 获取栈中有效元素个数
{
assert(ps);
return ps->top; //top从零开始的,存储完之后加1
}
int StackEmpty(Stack* ps) // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
{
assert(ps);
return ps->top == 0; //为空返回1,不为空返回0
}
void StackDestroy(Stack* ps) // 销毁栈
{
assert(ps); //不能为空指针
free(ps->a); //释放之前申请的数组空间
ps->a = NULL; //让数组指向空指针
ps->top = ps->capacity = 0; //把栈顶和容量都为0
}
test.c
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
void TestStack1()
{
Stack st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
StackPush(&st, 5);
printf("size:%d\n", StackSize(&st)); // 不关心底层实现
printf("size:%d\n", st.top); // 关心
//printf("size:%d\n", st.top + 1); // 关心
StackPop(&st);
StackPop(&st);
StackPop(&st);
StackPop(&st);
//StackPop(&st);
//StackPop(&st);
printf("%d\n", StackTop(&st));
StackDestroy(&st);
}
int main()
{
TestStack1();
return 0;
}
队列 :
Queue.h
//Queue.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int QDataType; //这样不用每次都写 int QDataType
typedef struct QueueNode //定义结点
{
QDataType data; //存放数据
struct QueueNode* next; //存放指针指向下一个结点
}QNode;
typedef struct Queue //凡是结构都写一下typedef,不然每次都写struct很难受
{
QNode* head;
QNode* tail;
int size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq); //头部删除
QDataType QueueFront(Queue* pq); //获取队列头部元素
QDataType QueueBack(Queue* pq); // 获取队列队尾元素
bool QueueEmpty(Queue* pq); //为空为1,不为空为0
int QueueSize(Queue* pq); // 获取队列中有效元素个数
Queue.c
//Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
pq->size=0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* del = cur;
cur = cur->next;
free(del);
//del = NULL; //这个不用置空,因为del是局部变量,出while就销毁了
}
pq->head = pq->tail = NULL; //free之后变为野指针,要置空
pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x) //尾插
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
//新建一个结点,由于只有这个函数需要开辟内存,所以不用写BuyNode函数
if (newnode == NULL) //开辟失败
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (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(!QueueEmpty(pq));
if (pq->head->next == NULL) //只有一个结点
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* del = pq->head; //保存当前节点
pq->head = pq->head->next; //后移
free(del);
}
pq->size--;
}
QDataType QueueFront(Queue* pq) // 获取队列头部元素
{
assert(pq);
assert(!QueueEmpty(pq)); //不能为空
return pq->head->data;
}
QDataType QueueBack(Queue* pq) //获取队列队尾元素
{
assert(pq);
assert(!QueueEmpty(pq)); //不能为空
return pq->tail->data;
}
bool QueueEmpty(Queue* pq) //为空为1,不为空为0
{
assert(pq);
return pq->head == NULL && pq->tail == NULL;
}
int QueueSize(Queue* pq) //获取队列中有效元素个数
{
assert(pq);
//int size = 0;
//QNode* cur = pq->head;
//while (cur) //size的时间复杂度是o(n),可以优化一下,在结构体中定义一个size
//{
// cur = cur->next;
// ++size;
//}
//return size;
return pq->size;
}
test.c
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
void TestQueue()
{
Queue q;
QueueInit(&q);
QueuePush(&q,1);
QueuePush(&q,2);
printf("%d\n", QueueFront(&q));
QueuePop(&q);
QueuePush(&q,3);
QueuePush(&q,4);
printf("%d\n", QueueSize(&q));
printf("%d\n", QueueEmpty(&q)); //0为假,不为空
printf("%d\n", QueueFront(&q));
printf("%d\n", QueueBack(&q));
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q)); //获取队列头部元素
QueuePop(&q); //头部删除
}
printf("\n");
QueueDestroy(&q);
}
int main()
{
TestQueue();
return 0;
}