前言:内容包括-栈的实现,队列的实现
目录
栈
栈只允许在固定的一端进行插入删除元素的操作,插入删除元素的一端称作栈顶,另一端称作栈底
简而言之,入数据在栈顶,出数据也在栈顶 ,元素后进先出
栈的实现:
栈可以使用数组和链表实现,但是数组的实现更优,因为数组的尾插效率很高,同时也完美符合在固定的一端进行插入和删除数据,下面以动态增长的数组实现栈:
实现栈的:初始化,销毁,入栈,出栈,得到栈顶元素,判空,得到有效数据的个数
Stack.h:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int STDatatype;//元素类型
typedef struct Stack//栈类型
{
STDatatype* a;//一块数组空间的地址
int top;
int capacity;
}ST;
void STInit(ST* pst);
void STDestroy(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 STInit(ST* pst)
{
assert(pst);//断言,确保pst不为空
pst->a = NULL;
pst->top = 0;//top指向栈顶元素的下一个位置
//若是初始化top=-1,则top指向栈顶元素
pst->capacity = 0;
}
栈的销毁:
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = 0;
pst->capacity = 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, newcapacity * sizeof(STDatatype));
if (tmp == NULL)
{
perror("realloc fail");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x;//插入数据
pst->top++;
}
栈满则需要先扩容再插入元素
扩容使用realloc,扩容一般增至原空间的2倍
需要注意的是:若是原来没有空间,则需要使用malloc先开4个空间,此时的a(数组的空间地址)是NULL,则realloc就相当于malloc,开辟出4个空间
出栈操作:
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];//top指向的是栈顶元素的下一个位置,top-1才是栈顶元素的下标
}
判断栈空:
bool STEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}
有效元素的个数:
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
队列
在队尾插入数据,在队头删除数据,元素先进先出
队列的实现:
队列也可以使用数组,链表实现,但是链表的结构更优,因为要在队头出数据,即要头删,数组的头删效率很低
实现队列的:初始化,销毁,入队,出队,获取队头数据,获取队尾数据,判空,有效元素个数
Queue.h:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
typedef struct QueueNode//队列中的每个节点
{
struct QueueNode* 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);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
队列的初始化:
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
队列的销毁:
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->phead;
while (cur)//遍历销毁每个节点
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
入队操作:
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));//开辟一个节点
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->data = x;
newnode->next = NULL;
if (pq->ptail == NULL)//若是队列为空
{
assert(pq->phead == NULL);
pq->phead = pq->ptail = newnode;
}
else//队列不为空,尾插
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
出队操作:
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));//若队列为空,不能进行删除操作
if (pq->phead->next == NULL)//只有一个节点
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else//多个节点,即头删
{
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
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;
}
队列判空:
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
}
有效元素的个数:
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}