栈
栈的概念和结构
栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
栈的实现
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
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 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);//栈中元素个数
Stack.c
#include"Stack.h"
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->top = 0;
pst->capacity = 0;
}//初始化,a置空,top,capacity赋值0,top表示栈顶元素的下一位,capacity表示栈容量,若top初始化为-1,则top表示栈顶元素的位置,这里将top赋值0。
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->capacity = 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 (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x;
pst->top++;
}//入栈先判断容量是否足够,不过就动态开辟内存空间,开辟失败则exit(-1)退出程序,最后top++
void STPop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
pst->top--;
}//出栈直接使top--。
STDataType STTop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
return pst->a[pst->top - 1];
}//栈顶元素返回top-1位的元素
bool STEmpty(ST* pst)
{
assert(pst);
return pst->top == 0;
}//pst->top为零返回true,栈为空,否则返回false,栈不为空
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}//栈的容量大小是top的值,因为数组下标从零开始
test.c
#include"Stack.h"
int main()
{
ST s;
STInit(&s);
STPush(&s, 1);
STPush(&s, 4);
STPush(&s, 3);
STPush(&s, 2);
STPush(&s, 7);
STPop(&s);
while (!STEmpty(&s))
{
printf("%d ", STTop(&s));
STPop(&s);
}
return 0;
}
队列
队列的概念和结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 。出队列:进行删除操作的一端称为队头。
队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
Queue.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
typedef struct QueueNote
{
struct QueueNode* next;
QDataType val;
}QN;
typedef struct Queue
{
QN* phead;
QN* ptail;
int size;
}Queue;//将队列的头尾节点和队列长定义到一个新的结构体中,减少找尾节点的麻烦。
void QInit(Queue* pq);//初始化
void QDestroy(Queue* pq);//销毁
void QPush(Queue* pq, QDataType x);//入队
void QPop(Queue* pq);//出队
bool QEmpty(Queue* pq);//判断队列是否为空
int size(Queue* pq);//队列大小
QDataType HeadData(Queue* pq);//队首元素
QDataType TailData(Queue* pq);//队尾元素
Queue.c
#include"Queue.h"
void QInit(Queue* pq)
{
assert(pq);
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
void QDestroy(Queue* pq)
{
assert(pq);
QN* cur = pq->phead;
while (cur)
{
QN* next = cur->next;
free(cur);
cur = next;
}
pq->phead = pq->ptail=NULL;
pq->size = 0;
}
void QPush(Queue* pq,QDataType x)
{
assert(pq);
QN* newnode = (QN*)malloc(sizeof(QN));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->val = x;
newnode->next = NULL;
if (pq->phead == NULL)
{
pq->phead = pq->ptail = newnode;
}
else {
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}//入队时首先初始化新节点,再判断队列中是否有元素,没有直接给首尾赋值为新节点,有则实现尾插,最后让新节点成为新的尾
void QPop(Queue* pq)
{
assert(pq);
assert(pq->phead);
if (pq->phead->next == NULL)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
QN* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
pq->size--;
}//出队注意如果首尾重合,释放首节点后要将首尾一起置空,尾不要忘记置空,防止野指针
QDataType HeadData(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->phead->val;
}
QDataType TailData(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->ptail->val;
}
bool QEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL;
}
int size(Queue* pq)
{
assert(pq);
return pq->size;
}
test.c
#include"Queue.h"
int main()
{
Queue q;
QInit(&q);
QPush(&q, 1);
QPush(&q, 4);
QPush(&q, 3);
QPush(&q, 6);
QPush(&q, 7);
QPop(&q);
printf("%d ", HeadData(&q));
printf("%d ",TailData(&q));
QDestroy(&q);
return 0;
}