目录
1.栈
栈:其数据的存储模式是,后进先出,如下面的筹码一样,假如你一次只能拿取一个,那么你能拿的也就是顶上的筹码,而这种模式就是栈。
1、建立栈的基本单元
基本要素:包括一个存储数据的地方,一个显示已经有多少数的地方,一个容量大小的地方(存储的方式如果是固定的那选用数组,如果需要动态开辟空间就选用指针数组)
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}Stack;
2、初始化栈
外部接受的话,定义一个栈的指针如何传入指针即可(满足改变哪个变量,传入该变量对应的指针,通过函数调用进行改变,所以这里传入栈的指针)
操作:指针指空,容量和个数定义为0
void StackInit(Stack* ps)
{
assert(ps);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
3、入栈
注意的是,如果容量和数量一致时说明栈空间已经满了,所以我们需要扩容
操作:判断是否要扩容,将最上方的数赋值,加一已有数量
void StackPush(Stack* ps, StackType x)
{
assert(ps);
if (ps->top == ps->capacity)//扩容
{
int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
ps->capacity = newCapacity;
STDataType* ret = (STDataType*)realloc(ps->a, newCapacity * sizeof(StackType));
if (ret == NULL)
{
perror("malloc fail");
exit(-1);
}
ps->a = ret;
}
ps->a[ps->top] = x;
ps->top++;
}
4、出栈
因为控制数多少的边界靠的是已有数多少决定,只操作已有数的内容,因此我们只需要改变栈中已有多少数的大小即可,把已有数减一
void StackPop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
5、查看栈第一个的值和查看数量
说明:top-1就是头一个值
StackType StackTop(Stack* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
说明:top就是有多少数
int StackSize(Stack* ps)
{
assert(ps);
return ps->top;
}
6、判空
说明:已有数等于0就是空
bool StackEmpty(Stack* ps)
{
assert(ps);
return ps->top == 0;
}
7、销毁栈
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
2.队列
队列:如图一样,先来先出
1、建立队列的基本单元
因为如果头删会比较麻烦,所以考虑使用链表的形式存储,包含头尾指针方便操作
typedef struct QListNode
{
struct QListNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
2、初始化
void QueueInit(Q_print* pf)
{
assert(pf);
pf->head = NULL;
pf->tail = NULL;
pf->size = 0;
}
3、入队
参考链表的push,在尾处链接一个队列的元素
void QueuePush(Q_print* pf, QueueType x)
{
assert(pf);
Queue* tmp = (Queue*)malloc(sizeof(Queue));
if (tmp == NULL)
{
perror("malloc fail");
exit(-1);
}
tmp->val = x;
tmp->next = NULL;
if (pf->head == NULL)
{
pf->head = pf->tail = tmp;
}
else
{
pf->tail->next = tmp;
pf->tail = pf->tail->next;
}
pf->size++;
}
4、出队
头指针指向下一个,释放原先的元素
void QueuePop(Q_print* pf)
{
assert(pf);
assert(!QueueEmpty(pf));
Queue* cur = pf->head;
pf->head = pf->head->next;
free(cur);
pf->size--;
}
5、判空
说明:头指针是否有所指向
bool QueueEmpty(Q_print* pf)
{
return pf->head == NULL;
}
6、获取头一个元素和尾元素
QueueType QueueFront(Q_print* pf)
{
assert(pf);
assert(!QueueEmpty(pf));
return pf->head->val;
}
QueueType QueueBack(Q_print* pf)
{
assert(pf);
assert(!QueueEmpty(pf));
Queue* cur = pf->head;
while (cur->next)
{
cur = cur->next;
}
return cur->val;
}
7、队列个数
int QueueSize(Q_print* pf)
{
assert(pf);
assert(!QueueEmpty(pf));
return pf->size;
}
8、销毁队列
void QueueDestroy(Q_print* pf)
{
assert(pf);
Queue* cur = pf->head;
if (cur)
{
pf->head = pf->head->next;
free(cur);
}
pf->head = pf->tail = NULL;
pf->size = 0;
}