目录
栈
栈的特点
是后进先出,像是蒸包子的笼屉最先放最底层的包子,拿的时候却是从最上面开始拿掉。
栈是一个特殊的线性表,在固定的位置插入删除数据,一端为栈顶负责入栈和出栈,另一端为栈底
如1,2,3,4,5,6,是这样入栈的,出栈则是6,5,4,3,2,1(不一定)
结果也可以是1,2,3,4,5,6等等,这就是入栈与出栈的顺序控制了
栈的实现
栈的实现可以由数组或单链表来完成
当用单链表来实现栈时一般使用头插法,链表尾部作栈底,链表头部作栈顶,而尾插法效率过低不宜使用,链表的高速缓存效率低
而使用数组来实现栈时感觉非常符合栈的特性,使用尾插尾删,但是它的缺点是需要扩容,用realloc函数扩容时很大可能会异地扩容,影响效率,不过数组(顺序表)在高速缓存中效率高。因为是连续的空间,所以优先选择数组来实现栈
#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);
//判空
bool StEmpty(St* pst);
//入栈
void StPush(St* pst,StDatatype x);
//出栈
void StPop(St* pst);
//栈顶元素
StDatatype StTop(St* pst);
//返回长度
int StSize(St* pst);
//初始化
void StInit(St* pst)
{
//初始化不开辟空间
assert(pst);
pst->a = NULL;
pst->top = 0;
pst->capacity = 0;
}
//销毁
void StDestroy(St* pst)
{
assert(pst);
free(pst->a);
pst->top = pst->capacity = 0;
}
//判空
bool StEmpty(St* pst)
{
assert(pst);
return pst->top == 0;
}
//入栈
void StPush(St* pst, StDatatype x)
{
//尾插
assert(pst);
//增容利用realloc既可以创建空间又可以扩容
if (pst->top == pst->capacity)
{
int newcpcy = pst->capacity == 0 ? 4:pst->capacity*2;
StDatatype* end = (StDatatype*)realloc(pst->a,newcpcy*sizeof(StDatatype));
if (end == NULL)
{
perror("realloc fail");
return;
}
pst->a= end;
pst->capacity = newcpcy;
}
pst->a[pst->top] = x;
pst->top++;
}
//出栈
void StPop(St* pst)
{
assert(pst);
pst->top--;
}
//返回栈顶元素
StDatatype StTop(St* pst)
{
assert(pst);
assert(!StEmpty(pst));
return pst->a[pst->top-1];
}
//返回长度
int StSize(St* pst)
{
assert(pst);
assert(!StEmpty(pst));
return pst->top;
}
队列
队列的特点
与栈相反队列则是先进先出
队列固定入队列在队尾,出队列在队头
如图1,2,3,4,5
队列的实现
队列也可以用数组或者链表来实现
但是优先选择效率较高的来实现
首先数组实现的话尾进头出,每次出队列数组都需要移动数据来覆盖队头的数据,效率诋
而用链表来实现的话无论是从队头出队列或是从队尾进队列都只需要重新链接一下节点就好了
相比之下用链表来实现队列更加合适
//用链表创建一个队列
//首先创建一个链表结构体
typedef int LTDatatype;
typedef struct LTNode
{
//下一个节点
struct LTNode* next;
//存放数据
LTDatatype val;
}LTNode;
//再创建一个队列结构体成员
typedef struct Queue
{
//队头
LTNode* phead;
//队尾
LTNode* ptail;
//队长
int size;
}Queue;
//初始化
void QuInit(Queue* obj);
//入队
void QuPush(Queue* obj, LTDatatype x);
//出队
void QuPop(Queue* obj);
//判空
bool QuEmpty(Queue* obj);
//销毁
void QuDestroy(Queue* obj);
//返回队头数据
LTDatatype QuFront(Queue* obj);
//返回队尾数据
LTDatatype QuBack(Queue* obj);
//返回队长
int Qusize(Queue* obj);
//队列实现
//队列初始化
void QuInit(Queue* obj)
{
assert(obj);
obj->phead = NULL;
obj->ptail = NULL;
obj->size = 0;
}
//队列销毁
void QuDestroy(Queue* obj)
{
assert(obj);
LTNode* Node = obj->phead;
while (Node)
{
LTNode* st = Node->next;
free(Node);
Node = st;
}
obj->phead = obj->ptail = NULL;
obj->size = 0;
}
//队列判空
bool QuEmpty(Queue* obj)
{
assert(obj);
return obj->size == 0;
}
//入队列
void QuPush(Queue* obj,LTDatatype x)
{
assert(obj);
LTNode* Node = (LTNode*)malloc(sizeof(LTNode));
if (Node == NULL)
{
perror("malloc fail");
return;
}
Node->val = x;
Node->next = NULL;
//节点为空
if (obj->phead == NULL)
{
//判断尾节点可能与头结点不同
assert(obj->ptail==NULL);
obj->phead = obj->ptail = Node;
}
//节点不为空
else
{
obj->ptail->next = Node;
obj->ptail = Node;
}
obj->size++;
}
//出队列
void QuPop(Queue* obj)
{
assert(obj);
//头删
//防止ptail成为野指针
if (obj->phead->next == NULL)
{
free(obj->phead);
//注意置空
obj->phead = NULL;
obj->ptail = NULL;
obj->size--;
}
else
{
LTNode* NewNode = obj->phead;
obj->phead = NewNode->next;
free(NewNode);
obj->size--;
}
}
//查看队头数据
LTDatatype QuFront(Queue* obj)
{
assert(obj);
assert(!QuEmpty(obj));
return obj->phead->val;
}
//返回队尾数据
LTDatatype QuBack(Queue* obj)
{
assert(obj);
assert(!QuEmpty(obj));
return obj->ptail->val;
}
//队长
int Qusize(Queue* obj)
{
assert(obj);
return obj->size;
}