栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
栈在生活中许多地方都有应用,如我们的自动售卖机,仓库等等。
栈结构实际上是对表结构的部分功能加以限制,形成的特殊表结构,只有一个进出口,由于它先进后出的特性,因此也简称为FILO(first in last out),同时,栈又细分为顺序栈和链式栈。
顺序栈的数据域如下:1、存储元素的内存首地址 2、栈的容量 3、栈顶位置;
顺序栈的运算如下:创建、销毁、入栈、出栈、栈顶、栈满、栈空。
链式栈的数据域如下:1、栈顶结点 2、结点数量
链式栈的运算如下:创建、销毁、入栈、出栈、栈空、栈顶
栈在编程中的运用:
栈的常考笔试面试题:
问题1:某个序列是一个栈的入栈顺序,判断哪个是正确的出栈顺序。
example:
1 2 3 4 5 入栈
1 2 3 4 5 yes
3 2 1 4 5 yes
3 1 2 5 4 no
tips: 有可能边入边出
问题2:两个容量相同的顺序栈,如何能够让空间利用率最高?
答:让两个栈相对着入栈
/************************************
> 作者:杭电羊皮卷
> weixin:QQ2997675141
************************************/
#include
#include
#include
#define TYPE int
//设计顺序栈结构
typedef struct ArrayStack{
TYPE* ptr; //储存元素内存首地址
size_t cal; //栈的容量
size_t top; //栈顶下标,从零开始,空增栈
}ArrayStack;
//创建
ArrayStack* create_array_stack(size_t cal)
{
//为栈结构分配内存
ArrayStack* stack = (ArrayStack* )malloc(sizeof(ArrayStack));
//分配储存元素的内存
stack->ptr = (TYPE* )malloc(sizeof(TYPE)*cal);
//记录栈容量
stack->cal = cal;
//记录栈顶位置,接下来要入栈的位置
stack->top = 0;
return stack;
}
//销毁
void destory_array_stack(ArrayStack* stack)
{
free(stack->ptr);
free(stack);
}
//栈空
bool empty_array_stack(ArrayStack* stack)
{
return 0 == stack->top;
}
//栈满
bool full_array_stack(ArrayStack* stack)
{
return stack->top >= stack->cal;
}
//入栈
bool push_array_stack(ArrayStack* stack,TYPE val)
{
if(full_array_stack(stack)) return false;
stack->ptr[stack->top++] = val;
return true;
}
//出栈
bool pop_array_stack(ArrayStack* stack)
{
if(empty_array_stack(stack)) return false;
stack->top--;
return true;
}
//栈顶
bool top_array_stack(ArrayStack* stack,TYPE* val)
{
if(empty_array_stack(stack)) return false;
*val = stack->ptr[stack->top-1];
return true;
}
int main(int argc,const char* argv[])
{
ArrayStack* stack = create_array_stack(10);
//这里写测试代码
return 0;
}
实现一个函数,序列a为入栈顺序,判断序列b是否是序列a的出栈顺序?即上面栈的常考笔试面试题问题1讲到的,用函数实现其功能
基于上面数组实现的栈结构,我们编写的函数如下:
bool is_order_pop_stack(cosnt int *a,const int *b,size_t len)
{
ArrayStack* stack = create_array_stack(len);
int val=0;
for(int i=0,j=0; i<len; i++)
{
//按照a的顺序一个一个入栈
push_array_stack(stack,a[i]);
//按照b的顺序尝试出栈
while(top_array_stack(stack,&val) && val == b[j])
{
pop_array_stack(stack);
j++;
}
}
bool res = empty_array_stack(stack);
destory_array_stack(stack);
return res;
}
/************************************
> 作者:杭电羊皮卷
> weixin:QQ2997675141
************************************/
#include
#include
#include
#define TYPE int
//节点数据结构
typedef struct Node{
TYPE data;
struct Node* next;
}Node;
//创建节点
Node* create_node(TYPE data)
{
Node* node = malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
//设计链式栈结构
typedef struct ListStack{
Node* top;
size_t cnt;
}ListStack;
//创建栈结构
ListStack* create_list_stack(void)
{
ListStack* stack = malloc(sizeof(ListStack));
stack->top = NULL;
stack->cnt = 0;
return stack;
}
//入栈
void push_list_stack(ListStack* stack,TYPE val)
{
Node* node = create_node(val);
node->next = stack->top;
stack->top = node;
stack->cnt++;
}
//栈顶
TYPE top_list_stack(ListStack* stack)
{
return stack->top->data;
}
//栈空
bool empty_list_stack(ListStack* stack)
{
return stack->cnt == 0;
}
//出栈
bool pop_list_stack(ListStack* stack)
{
if(empty_list_stack(stack)) return false;
Node* temp = stack->top;
stack->top = stack->top->next;
stack->cnt--;
free(temp);
return true;
}
//数量 一句话封装成函数是为了保持数据结构的封装行不被打破
size_t size_list_stack(ListStack* stack)
{
return stack->cnt;
}
//销毁栈
void destory_list_stack(ListStack* stack)
{
//把所有节点释放
while(pop_list_stack(stack));
//释放栈结构
free(stack);
}
int main(int argc,const char* argv[])
{
ListStack* stack = create_list_stack();
//这里写测试代码
destory_list_stack(stack);
return 0;
}
栈结构学习告一段落,下一章,我们将学习队列数据结构,敬请期待……