數據結構實驗項目二:棧的基本操作及其應用

實驗項目二:棧的基本操作及其應用

展示

實驗目的:

1.掌握棧的定義及實現;

2.掌握利用棧求解算術表達式的方法。

實驗要求:

1、    使用鏈式存儲結構完成棧的各種基本操作;

2、    補充完成In(c), Preced(t1,t2),Operate(a,theta,b)三個函數。

實驗題目:棧的基本操作及其應用

實驗過程:

1、通過修改完善教材中的算法3.22,利用棧來實現算術表達式求值的算法。對算法3.22中調用的幾個函數要給出其實現過程:

(1) 函數In(c):判斷c是否爲運算符;

(2) 函數Precede(t1,t2):判斷運算符t1和t2的優先級;

(3) 函數Operate(a,theta,b):對a和b進行二元運算theta。

2、程序運行時,輸入合法的算術表達式(中間值及最終結果要在0~9之間,可以包括加減乘除和括號),便可輸出相應的計算結果。

實驗提示:(僅供參考,每個函數的具體實現可以有多種方法,希望有創新)

1. 將棧的定義和實現單獨保存在頭文件“stack.h”中,然後在表達式求值的源程序中包含此頭文件(即#include“stack.h”)。

2.表達式求值源程序的具體實現

(1) 主函數如下:

void main()

 {

   Printf(“請輸入算術表達式,並以#結束.\n”);

  Printf(“the result of expression is:%d\n”,EvaluateExpression());

 }

(2) 函數EvaluateExpression的實現見算法3.22

(3) 函數In(c)的實現可以採用以下方式:

Status In(SElemType c)// 應在前面有定義typedef char SElemType;

 { // 判斷c是否爲運算符

   switch(c)

   {

     case'+':return TRUE;

     ……//補充完整

default:return FALSE;

   }

 }

(4) 函數Precede(t1,t2)的實現可以採用以下形式:

SElemType Precede(SElemType t1,SElemType t2)

 { //根據教材表3.1,判斷兩個運算符的優先關係

   SElemType f;

   switch(t2)

   {

     case '+':

     case '-':if(t1=='('||t1=='#')

                f='<';

              else

                f='>';

              break;

……//補充完整

}

   return f;

}

(5) 函數Operate(a,theta,b)的實現可以採用以下方式:

SElemType Operate(SElemType a,SElemType theta,SElemType b)

 {

   SElemType c;

   a=a-48;

   b=b-48;

   switch(theta)

   {

     case'+':c=a+b+48;

             break;

……//補充完整

   }

   return c;

 }

選做內容:進一步改進,使表達式的中間值及最終結果不侷限於0~9之間的個位數。(如果完成要在實驗報告中註明)。

實驗結果:

輸入:2*(4-1)+8

輸出:14

該程序能夠完成個位數的四則運算。

實驗分析:

1.棧的操作的特點;

2.列舉調試運行過程中出現的錯誤並分析原因。

要求:

(1) 程序要添加適當的註釋,程序的書寫要採用縮進格式

(2) 程序要具在一定的健壯性,即當輸入數據非法時,程序也能適當地做出反應。

(3) 程序要做到界面友好,在程序運行時用戶可以根據相應的提示信息進行操作。

 

(4) 上傳源程序到課堂派,源程序保存爲calculator.cpp

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <stdlib.h>
 
using namespace std; 
#define MAXSIZE  100				//順序棧存儲空間的初始分配量 
#define OK 1
#define ERROR 0
 
typedef int Status;
typedef char ElemType; 
	
//鏈棧的存儲結構
typedef struct StackNode
{
	ElemType data;
	struct StackNode *next;
 }StackNode,*LinkStack;
 
//鏈棧初始化 
Status InitStack(LinkStack &S)
{
	S=NULL;
	return OK;
 }
 
//入棧操作
Status Push(LinkStack &S,char e)
{
	LinkStack p;
	p=new StackNode;
	p->data=e;
	p->next=S;
	S=p;
	return OK;
 } 
 
//鏈棧的出棧
Status Pop(LinkStack &S,char &e)
{
	LinkStack p;
	if(S==NULL) return ERROR;
	e=S->data;
	p=S;
	S=S->next;
	delete p;
	return OK;
 } 
 
//取棧頂元素
char GetTop(LinkStack S)
{
	if(S!=NULL) 
		return S->data;
 } 
 
//判斷是否是運算符 
bool In(char c)
{
	if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='#') return 1;
	else return 0;
}
 
//比較OPTR棧頂元素和ch的優先級(運算符的優先級)
char Precede(char t1,char t2)
{
	char f;
	if(t1=='+'||t1=='-')
	{
		if(t2=='*'||t2=='/'||t2=='(') f='<';
		else f='>';
	 } 
	else if(t1=='*'||t1=='/')
	{
		if(t2=='(') f='<';
		else f='>';
	}
	else if(t1=='(') 
	{
		if(t2==')') f='=';
		else f='<';
	}
	else if(t1==')')
	{
		f='>';
	}
	else if(t1=='#')
	{
		if(t2=='=') f='=';
		else f='<';
	}
 	
	return f;
 } 
 
//計算簡單算術式
char Operate(char a,char theta,char b)
{
	char ans;
	if(theta=='+') ans=(a-'0')+(b-'0')+'0';
	else if(theta=='-') ans=(a-'0')-(b-'0')+'0';
	else if(theta=='*') ans=(a-'0')*(b-'0')+'0';
	else if(theta=='/') ans=(a-'0')/(b-'0')+'0';
	
	return ans;
 } 
 
//構建函數,求解算數表達式 
char EvaluateExpression()
{
	printf("請輸入一個表達式:\n"); 
	StackNode *OPND;//定義運算數棧
	StackNode *OPTR;//定義運算符棧 
	InitStack(OPND);				//初始化OPND棧,壓入操作數和運算結果
	InitStack(OPTR);				//初始化OPTR棧,壓入操作符
	char c;//起始輸入# 
	cin>>c;
	Push(OPTR,c);					//將表達式起始符'#'壓入OPTR棧頂
	char ch;
	cin>>ch;
	while(ch!='#'||GetTop(OPTR)!='#') 			//用ch!='#'來判斷表達式是否掃描完畢,表達式		
	{										    //沒有掃描完畢或OPTR棧頂元素不爲'#'則繼續執行
		if(!In(ch))	
		{
			Push(OPND,ch);
			cin>>ch; 
		}			
		else 
		
			switch(Precede(GetTop(OPTR),ch))
			{
				case '<':
					
						Push(OPTR,ch);cin>>ch;
						break;
					
				case '>':
					
						char theta;
						char a,b;
						Pop(OPTR,theta);
						Pop(OPND,b);
						Pop(OPND,a);
						Push(OPND,Operate(a,theta,b));
						break;
					
				case '=':
					
					char x;
					Pop(OPTR,x);
					cin>>ch;
					break;
							
			}					
	}
	return GetTop(OPND);										
} 													
 
int main()
{
 	char res=EvaluateExpression();
 	printf("結果爲:");
	cout<<res; 
 
	return 0;
} 

終於完成這個程序了啊,心裏很高興。過程一如既往的困難,因爲自己的不細心和小失誤,但還好堅持寫完了。

書上代碼還是不能全信啊,要獨立思考。 

有兩個印象深刻的收穫:

1、如何查bug?

第一遍我在查bug的時候照着書本一個字母一個字母的查,這辦法挺傻的。

後來我就改變策略了。

如果程序出錯了,(1)你可以把分函數一個一個執行,從而精確尋找錯誤,(2)在程序語句中插入如printf等,通過運行結果查找錯誤,(3)和別人正確的代碼對比,把別人的分函數複製過來使用,精確尋找錯誤。

2、之前只注意到寫程序的時候不能使用中文符號,沒想到這次在輸入中使用了中文符號致錯,花了好長時間才找出來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章