ZCMU-Data Structure-Stack and Queue
1、从键盘上输入一个后缀表达式,试编写算法计算表达式的值。规定:逆波兰表达式的长度不超过一行,以$符作为输入结束,操作数之间用空格分隔,操作符只可能有+、-、*、/四种运算。例如:234 34+2*$。
思路:逆波兰表达式(即后缀表达式)求值规则如下:设立运算数栈OPND,对表达式从左到右扫描(读入),当表达式中扫描到数时,压入OPND栈。当扫描到运算符时,从OPND退出两个数,进行相应运算,结果再压入OPND栈。这个过程一直进行到读出表达式结束符$,这时OPND栈中只有一个数,就是结果。
float expr( )
//从键盘输入逆波兰表达式,以‘$’表示输入结束,本算法求逆波兰式表达式的值。
{float OPND[30]; // OPND是操作数栈。
init(OPND); //两栈初始化。
float num=0.0; //数字初始化。
cin>>x;//x是字符型变量。
while(x!=’$’)
{switch
{case‘0’<=x<=’9’:
while((x>=’0’&&x<=’9’)||x==’.’) //拼数
if(x!=’.’) //处理整数
{num=num*10+(ord(x)-ord(‘0’)); cin>>x;}
else //处理小数部分。
{scale=10.0; cin>>x;
while(x>=’0’&&x<=’9’)
{num=num+(ord(x)-ord(‘0’)/scale;
scale=scale*10; cin>>x; }
}//else
push(OPND,num); num=0.0;//数压入栈,下个数初始化
case x=‘ ’:break; //遇空格,继续读下一个字符。
case x=‘+’:push(OPND,pop(OPND)+pop(OPND));break;
case x=‘-’:x1=pop(OPND);x2=pop(OPND);push(OPND,x2-x1);break;
case x=‘*’:push(OPND,pop(OPND)*pop(OPND));break;
case x=‘/’:x1=pop(OPND);x2=pop(OPND);push(OPND,x2/x1);break;
default: //其它符号不作处理。
}//结束switch
cin>>x;//读入表达式中下一个字符。
}//结束while(x!=‘$’)
cout<<“后缀表达式的值为”<<pop(OPND);
}//算法结束。
2、已知f为单链表的表头指针, 链表中存储的都是整型数据,试写出实现下列运算的递归算法:
① 求链表中的最大整数;
② 求链表的结点个数;
③ 求所有整数的平均值。
①
int GetMax(LinkList p)
{
if(!p->next)
return p->data;
else
{
int max=GetMax(p->next);
return p->data>=max ? p->data:max;
}
}
②
int GetLength(LinkList p)
{
if(!p->next)
return 1;
else
{
return GetLength(p->next)+1;
}
}
③
double GetAverage(LinkList p , int n)
{
if(!p->next)
return p->data;
else
{
double ave=GetAverage(p->next,n-1);
return (ave*(n-1)+p->data)/n;
}
}
3、假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素站点(注意不设头指针) ,试编写相应的置空队、判队空 、入队和出队等算法。
思路:置空队就是建立一个头节点,并把头尾指针都指向头节点,头节点是不存放数据的;判队空就是当头指针等于尾指针时,队空;入队时,将新的节点插入到链队列的尾部,同时将尾指针指向这个节点;出队时,删除的是队头节点,要注意队列的长度大于1还是等于1的情况,这个时候要注意尾指针的修改,如果等于1,则要删除尾指针指向的节点。
//先定义链队结构:
typedef struct queuenode
{Datatype data;
struct queuenode *next;
}QueueNode; //以上是结点类型的定义
typedef struct
{queuenode *rear;
}LinkQueue; //只设一个指向队尾元素的指针
(1) 置空队
void InitQueue( LinkQueue *Q)
{ //置空队:就是使头结点成为队尾元素
QueueNode *s;
Q->rear = Q->rear->next;//将队尾指针指向头结点
while (Q->rear!=Q->rear->next)//当队列非空,将队中元素逐个出队
{s=Q->rear->next;
Q->rear->next=s->next;
delete s;
}//回收结点空间
}
(2) 判队空
int EmptyQueue( LinkQueue *Q)
{ //判队空。当头结点的next指针指向自己时为空队
return Q->rear->next->next==Q->rear->next;
}
(3) 入队
void EnQueue( LinkQueue *Q, Datatype x)
{ //入队。也就是在尾结点处插入元素
QueueNode *p=new QueueNode;//申请新结点
p->data=x; p->next=Q->rear->next;//初始化新结点并链入
Q-rear->next=p;
Q->rear=p;//将尾指针移至新结点
}
(4) 出队
Datatype DeQueue( LinkQueue *Q)
{//出队,把头结点之后的元素摘下
Datatype t;
QueueNode *p;
if(EmptyQueue( Q ))
Error("Queue underflow");
p=Q->rear->next->next; //p指向将要摘下的结点
x=p->data; //保存结点中数据
if (p==Q->rear)
{//当队列中只有一个结点时,p结点出队后,要将队尾指针指向头结点
Q->rear = Q->rear->next;
Q->rear->next=p->next;
}
else
Q->rear->next->next=p->next;//摘下结点p
delete p;//释放被删结点
return x;
}