栈(Stack)
一、栈的基本概念
栈:栈是只允许在一端插入和删除数据的线性表,允许插入和删除的一端称作栈顶,另一端称作栈底。我们将插入数据称作压栈/入栈/进栈,删除数据称作出栈。
栈的基本操作
- 对栈的初始化
- 对栈的判空
- 对栈的插入删除
- 读取栈顶元素
- 获取栈内元素个数
- 销毁栈
二、栈的基本功能和实现
1.栈的结构
用数组和链表都可以实现栈,但是数组在删除数据时优于链表。下面我们将实现数组栈。
typedef int STDataType;//元素的类型
typedef struct stack
{
STDataType* a;//存放数据的数组
int top;//栈顶
int capacity;//数组最大容量
}ST;
2.对栈的初始化
在对栈的初始化时,我们可以选着在开始就给一些空间,也可以在插入数据时再扩容。这里选择初始化时扩容。
void STinit(ST* p)
{
assert(p);//防止对空指针解引用
STDataType* p->a = (STDataType*)malloc(sizeof(STDataType) * 4);
if(p->a == NULL)
{
perror("malloc file");
exit(-1);
}
p->capacity = 4;
p->top = 0;
}
3.对栈的插入和删除
入栈时注意是否还有空间,没空间时需要扩容,而出栈时要注意是否还有数据可以删除。
//入栈
void STpush(ST* p, STDataType data)
{
assert(p);//防止对空指针解引用
if (p->top == p->capacity)//判断数据是否满了,满了则扩容
{
STDataType* newa = (STDataType*)realloc(p->a, sizeof(STDataType) * 2 * p->capacity);
if (!newa)
{
perror("malloc file");
exit(-1);
}
p->a = newa;
p->capacity *= 2;
}
p->a[p->top] = data;
p->top++;
}
//出栈
void STpop(ST* p)
{
assert(p);//防止对空指针解引用
assert(!STEmpty(p));//STEmpty函数是判断栈内是否为空,之后会有介绍
p->top--;
}
4.判断栈是否为空、返回栈顶元素和获取栈内元素个数
这三个函数非常简单,我就放在一起了
//栈是否为空
bool STEmpty(ST* p)
{
assert(p);
return p->top == NULL;
}
//读取栈顶元素
STDataType STtop(ST* p)
{
assert(p);
assert(!STEmpty(p));
return p->a[p->top-1];
}
//栈内元素个数
int STsize(ST* p)
{
assert(p);
return p->top;
}
虽然这三个函数很简单,但其他使用者在使用这个栈时可能并不清楚底层是这么实现的。有了这些函数,使用者就可以不用了解底层实现从而对栈操作。
5.销毁栈
void STDestory(ST* p)
{
assert(p);
assert(p->a);
free(p->a);
p->a = NULL;
p->capacity = 0;
p->top = 0;
}
队列(Queue)
一、队列的基本概念
队列:只允许在一段插入数据,在另一端删除数据。插入数据的一段称作队头,另一端称作队尾。
队列的基本操作
- 队列的初始化
- 队列的插入删除数据
- 查询队列元素个数
- 获取队头队尾元素
- 对队列的判空
- 队列的销毁
二、队列的基本功能和实现
1.队列的结构
和栈一样,数组和链表都可以实现队列,但是队列的删除放在头部,使用数组的话效率太低了,所以一般我们使用链表实现。
typedef int QueueDataType;//元素的类型
typedef struct Data//链表的节点
{
QueueDataType data;
struct Data* next;
}Data;
typedef struct Queue//队列
{
Data* head;//指向链表头元素
Data* tail;//指向链表尾元素
unsigned int size;//链表中元素的个数
}Queue;
2.队列的初始化
void QueueCreate(Queue* p)//创建队列
{
p = (Queue*)malloc(sizeof(Queue));
if (p == NULL)
{
perror("malloc fail");
exit(-1);
}
p->head = NULL;
p->tail = NULL;
p->size = 0;
}
3.对队列的插入和删除
//插入数据
void QueuePush(Queue* p, QueueDataType data)
{
assert(p);
Data* newdata = (Data*)malloc(sizeof(Data));
if (newdata == NULL)
{
perror("malloc file");
exit(-1);
}
newdata->data = data;
newdata->next = NULL;
if (p->head == NULL)//判断是不是第一次插入数据,第一次插入数据时,头指针等于尾指针
{
p->head = newdata;
p->tail = newdata;
}
else
{
p->tail->next = newdata;
p->tail = newdata;
}
p->size++;
}
//删除数据
void QueuePop(Queue* p)
{
assert(p);
assert(p->head);
Data* def = p->head;
p->head = p->head->next;
if (p->head == NULL)
{
p->tail = NULL;
}
free(def);
p->size--;
}
4.查询队列元素个数
unsigned int QueueSize(Queue* p)//返回数据个数
{
assert(p);
return p->size;
}
5.获取队头,队尾元素
QueueDataType QueueFront(Queue* p)//返回队首数据
{
assert(p);
assert(p->head);
return p->head->data;
}
QueueDataType QueueBack(Queue* p)//返回队尾数据
{
assert(p);
assert(p->tail);
return p->tail->data;
}
6.对队列的判空
bool QueueEmpty(Queue* p)//数据是否为空
{
assert(p);
return p->size == 0;
}
7.队列的销毁
void QueuePop(Queue* p)//删除数据
{
assert(p);
assert(p->head);
Data* def = p->head;
p->head = p->head->next;
if (p->head == NULL)
{
p->tail = NULL;
}
free(def);
p->size--;
}