栈的性质
1 栈是一种特殊的线性表,只允许在固定的一端进行插入和删除元素.
2 进行插入删除操作的一端叫栈顶,另一端叫栈底。出入数据都在栈顶
3 栈的插入操作叫入栈/进栈/压栈.
栈的删除操作叫出栈;
4 栈中的数据元素遵循先进后出(或后进先出)的原则,
即先入栈的数据后出栈,后入栈的数据会先出栈.
栈的实现
用链表或数组实现栈?
链表和数组都可用来实现栈,但相对而言数组会更好。
1 分析用数组实现栈
首先,数组的尾插尾删效率高,可以用尾部作为栈顶;
其次,用数组cpu高速缓存命中率高.
唯一缺点是扩容的消耗.
2 分析用链表实现栈
缺点是cpu高速缓存命中率较低.
用带头双向循环链表,将哨兵位作栈底,在后面进行尾插或尾删来实现栈;
也可以用单链表来实现
采用数组来实现栈
定义栈的结构体
typedef int SKDataType;
typedef struct stack
{
SKDataType* data; //存放数据的动态空间
int top; //标识栈顶,也能代表栈的数据量,也能标识最后一个数据的下一个位置
int capacity; //容量
}SK;
栈的初始化和销毁
#define InitialCapacity 3
void StackInit(SK* stack)//给定初始空间
{
assert(stack);
SKDataType* tmp = (SKDataType*)malloc(sizeof(SKDataType) * InitialCapacity);
assert(tmp);
stack->data = tmp;
stack->capacity = InitialCapacity;
stack->top = 0;
}
void StackDestory(SK* stack)//只需free掉结构体内部动态申请的空间,然后其它数据置0
{
assert(stack);
free(stack->data);
stack->data = NULL;
stack->top = stack->capacity = 0;
}
入栈
void StackPush(SK* stack, SKDataType x)//栈的性质规定它只能在栈顶插入数据,这里只能尾插
{
assert(stack);
if (stack->top == stack->capacity)
{
//扩容
//内存块的大小记得乘以类型大小
SKDataType* tmp = (SKDataType*)realloc(stack->data, stack->capacity * 2 * sizeof(SKDataType));
assert(tmp);
stack->capacity *= 2;
stack->data = tmp;
}
stack->data[stack->top] = x;
stack->top++;
}
出栈
void StackPop(SK* stack)
{
assert(stack);
assert(!StackEmpty(stack));//栈里的数据不能为空
stack->top--;
}
其它函数
SKDataType StackTop(SK* stack)//取栈顶的元素
{
assert(stack);
assert(!StackEmpty(stack));
return stack->data[stack->top - 1];
}
bool StackEmpty(SK* stack)//判断栈是否为空
{
assert(stack);
return stack->top == 0;
}
int StackSize(SK* stack)//栈里的元素数目
{
assert(stack);
return stack->top;
}