学习目标:
- 栈的设计和实现
栈的特点:后进先出。
学习内容:
一、栈的头文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int STDataType;
//#define MAX 10
//typedef struct Stack
//{
// STDataType a[MAX];//数组,静态栈
// int top;//栈顶的位置,即栈顶的下标
//}ST;
typedef struct Stack
{
STDataType* a;//指针a,用来维护动态数组栈
int top;//既表示栈的当前元素个数,又表示当前栈顶的位置,即栈顶的下标
//当表示栈的元素个数时,范围:top >= 0,当top>0表示栈不为空
//当表示栈顶的位置时,范围:[0,top-1]
int capacity;//动态数组栈的容量
}ST;
//栈顶:栈的第一个元素的位置
//数组栈初始化
void StackInit(ST* ps);
//数组栈销毁
void StackDestroy(ST* ps);
//数组栈(顶)的插入
void StackPush(ST* ps, STDataType x);
//数组栈(顶)的删除
void StackPop(ST* ps);
//获取栈顶的数据
STDataType StackTop(ST* ps);
//数组栈的大小
int StackSize(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
注意:利用动态数组实现栈的结构
二、代码实现
1、void StackInit(ST* ps);数组栈初始化
//形参不会影响实参,传实参的地址,形参就能改变实参
//方式1:
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;//初始top = 0,表示top指向栈顶数据的下一个,即先放数据再++。初始top = -1.表示top指向栈顶数据,即先++再放数据
ps->capacity = 0;
}
//方式2:
void StackInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType)*4);
if (ps->a == NULL)
{
printf("malloc failed\n");
exit(-1);
}
ps->top = 0;
//top = 0,表示top指向栈顶数据的下一个,即先放数据再++。
//如;top=1,则top-1是栈顶
//top = -1.表示top指向栈顶数据,即先++再放数据
//如;top=1,则top是栈顶
ps->capacity = 4;
}
2、void StackPush(ST* ps, STDataType x);数组栈(顶)的插入
//方式1:
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)//满了,扩容
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity);
if (tmp == NULL)
{
printf("realloc failed\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
//方式2:
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)//满了,扩容
{
STDataType* tmp = realloc(ps->a, sizeof(STDataType) * (ps->capacity * 2));
if (tmp == NULL)
{
printf("realloc failed\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = ps->capacity * 2;
}
ps->a[ps->top] = x;
ps->top++;
}
3、void StackDestroy(ST* ps);数组栈销毁
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
4、void StackPop(ST* ps);数组栈(顶)的删除
void StackPop(ST* ps)
{
assert(ps);
//当栈顶没有数据,栈空了,不能再删除栈顶的数据,下标越界
//assert(ps->top > 0);相当于assert(!StackEmpty(ps));
assert(!StackEmpty(ps));
ps->top--;
}
5、STDataType StackTop(ST* ps);获取栈顶的数据
STDataType StackTop(ST* ps)
{
assert(ps);
//当栈顶没有数据,栈空了,不能再获取栈顶的数据,否则非法访问
//assert(ps->top > 0);相当于assert(!StackEmpty(ps));
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
//当top初始化为0,则return ps->a[ps->top - 1];
//当top初始化为-1,则return ps->a[ps->top];
}
6、int StackSize(ST* ps);数组栈的大小
int StackSize(ST* ps)
{
assert(ps);
return ps->top;//top既是栈的栈顶下标的前一个,也是栈的大小
}
7、bool StackEmpty(ST* ps);判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
/*if (ps->top == 0)
{
return true;
}
else
{
return false;
}*/
return ps->top == 0;
}
三、代码测试
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
void TestStack()
{
ST st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
StackPop(&st);
StackPop(&st);
StackPop(&st);
StackPop(&st);
//StackPop(&st);//栈为空,继续删除,报错
StackDestroy(&st);
}
//后进先出
void TestStack()
{
ST st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
printf("%d ", StackTop(&st));
StackPop(&st);
printf("%d ", StackTop(&st));
StackPop(&st);
StackPush(&st, 5);
StackPush(&st, 6);
//栈的遍历
//先打印当前栈顶的数据,再删除栈顶的数据。
while (!StackEmpty(&st))
{
printf("%d ", StackTop(&st));
StackPop(&st);
}
printf("\n");//4 3 6 5 2 1
//队列的数据是相对位置
StackDestroy(&st);
}
int main()
{
TestStack();
return 0;
}