typedef struct
{
ElemType *base;
ElemType *top;
int stackSize;
}sqStack;
base是指向栈底的指针,top是指向栈顶的指针,stackSize是指栈的当前可使用的最大容量。
创建一个栈
入栈:入栈又叫压栈,在栈顶进行,每次入栈,top指针就加1,直到栈满。
出栈
在栈顶取出数据,栈顶指针下移,当前容量减1
另一种声明方法:
清空一个栈
清空一个站就是将栈中的元素全部作废,但栈本身物理空间不改变(不是销毁)。
ClearStack(sqStack *s){
s->top = s->base;
}
销毁一个栈
销毁是要释放掉该栈所占据的物理内存空间
计算栈的当前容量
也就是计算栈中元素的个数,只要返回s.top-s.base即可
int StackLen(sqStack s){
return (s.top - s.base)//中间隔了几个元素,就相当于指针的差值再除以每个单元所占的内存,指针可相减,不可相加
}
栈因为只是用栈顶来插入和删除,所以比较好的方法就是将栈顶放在单链表的头部,栈顶指针和单链表的头指针合二为一。
进栈
出栈
逆波兰表达式
1.
2.
3.然后遇到乘法运算符,将9和-1弹出栈进行乘法运算,此时栈空,并且没有数据压栈,-9为最终结果
int main(){
sqStack s;
char c;
double d,e;
char str[MAXBUFFER];
int i = 0;
InitStack(&s);
printf("请按逆波兰表达式输入待计算数据,数据和运算符之间用空格隔开,以#作为结束标志");
scanf("%c", &c);
while(c != '#') {
while(isdigit(c) || c=='.'){
str[i++] = c;
str[i] = '\0';
if (i>=10){
printf("出错,输入的单个数据过大\n");
return -1;
}
scanf("%c",&c);
if(c == ''){
d = atof(str);//字符串转double
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出错:除数为零\n");
return -1;
}
break;
}
scanf("%c", &c);
}
pop(&s,&d)
printf("\n最终的计算结果为:%f\n", d)
return 0;
}
中缀表达式转为后缀表达式
(1-2)*(4+5) ===> 1 2 - 4 5 + *
利用栈的记忆,符号都推入栈即可
以上可转化为:1+(2-3)*4+10/5
int main(){
sqStack s;
char c, e;
InitStack(&s);
printf("请输入中缀表达式,以#作为结束标志");
scanf("%c",&c);
while(c != '#'){
if (c >= '0' && c <= '9'){
printf("%c", c);
} else 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 {
printf("\n输入错误\n");
return -1;
}
scanf("%c", &c);
}
while(StackLen(s)){
pop(&s, &e);
printf("%c", e);
}
return 0;
}
队列的链式存储结构
对列既可以用链表实现,也可以用顺序表来实现。跟栈相反,栈一般用顺序表实现,而对列常用链表实现,简称为链对列。
创建一个空队列
在内存中创建一个头节点,然后队列的头指针和尾指针都指向它,此时即为空队列。
入队列操作
出队列操作
销毁一个队列
队列的顺序存储结构
假设队列有n个元素,则顺序存储的的队列需建立一个大于n的存储单元,并把队列的所有元素存储在数组的前n个单元,下标为0的一端是队头。
改进:我们不去限制队头一定要在下标为0的位置,那么出队列的操作也就不移动全体元素了。
上问题又叫假溢出,要解决假溢出的方法就是,如果后面满了,就再从头开始,也就是头尾相接的循环。
循环队列
循环队列的容量是固定的,并且它的队头和队尾可随着元素出入队列而发生改变,这样的队列逻辑上就好像一个环形存储空间。
循环队列代码:
定义一个循环队列