1. 程式人生 > >浙江中醫藥大學-《資料結構》-棧和佇列演算法設計

浙江中醫藥大學-《資料結構》-棧和佇列演算法設計

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;
}