栈:
一种特殊的线性表,只允许在一端进行插入和删除。
进行插入和删除的一端称为栈顶,另一端称为栈底。
栈中的数据元素遵循后进先出的原则。
栈可以用数组或链表实现,相对而言用数组更好,因为数组尾删尾插更方便。
//顺序结构实现栈
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;//top初始为0表示栈顶下一个,初始为-1表示栈顶
int capacity;//容量
}ST;
//初始化栈
void STInit(ST* ps);
//销毁栈
void STDestroy(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 STInit(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);//开辟初始空间
if (ps->a == NULL)//判断是否开辟成功
{
perror("malloc");//如果失败,显示报错信息
return;
}
ps->capacity = 4;//初始化容量
ps->top = 0;//初始化top,top表示栈顶下一个
}
//销毁栈
void STDestroy(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
free(ps->a);
ps->a = NULL;
ps->capacity = 0;
ps->top = 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");//如果失败,显示报错信息
return;
}
ps->a = tmp;//扩容成功,把tmp赋给a
ps->capacity *= 2;//更新容量
}
ps->a[ps->top] = x;//尾插
ps->top++;//top指向栈顶下一个
}
//出栈
void STPop(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
assert(!STEmpty(ps));//保证栈不为空,才能删除
ps->top--;//更新top
}
//获取栈的数据个数
int STSize(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
return ps->top;//top就是栈的数据个数
}
//栈的判空
bool STEmpty(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
return ps->top == 0;//如果top为0则返回true,否则返回false
}
//获取栈顶元素
STDataType STTop(ST* ps)
{
assert(ps);//如果size为0则返回true,否则返回false
assert(!STEmpty(ps));//保证栈不为空,才有栈顶元素
return ps->a[ps->top - 1];//返回栈顶元素
}
#pragma once
#include
#include
#include
#include
//顺序结构实现栈
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;//top初始为0表示栈顶下一个,初始为-1表示栈顶
int capacity;//容量
}ST;
//初始化栈
void STInit(ST* ps);
//销毁栈
void STDestroy(ST* ps);
//入栈
void STPush(ST* ps, STDataType x);
//出栈
void STPop(ST* ps);
//获取栈的数据个数
int STSize(ST* ps);
//栈的判空
bool STEmpty(ST* ps);
//获取栈顶元素
STDataType STTop(ST* ps);
#include"stack.h"
//初始化栈
void STInit(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);//开辟初始空间
if (ps->a == NULL)//判断是否开辟成功
{
perror("malloc");//如果失败,显示报错信息
return;
}
ps->capacity = 4;//初始化容量
ps->top = 0;//初始化top,top表示栈顶下一个
}
//销毁栈
void STDestroy(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
free(ps->a);
ps->a = NULL;
ps->capacity = 0;
ps->top = 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");//如果失败,显示报错信息
return;
}
ps->a = tmp;//扩容成功,把tmp赋给a
ps->capacity *= 2;//更新容量
}
ps->a[ps->top] = x;//尾插
ps->top++;//top指向栈顶下一个
}
//出栈
void STPop(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
assert(!STEmpty(ps));//保证栈不为空,才能删除
ps->top--;//更新top
}
//获取栈的数据个数
int STSize(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
return ps->top;//top就是栈的数据个数
}
//栈的判空
bool STEmpty(ST* ps)
{
assert(ps);//断言,保证传入指针不为空,方便后面解引用
return ps->top == 0;//如果top为0则返回true,否则返回false
}
//获取栈顶元素
STDataType STTop(ST* ps)
{
assert(ps);//如果size为0则返回true,否则返回false
assert(!STEmpty(ps));//保证栈不为空,才有栈顶元素
return ps->a[ps->top - 1];//返回栈顶元素
}
队列:
一种特殊的线性表,只允许在一端插入数据,另一端删除数据,尾插头删。
队列可以用数组或链表实现,相对而言用链表更好,因为数组的头删要挪动数据,效率较低。
//链式结构实现队列
typedef int QDataType;
//节点声明
typedef struct QueueNode//结构体类型声明,并没有创建结构体变量
{
QDataType data;
struct QueueNode* next;//单链表实现
}QNode;
//封装指针和size,方便传参,直接传一个结构体指针,不用传多个参数
typedef struct Queue
{
QNode* head;//头指针,指向节点
QNode* tail; //尾指针,指向节点
int size; //数据个数
}Queue;
//初始化队列
void QueueInit(Queue* q);
//销毁队列
void QueueDestroy(Queue* q);
//入队列
void QueuePush(Queue* q, QDataType x);
//出队列
void QueuePop(Queue* q);
//获取头部元素
QDataType QueueFront(Queue* q);
//获取队尾元素
QDataType QueueBack(Queue* q);
//队列数据个数
int QueueSize(Queue* q);
//队列判空
bool QueueEmpty(Queue* q);
//初始化队列
void QueueInit(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
q->head = q->tail = NULL;//初始化头指针和尾指针
q->size = 0;//初始化数据个数
}
//销毁队列
void QueueDestroy(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
QNode* cur = q->head;
//遍历队列
while (cur)
{
//逐个销毁
QNode* next = cur->next;
free(cur);
cur = next;
}
q->head = q->tail = NULL;//头尾指针置空
q->size = 0;//数据个数清零
}
//入队列
void QueuePush(Queue* q, QDataType x)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
QNode* newnode = (QNode*)malloc(sizeof(QNode));//动态申请新结点
if (newnode == NULL)//判断是否申请成功
{
perror("malloc");//如果失败,显示报错信息
return;
}
newnode->data = x;//初始化新结点数据
newnode->next = NULL;//初始化新结点指针
if (q->tail == NULL)//如果是空队列的情况
{
assert(q->head == NULL);//此时头尾指针必然都为空,否则出错
q->head = q->tail = newnode;//头尾指针都指向新结点
}
else//不是空队列
{
q->tail->next = newnode;//尾插
q->tail = newnode;//更新尾指针
}
q->size++;//更新数据个数
}
//出队列
void QueuePop(Queue* q)
{
assert(q && q->head);
//断言,防止传入指针为空,方便后面解引用;
//保证队列不为空,才能删除
//头删
QNode* first = q->head;
q->head = first->next;
free(first);
q->size--;//更新数据个数
if (q->head == NULL)//如果头删后队列为空
{
q->tail = NULL;//应该更新尾指针,防止野指针的情况
}
}
//获取头部元素
QDataType QueueFront(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
assert(!QueueEmpty(q));//保证队列不为空,才有头部元素
return q->head->data;
}
//获取队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
assert(!QueueEmpty(q));//保证队列不为空,才有尾部元素
return q->tail->data;
}
//队列数据个数
int QueueSize(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
return q->size;
}
//队列判空
bool QueueEmpty(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
return q->size == 0;//如果size为0则返回true,否则返回false
}
#pragma once
#include
#include
#include
#include
//链式结构实现队列
typedef int QDataType;
//节点声明
typedef struct QueueNode//结构体类型声明,并没有创建结构体变量
{
QDataType data;
struct QueueNode* next;//单链表实现
}QNode;
//封装指针和size,方便传参,直接传一个结构体指针,不用传多个参数
typedef struct Queue
{
QNode* head;//头指针,指向节点
QNode* tail; //尾指针,指向节点
int size; //数据个数
}Queue;
//初始化队列
void QueueInit(Queue* q);
//销毁队列
void QueueDestroy(Queue* q);
//入队列
void QueuePush(Queue* q, QDataType x);
//出队列
void QueuePop(Queue* q);
//获取头部元素
QDataType QueueFront(Queue* q);
//获取队尾元素
QDataType QueueBack(Queue* q);
//队列数据个数
int QueueSize(Queue* q);
//队列判空
bool QueueEmpty(Queue* q);
#include"queue.h"
//初始化队列
void QueueInit(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
q->head = q->tail = NULL;//初始化头指针和尾指针
q->size = 0;//初始化数据个数
}
//销毁队列
void QueueDestroy(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
QNode* cur = q->head;
//遍历队列
while (cur)
{
//逐个销毁
QNode* next = cur->next;
free(cur);
cur = next;
}
q->head = q->tail = NULL;//头尾指针置空
q->size = 0;//数据个数清零
}
//入队列
void QueuePush(Queue* q, QDataType x)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
QNode* newnode = (QNode*)malloc(sizeof(QNode));//动态申请新结点
if (newnode == NULL)//判断是否申请成功
{
perror("malloc");//如果失败,显示报错信息
return;
}
newnode->data = x;//初始化新结点数据
newnode->next = NULL;//初始化新结点指针
if (q->tail == NULL)//如果是空队列的情况
{
assert(q->head == NULL);//此时头尾指针必然都为空,否则出错
q->head = q->tail = newnode;//头尾指针都指向新结点
}
else//不是空队列
{
q->tail->next = newnode;//尾插
q->tail = newnode;//更新尾指针
}
q->size++;//更新数据个数
}
//出队列
void QueuePop(Queue* q)
{
assert(q && q->head);
//断言,防止传入指针为空,方便后面解引用;
//保证队列不为空,才能删除
//头删
QNode* first = q->head;
q->head = first->next;
free(first);
q->size--;//更新数据个数
if (q->head == NULL)//如果头删后队列为空
{
q->tail = NULL;//应该更新尾指针,防止野指针的情况
}
}
//获取头部元素
QDataType QueueFront(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
assert(!QueueEmpty(q));//保证队列不为空,才有头部元素
return q->head->data;
}
//获取队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
assert(!QueueEmpty(q));//保证队列不为空,才有尾部元素
return q->tail->data;
}
//队列数据个数
int QueueSize(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
return q->size;
}
//队列判空
bool QueueEmpty(Queue* q)
{
assert(q);//断言,防止传入指针为空,方便后面解引用
return q->size == 0;//如果size为0则返回true,否则返回false
}