目录
一,栈的概念
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
二,栈与顺序表的对比
我目前对栈的理解就是栈是一种适用于特殊场景的顺序表,它的使用场景是特定的,因为它只允许在固定的一端进行插入和删除元素操作,否则不能称为栈,所以它的功能也是专门化的。顺序表中的插入操作,有在头插、尾插等,删除操作有头删、尾删等;而栈只对栈顶元素进行操作。
三,栈结构的实现
类似顺序表的结构,栈的结构成员包含一个数组,一个栈顶数据,一个容量
注意这里我们通过typedef将int重命名为StackDataType,这样当我们在栈中存放int之外类型的数据时,我们只需将int修改即可,例如float
typedef int StackDataType;
typedef struct Stack
{
StackDataType* nums;
int top;
int capacity;
}Stack;
四,栈接口的实现
1,基本接口
初始化:void StackInit(Stack* pstack);
使用者在创建一个栈的变量之后,将其指针传入初始化函数中,初始化函数将其成员nums置空,top置为-1(-1表示栈为空),capacity置空(栈的容量为0)
void StackInit(Stack* pstack)
{
pstack->nums = NULL;
pstack->top = -1;
pstack->capacity = 0;
}
销毁:void StackDestroy(Stack* pstack);
释放动态开辟的空间,top置为-1(-1表示栈为空),capacity置空(栈的容量为0)
void StackDestroy(Stack* pstack)
{
free(pstack->nums);
pstack->nums = NULL;
pstack->top = -1;
pstack->capacity = 0;
}
2,处理数据接口
插入数据:
插入数据前判断栈容量是否足够,不够则realloc()扩容,
在容量足够的情况下,在数组nums的最后一个元素后将数据插入即可。
注意,栈中的top是nums中最后一位有效数字的下标,在插入数据时应当先使top加一,再通过top插入数据,这样,在插入数据之后,top依然是nums中最后一位有效数字的下标。
void StackCheckCapacity(Stack* pstack)
{
if (pstack->top + 1 == pstack->capacity)
{
int newcapacity = (0 == pstack->capacity) ? 4 : 2 * pstack->capacity;
pstack->nums = (StackDataType*)realloc(pstack->nums, newcapacity * sizeof(StackDataType));
pstack->capacity = newcapacity;
}
}
void StackPush(Stack* pstack, StackDataType x)
{
assert(pstack != NULL);
StackCheckCapacity(pstack);
pstack->nums[++pstack->top] = x;
}
删除数据:
首先通过判断栈是否为空的函数(见下文)进行检查,栈为空则报错,
栈不为空的情况下,只需top减一即可完成删除操作(类比顺序表)
void StackPop(Stack* pstack)
{
assert(pstack != NULL);
assert(!StackEmpty(pstack));
pstack->top--;
}
3,其他接口
判断栈是否为空:
通过top进行判断,-1为空,否则为非空
bool StackEmpty(Stack* pstack)
{
assert(pstack != NULL);
return (pstack->top == -1) ? true : false;
}
栈内元素数量:
联系数组的相关知识,数组元素的多少就是最大下标加一的大小,栈的nums的最大下标即为top
int StackSize(Stack* pstack)
{
assert(pstack != NULL);
return pstack->top + 1;
}
栈顶元素:
下标为top的元素即为栈顶元素
StackDataType StackTop(Stack* pstack)
{
assert(pstack != NULL);
assert(StackEmpty(pstack) != true);
return pstack->nums[pstack->top];
}
五,写在最后的话
数据结构的实现不是单一的或者统一的,思想是关键,代码实现的细节的差异因人而异,使用数据结构应当对代码进行了解,不是想怎么用就怎么用的。
例如:栈的初始化中可以将top初始化为0,此时top为零表示栈为空,top-1是栈顶元素下标,而相关的接口实现也需要改变。