目录
一、栈
栈限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
栈所需要的一般功能:
- 初始化栈
- 栈是否为空(栈是否为满)
- 入栈
- 出栈
- 遍历栈
- 清空栈
栈的分类:
- 顺序栈:存储核心是数组,在初始化就需要决定开辟栈空间的大小,在操作的时候需要注意栈空间是否有空余。
- 链式栈:存储核心是链表,可以任意进行入栈与出栈操作
- 个人对数据结构的一点理解
二、顺序栈的实现
- 栈的定义
/*栈的定义*/
typedef struct stack
{
int *stack;//指向栈空间
int size;//栈空间大小
int top;//栈顶
}stack, *stack_p;
- 初始化
/*初始化栈操作,n为需要开辟的空间*/
*stack_p init_stack(int n)
{
stack_p sp = malloc(sizeof(stack));//堆空间
if(sp == NULL)
{
printf("malloc failed\n");
return sp;
}
sp->stack = calloc(n, sizeof(int));//分配n块数据
sp->size = n;//n块数据域
sp->top = -1;//没有存放任何数据 此时 栈顶=栈底
return sp;
}
- 判断是否为空栈 与 是否为满栈
/*判断栈是否为空*/
bool isEmpty(stack_p sp)
{
return sp->top == -1;
}
/*判断栈是否存放满数据*/
bool isFull(stack_p sp)
{
return sp->top >= sp->size -1;
}
- 入栈
/*入栈操作, 参数为需要入栈的数据, 以及对应存放的栈*/
bool push(int data, stack_p sp)
{
if(isFull(sp))//入栈前,判断栈空间是否满了
{
printf("stack is full of data\n");
return false;
}
sp->top++;
sp->stack[sp->top] = data;
re
- 出栈
/*出栈操作*/
bool pop(int *data, stack_p sp)
{
if(isEmpty(sp))//出站前,判断栈空间是否为空
{
printf("stack is empty\n");
return false;
}
*data = sp->stack[sp->top];//先取值
sp->top--;//栈顶往栈底方向移动
return true;
}
- 遍历栈 与 清空栈
/*显示栈空间中存放的数据*/
void showStackData(stack_p sp)
{
if(isEmpty(sp))//显示前,判断栈是否为空
{
printf("sp is empty\n");
return;
}
int pos;
for(pos=0; pos<=sp->top; pos++)
{
printf("%d\t", sp->stack[pos]);
}
}
/*清空栈*/
void clearStack(stack_p sp)
{
free(sp->stack);
}
三、链式栈的实现
- 栈的定义与栈节点的定义
/*定义栈存储节点 以及 栈(栈顶与栈底指针)*/
typedef struct stack_Node
{
int data;
struct stack_Node *next;
}stackNode,*stackNode_p;
typedef struct stack
{
stackNode_p top;//栈顶
int size;//有多少个节点
}stack,*stack_p;
- 栈的初始化
/*初始化栈*/
stack_p init_stack()
{
stack_p sp = malloc(sizeof( stack));
if (sp != NULL)
{
sp->top = NULL;
sp->size = 0;
}
return sp;
}
- 判断栈是否为空
/*判断栈是否为空*/
bool isEmpty(stack_p sp)
{
return sp->size == 0;
}
- 入栈
/*
入栈:输入需要入栈的数据
(包含给对应数据创建栈存储节点,不含头结点)
*/
void push(int data, stack_p sp)
{
//创建栈存储节点存放数据
stackNode_p new = malloc(sizeof(stackNode));
if(new != NULL)
{
new->data = data;
//入栈处理
new->next = sp->top;
sp->top = new;
sp->size++;
}
}
- 出栈
/*出栈*/
bool pop(stack_p sp)
{
//判断栈是否为空
if (isEmpty(sp))
{
printf("stack is empty\n");
return false;
}
//出栈
stackNode_p stNode_p = sp->top;
sp->top = sp->top->next;
sp->size--;
//释放空间
free(stNode_p);
return true;
}
- 遍历栈
/*遍历栈*/
void showStack(stack_p sp)
{
//判断栈是否为空
if (isEmpty(sp))
{
printf("stack is empty\n");
return;
}
//从栈顶一直打印到栈底
int pos;
stackNode_p tmp = sp->top;
for(pos=0; pos<sp->size; pos++)
{
printf("%d\t", tmp->data);
tmp = tmp->next;
}
}
- 清空栈
/*清空栈*/
bool clearStack(stack_p sp)
{
if (isEmpty(sp))
{
printf("stack is empty\n");
return false;
}
int pos;
int size = sp->size;//记录栈中总数量
stackNode_p tmp;
for(pos=0; pos<size; pos++)
{
//存储栈顶节点
tmp = sp->top;
//指向下一数据
sp->top = tmp->next;
sp->size--;
//释放数据
free(tmp);
}
return true;
}
四、栈的应用场景
1、数制转换
int main(int argc, char const *argv[])
{
int data;
int tmp;
stack_p sp = init_stack();
//输入需要转换进制的数值
printf("请输入需要转换成8进制数的10进制数值\n");
scanf("%d",&data);
while(data >0)
{
push(data%8,sp);//余数入栈
data/=8;
}
while(1)
{
if (pop(&tmp,sp) != false)
{
printf("%d\t", tmp);
}
else break;
}
return 0;
}
结果:
2、括号匹配
int main(int argc, char const *argv[])
{
char data;
char tmp_data;
stack_p sp = init_stack();
while(1)
{
printf("请输入需要入栈的括号\n");
data = getchar();
getchar();//吸收回车号
switch(data)
{
//如果为左括号与左花括号则入栈
case '(':
case '{':
push(data,sp);
showStack(sp);
break;
case ')':
case '}':
pop(&tmp_data,sp);//当输入为右括号或者右花括号则出栈对比
showStack(sp);
if(data == ')')//将括号反转进行对比
data = '(';
else if (data == '}')
data = '{';
if (data == tmp_data)
printf("匹配成功\n");
else
printf("匹配失败\n");
break;
}
printf("\n");
}
return 0;
}
测试结果:
3、行编辑程序
- 待补充
4、迷宫求解
- 待补充
5、表达式求值
- 待补充
6、运算符优先级
- 待补充
7、递归
- 待补充