[声明]:此文档为本人学习小甲鱼C语言与数据结构课程时的笔记记录。仅供学习之用,转载请标明出处!感谢小甲鱼!
本文目录
栈
后进先出,本质是一个线性表,只在表尾进行删除和插入操作。
两种存储方式:
- 顺序存储结构
- 链式存储结构
栈的顺序结构
栈头和栈底 | 指针 | 地址 | 线性表 |
---|---|---|---|
栈头 | s->top | 大地址 | 表头 |
栈 | s->base | 小地址 | 表尾 |
定义栈
typrdef struct
{
ElemType *base;
ElemType *top;
int stackSize; //当前可用最大容量
}sqStack;
创建一个空栈:
#define STACK_INIT_SIZE 100
initStack(sqStack *s)
{
s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if(!s->base)
exit(0); //申请空间失败,则退出
s->top = s->base;
s->stackSize = STACK_INIT_SIZE
}
入栈操作
#include<stdlib.h> //realloc操作
#define STACKINCREMENT 10
Push(sqStack *s, ElemType e)
{
//如果栈满,则追加空间
if(s->tpo - 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->tpo) = e;
s->tpo++;
}
出栈
// 修改栈使用指针,不修改(测试)直接传入
Pop(sqStack *s, ElemType *e)
{
if(s->top == s->base)
return;
*e = *--(s->top); //先将指针s->top减一再取出内容赋值给*e
}
栈的链式存储结构
通常我们使用栈的顺序存储结构存储。栈只能在栈顶进行插入和删除操作,栈的链式存储结构比较好的方法就是将栈顶放在单链表的表头,栈顶指针和单链表的头指针合二为一。
栈的链式存储结构:初始化栈
typedef struct StackNode
{
Elemtype data; // 存放栈的数据
struct StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPrt top; //top指针
int count; //栈元素计数器
}
栈的链式存储结构:入栈
// 假设元素之为e的新结点是s,top 为栈顶指针。
Status Push(LinkStack *s, ElemType e)
{
LinkStackPtr p = (LinkStackPtr) malloc (sizeof(StackNode));
p->data = e;
p->next = s->top;
s->top = p;
s->count++;
return OK;
}
栈的链式存储结构:出栈
Status Pop(LinkStack *s, ElemType *e)
{
LinkStackPtr p;
if(StackEmpty(*s)) //判断是否为空栈
return ERROR;
*e = s->top->data;
p = s->top;
s->top = s->top->next;
free(p);
s->count--;
return OK;
}
示例
(一):二进制转换成十进制
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
typedef char ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stackSize;
}sqStack;
void InitStack(sqStack *s)
{
s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if(!s->base)
{
exit(0);
}
s->top = s->base;
s->stackSize = STACK_INIT_SIZE;
}
void 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) = e;
s->top++;
}
void Pop(sqStack *s, ElemType *e)
{
if(s->top == s->base)
{
return;
}
*e = *--(s->top);
}
int StackLen(sqStack s) //传入非指针
{
return (s.top - s.base);
}
int main()
{
ElemType c;
sqStack s;
int len, i, sum=0;
InitStack(&s);
printf("请输入一个二进制数,输入#表示结束!\n");
scanf("%c", &c);
while(c != '#')
{
Push(&s, c);
scanf("%c", &c);
}
getchar(); //清理键盘缓冲区回车'\n'
len = StackLen(s);
printf("当前栈的容量是:%d\n", len);
for(i=0; i<len; i++)
{
Pop(&s, &c);
sum = sum + (c-48) * pow(2, i);
}
printf("转换为十进制输出是:%d\n", sum);
return 0;
}
(二):逆波兰计算器
输入逆波兰表达式(即后缀表达式),得出计算结果。
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
#define MAXBUFFER 10
typedef double ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stackSize;
}sqStack;
InitStack(sqStack *s)
{
s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if(!s->base)
{
exit(0);
}
s->top = s->base;
s->stackSize = 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);
}
int main()
{
sqStack s;
char c;
double d,e;
char str[MAXBUFFER];
int i=0;
InitStack(&s); //初始化栈
printf("请按逆波兰表达式输入数据,数据与运算符之间用空格隔开,以#结束!\n");
scanf("%c", &c);
while(c != '#')
{
while( isdigit(c) || c=='.') //判断C是否为数字,头文件ctype.h
{
str[i++] = c;
str[i] = '\0'; //数组是作为局部变量定义的,没有初始化为0。应为下一个数据自动填充0。
if(i >= 10)
{
printf("\n出错:输入的单个数据过大!\n");
return -1;
}
scanf("%c", &c);
if(c == ' ')
{
d = atof(str); // atof()字符串型->浮点数,atod()字符串->整型。
Push(&s, d);
i = 0;
break;
}
}
switch( c )
{
case '+':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d+e);
break;
case '-':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d-e);
break;
case '*':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d*e);
break;
case '/':
Pop(&s, &e);
Pop(&s, &d);
if(e != 0)
{
Push(&s, d/e);
}
else
{
printf("\n出错:除数为0!!!");
return -1;
}
break;
}
scanf("%c", &c);
}
Pop(&s, &d);
printf("\n最终的计算结果为:%f\n", d);
return 0;
}
//逆波兰表达式示例
//(1-2)*(4+5) -> 1 2 - 4 5 + *# 结果:(-9)
//5-(6+7)*8+9/4 -> 5 6 7 + 8 * - 9 4 / + 结果:(-96.75)
(三):中缀表达式转换为后缀表达式
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
typedef char ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stackSize;
}sqStack;
void InitStack(sqStack *s)
{
s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if(!s->base)
{
exit(0);
}
s->top = s->base;
s->stackSize = STACK_INIT_SIZE;
}
void 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) = e;
s->top++;
}
void Pop(sqStack *s, ElemType *e)
{
if(s->top == s->base)
{
return;
}
*e = *--(s->top);
}
int StackLen(sqStack s)
{
return (s.top - s.base);
}
int main()
{
sqStack s;
char c, e;
InitStack(&s);
printf("请输入中坠表达式,输入#表示结束!\n");
scanf("%c", &c);
while(c != '#')
{
while(c >= '0' && c <= '9') //输入为数字直接打印
{
printf("%c", c);
scanf("%c", &c);
if(c < '0' || c >= '9')
{
printf(" ");
}
}
if(')' == c) //输入为 ')',弹栈,打印
{
Pop(&s, &e);
while('(' != e)
{
printf("%c ", e);
Pop(&s, &e);
}
}
else if('+' == c || '-' == c)
{
if(!StackLen(s))
{
Push(&s, c);
}
else
{
do
{
Pop(&s, &e);
if('(' == e)
{
Push(&s, e);
}
else
{
printf("%c ", e);
}
}while(StackLen(s) && '(' != e);
Push(&s, c);
}
}
else if('*' == c || '/' == c || '(' == c)
{
Push(&s, c);
}
else if('#' == c)
{
break;
}
else
{
printf("\n出错:输入格式错误!\n");
return -1;
}
scanf("%c", &c);
}
while(StackLen(s))
{
Pop(&s, &e);
printf("%c ", e);
}
return 0;
}
// 输入:1+(2-3)*4+10/5#