栈(stack)是一个后进先出(LIFO: last in first out)的线性表,它要求只在表尾进行删除和插入等操作。也就是说,所谓栈其实就是一个线性表(顺序表,链表),但是它在操作上有一些特殊的要求和限制。首先,栈的元素必须先进后出,这与一般的顺序表不同。其次,栈的操作只能限定在这个顺序表的表尾进行。
对栈的概念对于大多数“纯”软件开发的工作岗位都很陌生,因为平时也用不到栈的知识,开发的环境ROM和RAM都够用,不用考虑这些烦恼的问题。如果你是一个嵌入式软硬件开发、单片机开发、设计者等等你可能对栈理解的更透彻些。因为我们在单片机程序经常遇到写着写RAM空间满了,所以在开发之前选型很重要。
C语言中的局部变量都是用栈来实现的,编写单片机程序(例如51、AVR、STM32)或者ARM等编写应用程序时并没有去设置栈,但是C程序还是可以运行的。 原因是:在单片机、ARM中由硬件初始化时提供了一个默认可用的栈,嵌入式开发中会在Uboot(由两部编写一是汇编语言;二是C语言)的汇编代码中定义栈的大小。
入栈
入栈操作过程
出栈
出栈操作过程
#include "stdio.h"#include "math.h"#include "malloc.h"#define STACK_INIT_SIZE 20#define STACKINCREMENT 10typedef char ElemType;typedef struct{ ElemType *base; ElemType *top; int stacksize;}sqStack;initStack(sqStack *s){ /*内存中开辟一段连续空间作为栈空间,首地址赋值给s->base*/ s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType)); if(!s->base) exit(0); /*分配空间失败*/ s->top = s->base; /*最开始,栈顶就是栈底*/ s->stacksize = STACK_INIT_SIZE; /*最大容量为STACK_INIT_SIZE */}Push(sqStack *s, ElemType e){ if(s->top - s->base >= s->stacksize){ /*栈满,追加空间*/ s->base = (ElemType *)realloc(s->base, (s->stacksize STACKINCREMENT)*sizeof(ElemType)); if(!s->base) exit(0); /*存储分配失败*/ s->top = s->base s->stacksize; s->stacksize = s->stacksize STACKINCREMENT; /*设置栈的最大容量*/ } *(s->top) = e; /*放入数据*/ s->top ;}Pop(sqStack *s , ElemType *e){ if(s->top == s->base) return; *e = *--(s->top); }int StackLen(sqStack s){ return (s.top - s.base) ; }void DestroyStack(sqStack *s){ free(s->base); s->base = s->top = NULL; /*栈底栈顶指针置NULL*/ s->stacksize = 0; /*设置栈的最大容量为0*/}main(){ ElemType c; sqStack s; int len , i , sum = 0; printf("Please input a Binary digit\n"); initStack(&s); /*创建一个栈,用来存放二进制字符串*/ /*输入0/1字符表示的二进制数,以#结束*/ scanf("%c",&c); while(c!='#') { Push(&s,c); scanf("%c",&c); } getchar(); len = StackLen(s); /*得到栈中的元素个数,即二进制数的长度*/ for(i=0;i<len;i ){ Pop(&s,&c); sum = sum (c-48) * pow(2,i); /*转换为十进制*/ } printf("Decimal is %d\n",sum); DestroyStack(&s); /*销毁栈空间*/ getche();}