栈:后进先出(LIFO) last in first out
栈是一种特殊的线性表,只能在线性表的一端进行操作。
栈顶 top
栈底 bottom
实现方式:顺序结构实现,线性结构实现
链式存储实现
LinkStack.h
#ifndef _LINKSTACK_H_ #define _LINKSTACK_H_ typedef void LinkStack; LinkStack* LinkStack_Create(); void LinkStack_Destroy(LinkStack* stack); void LinkStack_Clear(LinkStack* stack); int LinkStack_Push(LinkStack* stack, void* item); void* LinkStack_Pop(LinkStack* stack); void* LinkStack_Top(LinkStack* stack); int LinkStack_Size(LinkStack* stack); #endif
LinkStack.c
#include <malloc.h> #include "LinkStack.h" #include "LinkList.h" typedef struct _tag_LinkStackNode { LinkListNode header; void* item; } TLinkStackNode; LinkStack* LinkStack_Create() { return LinkList_Create(); } void LinkStack_Destroy(LinkStack* stack) { LinkStack_Clear(stack); LinkList_Destroy(stack); } void LinkStack_Clear(LinkStack* stack) { while( LinkStack_Size(stack) > 0 ) { LinkStack_Pop(stack); } } int LinkStack_Push(LinkStack* stack, void* item) { TLinkStackNode* node = (TLinkStackNode*)malloc(sizeof(TLinkStackNode)); int ret = (node != NULL) && (item != NULL); if( ret ) { node->item = item; ret = LinkList_Insert(stack, (LinkListNode*)node, 0); } if( !ret ) { free(node); } return ret; } void* LinkStack_Pop(LinkStack* stack) { TLinkStackNode* node = (TLinkStackNode*)LinkList_Delete(stack, 0); void* ret = NULL; if( node != NULL ) { ret = node->item; free(node); } return ret; } void* LinkStack_Top(LinkStack* stack) { TLinkStackNode* node = (TLinkStackNode*)LinkList_Get(stack, 0); void* ret = NULL; if( node != NULL ) { ret = node->item; } return ret; } int LinkStack_Size(LinkStack* stack) { return LinkList_Length(stack); }
main.c
#include <stdio.h> #include <stdlib.h> #include "LinkStack.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { LinkStack* stack = LinkStack_Create(); int a[10]; int i = 0; for(i=0; i<10; i++) { a[i] = i; LinkStack_Push(stack, a + i); } printf("Top: %d\n", *(int*)LinkStack_Top(stack)); printf("Length: %d\n", LinkStack_Size(stack)); while( LinkStack_Size(stack) > 0 ) { printf("Pop: %d\n", *(int*)LinkStack_Pop(stack)); } LinkStack_Destroy(stack); return 0; }
顺序存储实现:
SeqStack.h
#ifndef _SEQSTACK_H_ #define _SEQSTACK_H_ typedef void SeqStack; SeqStack* SeqStack_Create(int capacity); void SeqStack_Destroy(SeqStack* stack); void SeqStack_Clear(SeqStack* stack); int SeqStack_Push(SeqStack* stack, void* item); void* SeqStack_Pop(SeqStack* stack); void* SeqStack_Top(SeqStack* stack); int SeqStack_Size(SeqStack* stack); int SeqStack_Capacity(SeqStack* stack); #endif
SeqStack.c
#include "SeqStack.h" #include "SeqList.h" SeqStack* SeqStack_Create(int capacity) { return SeqList_Create(capacity); } void SeqStack_Destroy(SeqStack* stack) { SeqList_Destroy(stack); } void SeqStack_Clear(SeqStack* stack) { SeqList_Clear(stack); } int SeqStack_Push(SeqStack* stack, void* item) { return SeqList_Insert(stack, item, SeqList_Length(stack)); } void* SeqStack_Pop(SeqStack* stack) { return SeqList_Delete(stack, SeqList_Length(stack) - 1); } void* SeqStack_Top(SeqStack* stack) { return SeqList_Get(stack, SeqList_Length(stack) - 1); } int SeqStack_Size(SeqStack* stack) { return SeqList_Length(stack); } int SeqStack_Capacity(SeqStack* stack) { return SeqList_Capacity(stack); }
main.c
#include <stdio.h> #include <stdlib.h> #include "SeqStack.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { SeqStack* stack = SeqStack_Create(20); int a[10]; int i = 0; for(i=0; i<10; i++) { a[i] = i; SeqStack_Push(stack, a + i); } printf("Top: %d\n", *(int*)SeqStack_Top(stack)); printf("Capacity: %d\n", SeqStack_Capacity(stack)); printf("Length: %d\n", SeqStack_Size(stack)); while( SeqStack_Size(stack) > 0 ) { printf("Pop: %d\n", *(int*)SeqStack_Pop(stack)); } SeqStack_Destroy(stack); return 0; }
栈的特别实现
q1是专职进出栈的,q2只是个中转站。元素集中存放在一个栈中(q1 或 q2, 会根据不同情况变动)
定义两个指针:pushtmp:指向专门进栈的队列q1; tmp:指向临时作为中转站的另一个栈q2
入栈:直接入pushtmp所指队列即可
出栈:把pushtmp的除最后一个元素外全部转移到队列tmp中,然后把刚才剩下q1中的那个元素出队列
参考:http://www.cnblogs.com/kaituorensheng/archive/2013/03/02/2939690.html
栈的应用:
互不相邻,又相互匹配的事物
非常适合于就近匹配的场合
1、检测代码中括号是否匹配
原理:
1、从左往右扫描
2、遇到普通字符忽略,遇到做符号入栈
3、遇到有符号出栈
4、进行匹配
匹配成功继续下一个
匹配失败,停止报错
5、结束
成功:所有字符扫描完毕,且栈为空
失败:匹配失败或扫描完毕栈不为空
检测括号是否匹配
main.c
#include <stdio.h> #include <stdlib.h> #include "LinkStack.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int isLeft(char c) { int ret = 0; switch(c) { case '<': case '(': case '[': case '{': case '\'': case '\"': ret = 1; break; default: ret = 0; break; } return ret; } int isRight(char c) { int ret = 0; switch(c) { case '>': case ')': case ']': case '}': case '\'': case '\"': ret = 1; break; default: ret = 0; break; } return ret; } int match(char left, char right) { int ret = 0; switch(left) { case '<': ret = (right == '>'); break; case '(': ret = (right == ')'); break; case '[': ret = (right == ']'); break; case '{': ret = (right == '}'); break; case '\'': ret = (right == '\''); break; case '\"': ret = (right == '\"'); break; default: ret = 0; break; } return ret; } int scanner(const char* code) { LinkStack* stack = LinkStack_Create(); int ret = 0; int i = 0; while( code[i] != '\0' ) { if( isLeft(code[i]) ) { LinkStack_Push(stack, (void*)(code + i)); } if( isRight(code[i]) ) { char* c = (char*)LinkStack_Pop(stack); if( (c == NULL) || !match(*c, code[i]) ) { printf("%c does not match!\n", code[i]); ret = 0; break; } } i++; } if( (LinkStack_Size(stack) == 0) && (code[i] == '\0') ) { printf("Succeed!\n"); ret = 1; } else { printf("Invalid code!\n"); ret = 0; } LinkStack_Destroy(stack); return ret; } int main(int argc, char *argv[]) { const char* code = "#include <stdio.h> int main() { int a[5][5]; int (*p)[4]; p = a[0]; printf(\"%d\\n\", &p[3][3] - &a[3][3]); return 0; }"; scanner(code); return 0; }
2、计算机做数学运算
中缀表达式符合我们的阅读习惯
后缀表达式符合计算机运算习惯
中缀转后缀计算方式:
遍历中缀表达式中的数字和符号
对于数字:直接输出
对于符号:
左括号:进栈
符号:与栈顶符号进行优先级比较
栈顶符号优先级低:入栈
其他情况(高于或等于,括号和栈为空认为最低):将栈顶符号弹出直至为空或比当前符号优先级低,然后入栈
右括号:将栈顶符号弹出直至匹配左括号
遍历结束:将栈中所有符号弹出
中缀转后缀:
#include <stdio.h> #include "LinkStack.h" int isNumber(char c) { return ('0' <= c) && (c <= '9'); } int isOperator(char c) { return (c == '+') || (c == '-') || (c == '*') || (c == '/'); } int isLeft(char c) { return (c == '('); } int isRight(char c) { return (c == ')'); } int priority(char c) { int ret = 0; if( (c == '+') || (c == '-') ) { ret = 1; } if( (c == '*') || (c == '/') ) { ret = 2; } return ret; } void output(char c) { if( c != '\0' ) { printf("%c", c); } } void transform(const char* exp) { LinkStack* stack = LinkStack_Create(); int i = 0; while( exp[i] != '\0' ) { if( isNumber(exp[i]) ) { output(exp[i]); } else if( isOperator(exp[i]) ) { //栈顶比他低则入栈,高则先把栈里面依次出栈后在入栈 while( priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)) ) { output((char)(int)LinkStack_Pop(stack)); } LinkStack_Push(stack, (void*)(int)exp[i]); } else if( isLeft(exp[i]) ) { LinkStack_Push(stack, (void*)(int)exp[i]); } else if( isRight(exp[i]) ) { char c = '\0'; while( !isLeft((char)(int)LinkStack_Top(stack)) ) { output((char)(int)LinkStack_Pop(stack)); } LinkStack_Pop(stack); } else { printf("Invalid expression!"); break; } i++; } while( (LinkStack_Size(stack) > 0) && (exp[i] == '\0') ) { output((char)(int)LinkStack_Pop(stack)); } LinkStack_Destroy(stack); } int main() { transform("9+(3-1)*5+8/2"); printf("\n"); return 0; }
后缀计算:
#include <stdio.h> #include "LinkStack.h" int isNumber(char c) { return ('0' <= c) && (c <= '9'); } int isOperator(char c) { return (c == '+') || (c == '-') || (c == '*') || (c == '/'); } int value(char c) { return (c - '0'); } int express(int left, int right, char op) { int ret = 0; switch(op) { case '+': ret = left + right; break; case '-': ret = left - right; break; case '*': ret = left * right; break; case '/': ret = left / right; break; default: break; } return ret; } int compute(const char* exp) { LinkStack* stack = LinkStack_Create(); int ret = 0; int i = 0; while( exp[i] != '\0' ) { if( isNumber(exp[i]) ) { LinkStack_Push(stack, (void*)value(exp[i])); } else if( isOperator(exp[i]) ) { int right = (int)LinkStack_Pop(stack); int left = (int)LinkStack_Pop(stack); int result = express(left, right, exp[i]); LinkStack_Push(stack, (void*)result); } else { printf("Invalid expression!"); break; } i++; } if( (LinkStack_Size(stack) == 1) && (exp[i] == '\0') ) { ret = (int)LinkStack_Pop(stack); } else { printf("Invalid expression!"); } LinkStack_Destroy(stack); return ret; } int main() { printf("9 + (3 - 1) * 5 + 8 / 2 = %d\n", compute("931-5*+82/+")); return 0; }
3、进制转换
4、迷宫问题
http://www.cnblogs.com/liuling/archive/2013/04/29/mazestack.html
5、历史记录
6、汉诺塔