栈是一种特殊的线性表。其特殊性在于限定插入和删除数据元素的操作只能在线性表的一端进行。所以具有先进后出的特点。
栈的基本运算有六种:
构造空栈:InitStack(S)、
判栈空: StackEmpty(S)、
判栈满: StackFull(S)、
进栈: Push(S,x)、可形象地理解为压入,这时栈中会多一个元素
退栈: Pop(S) 、 可形象地理解为弹出,弹出后栈中就无此元素了。
取栈顶元素:StackTop(S),不同与弹出,只是使用栈顶元素的值,该元素仍在栈顶不会改变。
由于栈也是线性表,因此线性表的存储结构对栈也适用,通常栈有顺序栈和链栈两种存储结构,这两种存储结构的不同,则使得实现栈的基本运算的算法也有所不同。
这里只对链栈进行介绍:
若是栈中元素的数目变化范围较大或不清楚栈元素的数目,就应该考虑使用链式存储结构。人们将用链式存储结构表示的栈称作"链栈"。链栈通常用一个无头结点的单链表表示。如图所示:
栈的操作是线性表操作的特例。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> using namespace std; #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef struct node//栈的存储结构 { //int num; char num; struct node *ptop; } stack; void push(stack **p,int shu)//入栈 { stack *add=(node *)malloc(sizeof(node)); add->num =shu; add->ptop =*p; *p = add; } void pushchar(stack **p,char shu)//字符入栈,主要针对括号匹配类的题型。 { stack *add=(node *)malloc(sizeof(node)); add->num=shu; add->ptop=*p; *p=add; } void visit(stack *p)//遍历整个链栈 { while(p) { if(p->ptop!=NULL) { cout<<p->num<<" "; } else { cout<<p->num<<endl; } p=p->ptop; } } bool empty(stack *p)//判断栈是否为空 { if(NULL==p) return true; else return false; } int top(stack **p)//返回栈顶元素 { return (*p)->num; } void topchar(stack *p,char *e)//(括号匹配)*e是为了传参 { *e=p->num; } int pop(stack **p)//出栈 { int shu; stack *del= *p; shu=del->num; *p=(*p)->ptop; free(del); return shu; } int main() { node *p=NULL; push(&p,11); push(&p,12); push(&p,13); push(&p,14); ///三个杠注释是在括号匹配下使用 ///char e; ///pushchar(&p,')'); ///pushchar(&p,')'); ///pushchar(&p,'('); ///pushchar(&p,'('); visit(p); ///topchar(p,&e); cout<<e<<endl; cout<<top(&p)<<endl; cout<<pop(&p)<<endl; cout<<pop(&p)<<endl; }
栈的应用
(1) 数制转换//(十进制转换为任意进制)
#include <iostream> #include <stdlib.h> using namespace std; typedef struct _stack { int num; struct _stack *top; } stack; void push(stack* &head,int shu) { stack *add; add=(stack *)malloc(sizeof(stack)); add->num=shu; add->top=head; head=add; } int pop(stack* &head) { int shu; stack *del; shu=(head)->num; del=head; head=(head)->top; free(del); return shu; } void destroy(stack **head) { stack *del; while(*head!=NULL) { del=*head; *head=(*head)->top; free(del); } } void visit(stack *head) { while(head) { if(head->top!=NULL) { cout<<head->num<<" "; } else { cout<<head->num<<endl; } head=head->top; } } int top(stack *head) { return head->num; } bool Isempty(stack *head) { if(head==NULL) return true; else return false; } int main() { char c[]="0123456789ABCDEF"; int n,k; while(cin>>n>>k) { stack *p=NULL; if(n<0) { n=-n; if(k>=2&&k<=10) { while(n!=0) { push(p,n%k); n/=k; } cout<<"-"; while(!Isempty(p)) { cout<<top(p); pop(p); } cout<<endl; } else { while(n!=0) { push(p,n%k); n/=k; } cout<<"-"; while(!Isempty(p)) { cout<<c[top(p)]; pop(p); } cout<<endl; } } else { if(k>=2&&k<=10) { while(n!=0) { push(p,n%k); n/=k; } while(!Isempty(p)) { cout<<top(p); pop(p); } cout<<endl; } else { while(n!=0) { push(p,n%k); n/=k; } while(!Isempty(p)) { cout<<c[top(p)]; pop(p); } cout<<endl; } } destroy(&p); } return 0; }
(2)语法词法分析
(3)表达式求值等//此为大神所写,大家可以借鉴一下
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #define true 1 #define false 0 #define OPSETSIZE 8 typedef int Status; unsigned char Prior[8][8] = { // 运算符优先级表 // '+' '-' '*' '/' '(' ')' '#' '^' /*'+'*/'>','>','<','<','<','>','>','<', /*'-'*/'>','>','<','<','<','>','>','<', /*'*'*/'>','>','>','>','<','>','>','<', /*'/'*/'>','>','>','>','<','>','>','<', /*'('*/'<','<','<','<','<','=',' ','<', /*')'*/'>','>','>','>',' ','>','>','>', /*'#'*/'<','<','<','<','<',' ','=','<', /*'^'*/'>','>','>','>','<','>','>','>' }; typedef struct StackChar { char c; struct StackChar *next; }SC; //StackChar类型的结点SC typedef struct Stackdouble { double f; struct Stackdouble *next; }SF; //Stackdouble类型的结点SF SC *Push(SC *s,char c) //SC类型的指针Push,返回p { SC *p=(SC*)malloc(sizeof(SC)); p->c=c; p->next=s; return p; } SF *Push(SF *s,double f) //SF类型的指针Push,返回p { SF *p=(SF*)malloc(sizeof(SF)); p->f=f; p->next=s; return p; } SC *Pop(SC *s) //SC类型的指针Pop { SC *q=s; s=s->next; free(q); return s; } SF *Pop(SF *s) //SF类型的指针Pop { SF *q=s; s=s->next; free(q); return s; } double Operate(double a,unsigned char theta, double b) //计算函数Operate { switch(theta) { case '+': return a+b; case '-': return a-b; case '*': return a*b; case '/': return a/b; case '^': return pow(a,b); default : return 0; } } char OPSET[OPSETSIZE]={'+','-','*','/','(',')','#','^'}; Status In(char Test,char *TestOp) { int Find=false; for (int i=0; i< OPSETSIZE; i++) { if(Test == TestOp[i]) Find= true; } return Find; } Status ReturnOpOrd(char op,char *TestOp) { for(int i=0; i< OPSETSIZE; i++) { if (op == TestOp[i]) return i; } } char precede(char Aop, char Bop) { return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)]; } double EvaluateExpression(char* MyExpression) { // 算术表达式求值的算符优先算法 // 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合 SC *OPTR=NULL; // 运算符栈,字符元素 SF *OPND=NULL; // 运算数栈,实数元素 char TempData[20]; double Data,a,b; char theta,*c,Dr[]={'#','