一、栈的表示和操作的实现
- 定义:栈(stack)是限定只在表尾进行插入或删除操作的线性表;表头为栈底(bottom),表尾为栈顶(top);不含元素叫空栈;具有后进先出(LIFO)的特点。
- 顺序栈的表示和实现
//-----顺序栈的存储结构----- #define MAXSIZE 100 //顺序栈存储最大容量 typedef struct { SElemType *base; //栈底指针 SElemType *top; //栈顶指针 int stacksize; //栈可用的最大容量 }SqStack; //-----顺序栈的建立----- Status InitStack(SqStack &s) { s.base=new SElemType[MAXSIZE]; //分配容量 if(!s.base) exit(OVERFLOW); //分配错误 s.top=s.base; //空栈 s.stacksize=MAXSIZE; return OK; } *s.top++=e; //入栈 e=*--s.top; //出栈 *(s.top-1); //取栈顶元素
-
链栈的表示和实现
//-----链栈的存储结构----- typedef struct StackNode { ElemType data; //数据域 ElemType StackNode *next; //指针域 }StackNode,*LinkStack; S=NULL; //链栈初始化 {//入栈 p=new StackNode; //新结点 p->data=e; p->next=S; S=p; //修改栈顶指针为p } {//出栈 if(S==NULLL) return ERROR; //栈空 e=S->data; p=S; S=S->next; delete p; }
二、队列的表示和操作的实现
1.定义:队列(queue)是一种允许在表的一端删除,另一端插入的线性表;允许插入的一端为队尾(rear),允许删除的一端是队头(front);具有先进先出(FIFO)的特点。
2.循环队列的顺序表示和实现
//-----队列的顺序存储结构-----
#define MAXSIZE 100 //队列可能最大长度
typedef struct
{
QElemType *base; //存储空间的基地址
int front; //头指针
int rear; //尾指针
}SqQueue;
{//初始化循环队列
Q.base=new QElemType[MAXSIZE];
Q.front=Q.base=0; //队列为空
}
{//求队列长度
length=(Q.rear-Q.front+MAXSIZE)%MAXSIZE;
}
{//入队
Q.base[Q.rear]=e; //新元素入队
Q.rear=(Q.rear+1)%MAXSIZE; //队尾指针加1
}
{//出队
e=Q.base[Q.front]; //队头出队
Q.front=(Q.front+1)%MAXSIZE; //队头指针加1
}
3.链队的表示和实现
//-----队列的链式存储结构-----
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
{//初始化空队列
Q.front = Q.rear =new QNode;
Q.front->next=NULL;
}
{//入队
p=new QNode;
p->data=e;
p-next=NULL;
Q.rear->next=p;
Q.rear=p;
}
{//出队
if(Q.front=Q.rear)
return ERROR; //队列空
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front; //最后一个元素被删,队尾指针指向头结点
delete p;
}
三、栈和队列的应用
1.十进制转八进制问题
思路:可运用栈的特性,将每次 N mod 8 的值压入栈中,然后 N 更新为 N / 8;最后不断从栈顶弹出元素,即为八进制数。
//-----十进制转八进制-----
void conversion(int N)
{
InitStack(S);
while(N)
{
Push(N % 8);
N/=8;
}
while(!StackEmpty(S))
{
Pop(S,e);
cout<<e;
}
}
2.括号匹配问题
思路:可运用栈的特性,将输入的字符串中的左括号压入栈中,若遇到右括号,则判断是否与栈顶的左括号匹配,若匹配,则弹出栈顶的左括号,flag=1;否则,flag=0,即不匹配,退出循环。
//-----括号匹配-----
void matching()
{
InitStack(S);
flag=1;
cin>>ch; //输入第一个字符,字符串以 # 结束
while(ch!='#'&&flag)
{
switch(ch)
{
case '(':
case '[':
Push(S,ch);
break;
case ')':
if(!StackEmpty(S)&&GetTop(S)=='(')
Pop(S,x);
else
flag=0;
break;
case ']':
if(!StackEmpty(S)&&GetTop(S)=='[')
Pop(S,x);
else
flag=0;
break;
}
cin>>ch;
}
if(StackEmpty(S)&&flag)
return TRUE;
else
return FALSE;
}
3.表达式求值
思路:建立两个栈:OPTR存运算符,OPND存操作数和运算结果;表达式以#开头和结尾;比较运算符的优先级来进行运算。
//-----表达式求值-----
char EvaluateExpression()
{
InitStack(OPND); //存操作数和运算结果
InitStack(ONTR); //存运算符
Push(OPTR,'#');
cin>>ch;
while(ch!='#' || GetTop(OPTR)!='#')
{
if(!In(ch))
{
Push(OPND,ch);
cin>>ch; //不是运算符,存入OPND中
}
else //运算符
{
switch (Precede(GetTop(OPTR),ch)) //比较栈顶元素和ch的优先级
{
case '<'
Push(OPTR,ch);
cin>>ch; //将ch压入栈
break;
case '>'
Pop(OPTR,theta); //弹出运算符
Pop(OPND,b);
Pop(OPND,a); //弹出两个操作数
Push(OPND.Operate(a,theta,b)); //将运算结果存入OPND中
break;
case '=':
Pop(OPTR,x);
cin>>ch;
break; //这时候栈顶为( 且ch为 ),括号匹配后弹出栈顶括号
}
}
return GetTop(OPND);
}
}