目录
1.栈
1.1栈的概念
栈是一种特殊的线性表,它只能在固定的一段插入删除数据,插入删除数据的一端称为栈顶,另一端称为栈底。栈需要遵守后进先出LIFO(Last In First Out).
压栈:压栈/入栈是栈的入数据操作。从栈顶入数据。
出栈:出栈是栈的删除操作。从栈顶删除数据。
后进先出LIFO(Last In First Out)
1.2栈的实现
栈可以使用数组或链表来实现,这里我用数组实现,应为数组在尾部插入删除的效率更优。
定义
首先typedef一下数据类型,方便修改,使用动态数组来实现,top表示栈顶,capacity表示空间大小。
void STInit(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
void STDestroy(ST* pst);
初始化
capacity是栈的容量,top是数据位的下一位的下标。
void STInit(ST* pst)
{
pst->a = NULL;
pst->capacity = 0;
pst->Top = 0;
}
压栈
先断言一下是否为空指针,判断栈是否需要扩容,初始值给4后面按2倍扩容,最后把数据放入top下标,top++。
void STPush(ST* pst, STDataType x)
{
assert(pst);
if (pst->Top == pst->capacity)
{
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
if (NULL == tmp)
{
perror("realloc fail");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->Top] = x;
pst->Top++;
}
出栈
出栈就很简单了,判断一下是否空指针和栈是否为空,不为空就可以直接top--
void STPop(ST* pst)
{
assert(pst);
assert(!STEmpty(pst));
pst->Top--;
}
获取栈顶数据
因为top是数据位的下一位下标,所以要返回top之前那个下标的数据。
STDataType STTop(ST* pst)
{
assert(pst);
assert(!STEmpty(pst));
return pst->a[pst->Top-1];
}
获取栈的数据个数
int STSize(ST* pst)
{
assert(pst);
return pst->Top;
}
销毁栈
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = 0;
pst->Top = 0;
}
2.队列
2.1队列的概念
队列需要遵循的规则是先进先出FIFO(First In First Out),插入数据的是队尾,删除数据的是队头。
2.2队列的实现
队列也可以用数组和链表实现,因为数组的头部插入效率比较低所以这里选择链表实现队列。
定义结构
QNode是队列的单个节点,里面存储数据和下一个节点的指针
Queue是整个队列,里面存放队列的头,尾和数据个数。
typedef int QDataType;
typedef struct QNode
{
struct QNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
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);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
初始化
断言是否为空指针,把头和尾置空,大小设置为0,
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
队列的销毁
遍历链表free掉每个节点
void QueueDestroy(Queue* pq)
{
assert(pq);
while (pq->phead)
{
QNode* cur = pq->phead;
pq->phead = pq->phead->next;
free(cur);
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
入队
首先判断空间是否足够,不足就扩容,然后分情况讨论,如果链表为空头尾指针都指向nduan为空就把节点链接在最后。
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
newnode->next = NULL;
newnode->data = x;
if (pq->phead == 0)
{
assert(pq->ptail == NULL);
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = pq->ptail->next;
}
pq->size++;
}
判断队列是否为空
用头尾指针来判断,头尾指针都为空队列就为空,反之亦然。
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL && pq->ptail == NULL;
}
出队
出队操作要多一个判断链表是否为空。
也是分情况讨论,如果链表只有一个节点就要释放这个节点,把头尾指针置空,链表不为空就释放第一个节点并移动头指针。
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QNode* cur = pq->phead;
if (pq->phead->next == NULL)
{
free(cur);
pq->phead = pq->ptail = NULL;
}
else
{
pq->phead = pq->phead->next;
free(cur);
}
pq->size--;
}
获取队头数据
直接返回链表第一个节点的数据。
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->phead->data;
}
获取队尾数据
直接返回链表tail指针指向的数据。
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->ptail->data;
}
获取队列数据个数
直接返回size
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
3.源码
stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int Top;
int capacity;
}ST;
void STInit(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
void STDestroy(ST* pst);
stack.c
#include"Stack.h"
void STInit(ST* pst)
{
pst->a = NULL;
pst->capacity = 0;
pst->Top = 0;
}
bool STEmpty(ST* pst)
{
assert(pst);
return pst->Top == 0;
}
void STPush(ST* pst, STDataType x)
{
assert(pst);
if (pst->Top == pst->capacity)
{
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
if (NULL == tmp)
{
perror("realloc fail");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->Top] = x;
pst->Top++;
}
void STPop(ST* pst)
{
assert(pst);
assert(!STEmpty(pst));
pst->Top--;
}
STDataType STTop(ST* pst)
{
assert(pst);
assert(!STEmpty(pst));
return pst->a[pst->Top-1];
}
int STSize(ST* pst)
{
assert(pst);
return pst->Top;
}
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = 0;
pst->Top = 0;
}
queue.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
typedef struct QNode
{
struct QNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
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);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
queue.c
#include"queue.h"
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
while (pq->phead)
{
QNode* cur = pq->phead;
pq->phead = pq->phead->next;
free(cur);
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
newnode->next = NULL;
newnode->data = x;
if (pq->phead == 0)
{
assert(pq->ptail == NULL);
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = pq->ptail->next;
}
pq->size++;
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QNode* cur = pq->phead;
if (pq->phead->next == NULL)
{
free(cur);
pq->phead = pq->ptail = NULL;
}
else
{
pq->phead = pq->phead->next;
free(cur);
}
pq->size--;
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->phead->data;
}
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->ptail->data;
}
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL && pq->ptail == NULL;
}