栈
栈 ----- 限定仅在表尾进行插入和删除操作的线性表
特点 ----- 后进先出(后进入栈的元素先出来)
栈顶(top) ---- 栈的表尾
栈底(base) ---- 栈的表头
顺序栈
顺序栈 ---- 利用一组连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶的位置
顺序栈中,栈底指针base始终指向栈底的位置,若base == NULL, 说明栈结构不存在;栈顶指针top初值指向栈底,即top = base,此时栈为空,每当插入新的栈顶元素时,指针top增1,删除栈顶元素时,指针top减1;栈中元素长度= top - base.
算法实现
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define STACK_INIT_SIZE 30
#define STACKINCREMENT 5
typedef int SElemType;
typedef int Status;
typedef struct{
SElemType* base;
SElemType* top;
int stacksize;
}SqStack;
/*
构造空栈
*/
Status InitStack(SqStack *S){
//分配存储空间
(*S).base = (SElemType* )malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL){
exit(OVERFLOW); //分配失败
}
(*S).top = (*S).base; //空栈
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
返回栈顶元素
*/
Status GetTop(SqStack S, SElemType *e){
if(S.top == S.base){
return ERROR; //栈为空
}
*e = *(S.top - 1);
return OK;
}
/*
判空
*/
Status StackEmpty(SqStack S){
if(S.top == S.base){
return OK; //栈空
}else{
return ERROR; //栈非空
}
}
/*
栈中元素长度
*/
int SqStackLength(SqStack S){
return S.top - S.base;
}
/*
压入元素
*/
Status Push(SqStack* S, SElemType e){
SElemType* temp;
if((*S).top - (*S).base == (*S).stacksize){
//栈满,追加空间
temp =(SElemType* )realloc((*S).base,((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if(temp == NULL){
exit(OVERFLOW); //分配失败
}
(*S).base = temp;
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
*((*S).top++) = e; //压入元素,栈顶指针上移
return OK;
}
/*
弹出元素
*/
Status Pop(SqStack* S, SElemType* e){
if((*S).top == (*S).base){
return ERROR; //栈空
}
*e = *(--(*S).top); //栈顶指针下移,元素弹出
return OK;
}
int main(void){
SqStack S;
SElemType e[5] = {1, 3, 7, 9, 11};
SElemType temp;
int i;
InitStack(&S);
if(!StackEmpty(S)){
printf("未压入元素前为空栈\n");
}else{
printf("未压入元素前为非空栈\n");
}
for(i = 0; i < 5; i++){
Push(&S, e[i]);
}
//压入元素后
printf("\n");
if(!StackEmpty(S)){
printf("压入元素前为空栈\n");
}else{
printf("压入元素前为非空栈\n");
}
printf("压入元素前为栈中元素长度为: %d\n",SqStackLength(S));
GetTop(S, &temp);
printf("压入元素前为栈顶元素为: %d\n",temp);
//执行一次出栈后
printf("\n");
Pop(&S, &temp);
printf("出栈元素为: %d\n",temp);
printf("执行一次出栈后元素长度为: %d\n",SqStackLength(S));
GetTop(S, &temp);
printf("执行一次出栈后的栈顶元素为: %d\n",temp);
return 0;
}
栈的应用
数制转换
十进制数与d进制数的转换原理 : N = (N div d) * d + N mod d ; 其中div为整除运算,mod为求余运算
以十进制数37转化为二进制数为例:
37 / 2 = 18… 1
18 / 2 = 9… 0
9 / 2 = 4 … 1
4 / 2 = 2 … 0
2 / 2 = 1 … 0
1 / 2 = 0 … 1
将余数从下到上依次组合就是十进制数37的二进制数100101
算法实现
Status Conversion(int num, int d){
SqStack S;
SElemType e;
int temp = num;
InitStack(&S);
while(num){
Push(&S, num%d); //取余压入栈
num = num / d;
}
printf("十进制数%d化为%d进制数为",temp, d);
while(!StackEmpty(S)){
Pop(&S, &e); //出栈
printf("%d",e);
}
printf("\n");
return OK;
}