當前位置:首頁 » 操作系統 » 計算表達式演算法

計算表達式演算法

發布時間: 2022-05-02 21:06:14

A. 求演算法表達式,要詳細解釋


c語言是一種計算機程序設計語言。它既有高級語言的特點,又具有匯編語言的特點。它可以作為系統設計語言,編寫工作系統應用程序,也可以作為應用程序設計語言,編寫不依賴計算機硬體的應用程序。因此,它的應用范圍廣泛。

C語言對操作系統和系統使用程序以及需要對硬體進行操作的場合,用C語言明顯優於其它解釋型高級語言,有一些大型應用軟體也是用C語言編寫的。

C語言具有繪圖能力強,可移植性,並具備很強的數據處理能力,因此適於編寫系統軟體,三維,二維圖形和動畫。它是數值計算的高級語言。

常用的C語言IDE(集成開發環境)有Microsoft Visual C++,Borland C++,Watcom C++ ,Borland C++ ,Borland C++ Builder,Borland C++ 3.1 for DOS,Watcom C++ 11.0 for DOS,GNU DJGPP C++ ,Lccwin32 C Compiler 3.1,Microsoft C,High C,Turbo C等等......

C語言的缺點

1. C語言的缺點主要是表現在數據的封裝性上,這一點使得C在數據的安全性上做的有很大缺陷,這也是C和C++的一大區別。

2. C語言的語法限制不太嚴格,對變數的類型約束不嚴格,影響程序的安全性,對數組下標越界不作檢查等。從應用的角度,C語言比其他高級語言較難掌握。

[C語言指針]
指針就是C語言的一大特色,可以說C語言優於其它高級語言的一個重要原因就是因為它有指針操作可以直接進行靠近硬體的操作,但是C的指針操作也給它帶來了很多不安全的因素。C++在這方面做了很好的改進,在保留了指針操作的同時又增強了安全性。Java取消了指針操作,提高了安全性。

C源程序的結構特點

1.一個C語言源程序可以由一個或多個源文件組成。

2.每個源文件可由一個或多個函數組成。

3.一個源程序不論由多少個文件組成,都有一個且只能有一個main函數,即主函數。

4.源程序中可以有預處理命令(include 命令僅為其中的一種),預處理命令通常應放在源文件或源程序的最前面。

5.每一個說明,每一個語句都必須以分號結尾。但預處理命令,函數頭和花括弧「}」之後不能加分號。

6.標識符,關鍵字之間必須至少加一個空格以示間隔。若已有明顯的間隔符,也可不再加空格來間隔。

學習C語言

在初學C語言時,可能會遇到有些問題理解不透,或者表達方式與以往數學學習中不同(如運算符等),這就要求不氣餒,不明白的地方多問多想,鼓足勇氣進行學習,待學完後面的章節知識,前面的問題也就迎刃而解了,這一方面我感覺是我們同學最欠缺,大多學不好的就是因為一開始遇到困難就放棄,曾經和好多同學談他的問題,回答是聽不懂、不想聽、放棄這樣三個過程,我反問,這節課你聽過課嗎?回答又是沒有,根本就沒聽過課,怎麼說自己聽不懂呢?相應的根本就沒學習,又談何學的好?
學習C語言始終要記住「曙光在前頭」和「千金難買回頭看」,「千金難買回頭看」是學習知識的重要方法,就是說,學習後面的知識,不要忘了回頭弄清遺留下的問題和加深理解前面的知識,這是我們學生最不易做到的,然而卻又是最重要的。學習C語言就是要經過幾個反復,才能前後貫穿,積累應該掌握的C知識。
那麼,我們如何學好《C程序設計》呢?
一.學好C語言的運算符和運算順序
這是學好《C程序設計》的基礎,C語言的運算非常靈活,功能十分豐富,運算種類遠多於其它程序設計語言。在表達式方面較其它程序語言更為簡潔,如自加、自減、逗號運算和三目運算使表達式更為簡單,但初學者往往會覺的這種表達式難讀,關鍵原因就是對運算符和運算順序理解不透不全。當多種不同運算組成一個運算表達式,即一個運算式中出現多種運算符時,運算的優先順序和結合規則顯得十分重要。在學習中,只要我們對此合理進行分類,找出它們與我們在數學中所學到運算之間的不同點之後,記住這些運算也就不困難了,有些運算符在理解後更會牢記心中,將來用起來得心應手,而有些可暫時放棄不記,等用到時再記不遲。
先要明確運算符按優先順序不同分類,《C程序設計》運算符可分為15種優先順序,從高到低,優先順序為1 ~ 15,除第2、3級和第14級為從右至左結合外,其它都是從左至右結合,它決定同級運算符的運算順序.

二.學好C語言的四種程序結構
(1)順序結構
順序結構的程序設計是最簡單的,只要按照解決問題的順序寫出相應的語句就行,它的執行順序是自上而下,依次執行。
例如;a = 3,b = 5,現交換a,b的值,這個問題就好像交換兩個杯子水,這當然要用到第三個杯子,假如第三個杯子是c,那麼正確的程序為: c = a; a = b; b = c; 執行結果是a = 5,b = c = 3如果改變其順序,寫成:a = b; c = a; b = c; 則執行結果就變成a = b = c = 5,不能達到預期的目的,初學者最容易犯這種錯誤。順序結構可以獨立使用構成一個簡單的完整程序,常見的輸入、計算,輸出三步曲的程序就是順序結構,例如計算圓的面積,其程序的語句順序就是輸入圓的半徑 r,計算s = 3.14159*r*r,輸出圓的面積s。不過大多數情況下順序結構都是作為程序的一部分,與其它結構一起構成一個復雜的程序,例如分支結構中的復合語句、循環結構中的循環體等。

(2) 分支結構
順序結構的程序雖然能解決計算、輸出等問題,但不能做判斷再選擇。對於要先做判斷再選擇的問題就要使用分支結構。分支結構的執行是依據一定的條件選擇執行路徑,而不是嚴格按照語句出現的物理順序。分支結構的程序設計方法的關鍵在於構造合適的分支條件和分析程序流程,根據不同的程序流程選擇適當的分支語句。分支結構適合於帶有邏輯或關系比較等條件判斷的計算,設計這類程序時往往都要先繪制其程序流程圖,然後根據程序流程寫出源程序,這樣做把程序設計分析與語言分開,使得問題簡單化,易於理解。程序流程圖是根據解題分析所繪制的程序執行流程圖。
學習分支結構不要被分支嵌套所迷惑,只要正確繪制出流程圖,弄清各分支所要執行的功能,嵌套結構也就不難了。嵌套只不過是分支中又包括分支語句而已,不是新知識,只要對雙分支的理解清楚,分支嵌套是不難的。下面我介紹幾種基本的分支結構。
①if(條件)
{
分支體
}
這種分支結構中的分支體可以是一條語句,此時「」可以省略,也可以是多條語句即復合語句。它有兩條分支路徑可選,一是當條件為真,執行分支體,否則跳過分支體,這時分支體就不會執行。如:要計算x的絕對值,根據絕對值定義,我們知道,當x>=0時,其絕對值不變,而x<0時其絕對值是為x的反號,因此程序段為:if(x<0) x=-x;

②if(條件)

else

這是典型的分支結構,如果條件成立,執行分支1,否則執行分支2,分支1和分支2都可以是1條或若干條語句構成。如:求ax^2+bx+c=0的根
分析:因為當b^2-4ac>=0時,方程有兩個實根,否則(b^2-4ac<0)有兩個共軛復根。其程序段如下:
d=b*b-4*a*c;
if(d>=0)
{x1=(-b+sqrt(d))/2a;
x2=(-b-sqrt(d))/2a;
printf(「x1=%8.4f,x2=%8.4f\n」,x1,x2);
}
else
{r=-b/(2*a);
i =sqrt(-d)/(2*a);
printf(「x1=%8.4f+%8.4fi\n」r, i);
printf(「x2=%8.4f-%8.4fi\n」r,i)
}

③嵌套分支語句:其語句格式為:
if(條件1) ;
else if(條件2)
else if(條件3)
……
else if(條件n)
else
嵌套分支語句雖可解決多個入口和出口的問題,但超過3重嵌套後,語句結構變得非常復雜,對於程序的閱讀和理解都極為不便,建議嵌套在3重以內,超過3重可以用下面的語句。

④switch開關語句:該語句也是多分支選擇語句,到底執行哪一塊,取決於開關設置,也就是表達式的值與常量表達式相匹配的那一路,它不同if… else 語句,它的所有分支都是並列的,程序執行時,由第一分支開始查找,如果相匹配,執行其後的塊,接著執行第2分支,第3分支……的塊,直到遇到break語句;如果不匹配,查找下一個分支是否匹配。這個語句在應用時要特別注意開關條件的合理設置以及break語句的合理應用。

(3)循環結構:
循環結構可以減少源程序重復書寫的工作量,用來描述重復執行某段演算法的問題,這是程序設計中最能發揮計算機特長的程序結構,C語言中提供四種循環,即 goto循環、while循環、do –while循環和for循環。四種循環可以用來處理同一問題,一般情況下它們可以互相代替換,但一般不提倡用goto循環,因為強制改變程序的順序經常會給程序的運行帶來不可預料的錯誤,在學習中我們主要學習while、do…while、for三種循環。常用的三種循環結構學習的重點在於弄清它們相同與不同之處,以便在不同場合下使用,這就要清楚三種循環的格式和執行順序,將每種循環的流程圖理解透徹後就會明白如何替換使用,如把while循環的例題,用for語句重新編寫一個程序,這樣能更好地理解它們的作用。特別要注意在循環體內應包含趨於結束的語句(即循環變數值的改變),否則就可能成了一個死循環,這是初學者的一個常見錯誤。
在學完這三個循環後,應明確它們的異同點:用while和do…while循環時,循環變數的初始化的操作應在循環體之前,而for循環一般在語句1中進行的;while 循環和for循環都是先判斷表達式,後執行循環體,而do…while循環是先執行循環體後判斷表達式,也就是說do…while的循環體最少被執行一次,而while 循環和for就可能一次都不執行。另外還要注意的是這三種循環都可以用break語句跳出循環,用continue語句結束本次循環,而goto語句與 if構成的循環,是不能用break和 continue語句進行控制的。
順序結構、分支結構和循環結構並不彼此孤立的,在循環中可以有分支、順序結構,分支中也可以有循環、順序結構,其實不管哪種結構,我們均可廣義的把它們看成一個語句。在實際編程過程中常將這三種結構相互結合以實現各種演算法,設計出相應程序,但是要編程的問題較大,編寫出的程序就往往很長、結構重復多,造成可讀性差,難以理解,解決這個問題的方法是將C程序設計成模塊化結構。

(4)模塊化程序結構
C語言的模塊化程序結構用函數來實現,即將復雜的C程序分為若干模塊,每個模塊都編寫成一個C函數,然後通過主函數調用函數及函數調用函數來實現一大型問題的C程序編寫,因此常說:C程序=主函數+子函數。 因此,對函數的定義、調用、值的返回等中要尤其注重理解和應用,並通過上機調試加以鞏固。

三.掌握一些簡單的演算法
編程其實一大部分工作就是分析問題,找到解決問題的方法,再以相應的編程語言寫出代碼。這就要求掌握演算法,根據我們的《C程序設計》教學大綱中,只要求我們掌握一些簡單的演算法,在掌握這些基本演算法後,要完成對問題的分析就容易了。如兩個數的交換、三個數的比較、選擇法排序和冒泡法排序,這就要求我們要清楚這些演算法的內在含義
結語:當我們把握好上述幾方面後,只要同學們能克服畏難、厭學、上課能專心聽講,做好練習與上機調試,其實C語言並不難學

C源程序的關鍵字---------------------------------------------------------------------------------------
所謂關鍵字就是已被C語言本身使用, 不能作其它用途使用的字。例如關鍵字不能用作變數名、函數名等
由ANSI標準定義的C語言關鍵字共32個 :
auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if while static
根據關鍵字的作用,可分其為數據類型關鍵字、控制語句關鍵字、存儲類型關鍵字和其它關鍵字四類。
1 數據類型關鍵字(12個):
(1) char :聲明字元型變數或函數
(2) double :聲明雙精度變數或函數
(3) enum :聲明枚舉類型
(4) float:聲明浮點型變數或函數
(5) int: 聲明整型變數或函數
(6) long :聲明長整型變數或函數
(7) short :聲明短整型變數或函數
(8) signed:聲明有符號類型變數或函數
(9) struct:聲明結構體變數或函數
(10) union:聲明聯合數據類型
(11) unsigned:聲明無符號類型變數或函數
(12) void :聲明函數無返回值或無參數,聲明無類型指針(基本上就這三個作用)
(2)控制語句關鍵字(12個):
A循環語句
(1) for:一種循環語句(可意會不可言傳)
(2) do :循環語句的循環體
(3) while :循環語句的循環條件
(4) break:跳出當前循環
(5) continue:結束當前循環,開始下一輪循環
B條件語句
(1)if: 條件語句
(2)else :條件語句否定分支(與 if 連用)
(3)goto:無條件跳轉語句
C開關語句
(1)switch :用於開關語句
(2)case:開關語句分支
(3)default:開關語句中的「其他」分支
D
return :子程序返回語句(可以帶參數,也看不帶參數)
3 存儲類型關鍵字(4個)
(1)auto :聲明自動變數 一般不使用
(2)extern:聲明變數是在其他文件正聲明(也可以看做是引用變數)
(3)register:聲明積存器變數
(4)static :聲明靜態變數
4 其它關鍵字(4個):
(1)const :聲明只讀變數
(2)sizeof:計算數據類型長度
(3)typedef:用以給數據類型取別名(當然還有其他作用
(4)volatile:說明變數在程序執行中可被隱含地改變

B. 算術表達式求值演算法實現的難點剖析

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>

#define TRUE 1
#define FALSE 0
#define Stack_Size 50

char ops[7]={'+','-','*','/','(',')','#'}; /*運算符數組*/

int cmp[7][7]={{2,2,1,1,1,2,2}, /*用來進行比較運算符優先順序的矩陣,3代表'=',2代表'>',1代表'<',0代表不可比*/
{2,2,1,1,1,2,2},
{2,2,2,2,1,2,2},
{2,2,2,2,1,2,2},
{1,1,1,1,1,3,0},
{2,2,2,2,0,2,2},
{1,1,1,1,1,0,3}};

typedef struct
{
char elem[Stack_Size];
int top;
}SeqStack; /*運算符棧的定義*/

typedef struct
{
int elem[Stack_Size];
int top;
}nSeqStack; /* 運算數棧的定義*/

void InitStack(SeqStack *S) /*初始化運算符棧*/
{
S->top =-1;
}

void InitStackn(nSeqStack *S) /*初始化運算數棧*/
{
S->top =-1;
}

int IsEmpty(SeqStack *S) /*判斷棧S為空棧時返回值為真,反之為假*/
{
return(S->top==-1?TRUE:FALSE);
}

int IsEmptyn(nSeqStack *S) /*判斷棧S為空棧時返回值為真,反之為假*/
{
return(S->top==-1?TRUE:FALSE);
}

/*判棧滿*/
int IsFull(SeqStack *S) /*判斷棧S為滿棧時返回值為真,反之為假*/
{
return(S->top==Stack_Size-1?TRUE:FALSE);
}

int IsFulln(nSeqStack *S) /*判斷棧S為滿棧時返回值為真,反之為假*/
{
return(S->top==Stack_Size-1?TRUE:FALSE);
}

int Push(SeqStack *S, char x) /*運算符棧入棧函數*/
{
if (S->top==Stack_Size-1)
{
printf("Stack is full!\n");
return FALSE;
}
else
{
S->top++;
S->elem[S->top]=x;
return TRUE;
}
}

int Pushn(nSeqStack *S, int x) /*運算數棧入棧函數*/
{
if (S->top==Stack_Size-1)
{
printf("Stack is full!\n");
return FALSE;
}
else
{
S->top++;
S->elem[S->top]=x;
return TRUE;
}
}

int Pop(SeqStack *S, char *x) /*運算符棧出棧函數*/
{
if (S->top==-1)
{
printf("運算符棧空!\n");
return FALSE;
}
else
{
*x=S->elem[S->top];
S->top--;
return TRUE;
}
}

int Popn(nSeqStack *S, int *x) /*運算數棧出棧函數*/
{
if (S->top==-1)
{
printf("運算符棧空!\n");
return FALSE;
}
else
{
*x=S->elem[S->top];
S->top--;
return TRUE;
}
}

char GetTop(SeqStack *S) /*運算符棧取棧頂元素函數*/
{
if (S->top ==-1)
{
printf("運算符棧為空!\n");
return FALSE;
}
else
{
return (S->elem[S->top]);
}
}

int GetTopn(nSeqStack *S) /*運算數棧取棧頂元素函數*/
{
if (S->top ==-1)
{
printf("運算符棧為空!\n");
return FALSE;
}
else
{
return (S->elem[S->top]);
}
}

int Isoperator(char ch) /*判斷輸入字元是否為運算符函數,是返回TRUE,不是返回FALSE*/
{
int i;
for (i=0;i<7;i++)
{
if(ch==ops[i])
return TRUE;
}
return FALSE;
}

/*
int isvariable(char ch)
{ if (ch>='a'ch<='z')
return true;
else
return false;
}*/

char Compare(char ch1, char ch2) /*比較運算符優先順序函數*/
{
int i,m,n;
char pri; /*保存優先順序比較後的結果'>'、'<'、'='*/
int priority; /*優先順序比較矩陣中的結果*/
for(i=0;i<7;i++) /*找到相比較的兩個運算符在比較矩陣里的相對位置*/
{
if(ch1==ops[i])
m=i;
if (ch2==ops[i])
n=i;
}

priority = cmp[m][n];
switch(priority)
{
case 1:
pri='<';
break;
case 2:
pri='>';
break;
case 3:
pri='=';
break;
case 0:
pri='$';
printf("表達式錯誤!\n");
break;
}
return pri;
}

int Execute(int a, char op, int b) /*運算函數*/
{
int result;
switch(op)
{
case '+':
result=a+b;
break;
case '-':
result=a-b;
break;
case '*':
result=a*b;
break;
case '/':
result=a/b;
break;
}
return result;
}

int ExpEvaluation()
/*讀入一個簡單算術表達式並計算其值。optr和operand分別為運算符棧和運算數棧,OPS為運算符集合*/
{
int a,b,v,temp;
char ch,op;
char *str;
int i=0;

SeqStack optr; /*運算符棧*/
nSeqStack operand; /*運算數棧*/

InitStack(optr);
InitStackn(operand);
Push(optr,'#');
printf("請輸入表達式(以#結束):\n"); /*表達式輸入*/
str =(char *)malloc(50*sizeof(char));
gets(str); /*取得一行表達式至字元串中*/

ch=str[i];
i++;
while(ch!='#'||GetTop(optr)!='#')
{
if(!Isoperator(ch))
{
temp=ch-'0'; /*將字元轉換為十進制數*/
ch=str[i];
i++;
while(!Isoperator(ch))
{
temp=temp*10 + ch-'0'; /*將逐個讀入運算數的各位轉化為十進制數*/
ch=str[i];
i++;
}
Pushn(operand,temp);
}
else
{
switch(Compare(GetTop(optr),ch))
{
case '<':
Push(optr,ch);
ch=str[i];
i++;
break;
case '=':
Pop(optr,op);
ch=str[i];
i++;
break;
case '>':
Pop(optr,op);
Popn(operand,b);
Popn(operand,a);
v=Execute(a,op,b); /* 對a和b進行op運算 */
Pushn(operand,v);
break;
}
}
}
v=GetTopn(operand);
return v;
}

void main() /*主函數*/
{
int result;
result=ExpEvaluation();
printf("\n表達式結果是%d\n",result);
}

C. 表達式求值演算法的完善及程序實現

表達式的計算應用相當廣泛,比如電力調度系統中的計算遙測、車站票務系統中的票價類型計算公式等。
本文講述中置表達式轉換為後置表達式和後置表達式的求值演算法,並給出實現的C++源代碼,同時給出一個相當簡潔的堆棧C++模板類。

中綴表達式到後綴表達式的轉換
要把表達式從中綴表達式的形式轉換成用後綴表示法表示的等價表達式,必須了解操作符的優先順序和結合性。優先順序或者說操作符的強度決定求值順序;優先順序高 的操作符比優先順序低的操作符先求值。 如果所有操作符優先順序一樣,那麼求值順序就取決於它們的結合性。操作符的結合性定義了相同優先順序操作符組合的順序(從右至左或從左至右)。

D. 急!算數表達式求值的優先演算法!

定義:運算符棧S,操作數棧C
讀3+,+壓入棧S,3壓入棧C;
讀5*7,*壓入棧S,5壓入棧C,7壓入棧C;
讀-,*運算順序高於+-,取棧C中的7和5,取棧S中的*,計算5*7=35,35壓入棧C,-壓入棧S;
讀4,壓入棧C,讀取完;
取棧C中的4和35,取棧S中的-,計算35-4=31,取棧C中的3,取棧S中的+,計算3+31=34

E. 怎麼用c語言輸入計算表達式的演算法

可以。
逗號運算符,從左至右計算,取最後一個表達式的值作為整個語句的值。
先算a=3,就是把a賦值成3,然後算b=4,對b賦值成4,最後計算c=a+b,實際就是c=3+4,c的值是7。最終整條語句的最後值就是c的值7.

F. Java計算字元串中的數學表達式的值演算法怎麼寫

代碼網上很多,只說說演算法吧
12+8/4-5+(3-4)

把這樣的表達式拆成:(操作數)(操作符) 、
12+
8/
4-
5+(
3-
4)
(術語叫做逆波蘭式)
默認的計算順序是從左往右,記為left。另設從右往左,記為right
設計Element類,具有 操作數 operant, 操作符operator, 操作順序 order三個屬性
用兩個先進後出的棧結構Stack<Element> a,b;
一開始所有的Element都在a中,逐個彈出計算合並值,
當遇到乘、除、括弧時計算順序改變成right,把當前結果放到b中暫存。
直到再次遇到加、減、)右括弧時,意味計算順序復位成left,先把b中的暫存結果全部合並後,再繼續算a中的剩餘數據
最後合並成一個結果值。

G. 求用C語言編寫一個算術表達式的演算法,如輸入3*4+8-2鍵入Enter鍵輸出18.

#include<iostream.h>
//#defineMaxLen100//存儲空間
inttran(charstr[],charexpr[])//將中綴表達式轉換成後綴表達式if(tran(str,expr)==0)//原來表達式,後綴表達式
{
intst[100];//轉化過程使用的過度棧
charch;
inti=0,exindex=0,stindex=-1;//i是str下標,exindex是expr下標,stindex是st下標
while((ch=str[i++])!='')
{
if(ch>='0'&&ch<='9')//判斷是數字
{
expr[exindex]=ch;//壓棧
exindex++;//棧頂指針上移
while((ch=str[i++])!=''&&ch>='0'&&ch<='9')//其它位依次入棧
{
expr[exindex]=ch;
exindex++;
}
i--;//str原算術表達式棧向下遍歷
expr[exindex]='#';//以特殊字元「#」表示結束
exindex++;
}
elseif(ch=='(')//判斷為左括弧
{
stindex++;
st[stindex]=ch;
}
elseif(ch==')')//判斷為右括弧
{
while(st[stindex]!='(')
{
expr[exindex]=st[stindex];
stindex--;//依次彈出
exindex++;
}
stindex--;//'('出棧
}
elseif(ch=='+'||ch=='-')//判斷為加減號
{
while(stindex>=0&&st[stindex]!='(')
{
expr[exindex]=st[stindex];
stindex--;
exindex++;
}
stindex++;
st[stindex]=ch;
}
elseif(ch=='*'||ch=='/')//判斷為乘除號
{
while(st[stindex]=='*'||st[stindex]=='/')
{
expr[exindex]=st[stindex];
stindex--;
exindex++;
}
stindex++;
st[stindex]=ch;
}
}
while(stindex>=0)//將棧中所有運算符依次彈出存入expr棧中
{
expr[exindex]=st[stindex];
exindex++;
stindex--;
}
expr[exindex]='';
return1;
}
intcompvalue(charexpr[],int*n)
{
intst[100],d;//st為數棧
charch;
intexindex=0,stindex=-1;//exindex是expr下標,stindex是st的下標
while((ch=expr[exindex++])!='')
{
if(ch>='0'&&ch<='9')//將數字字元轉換成數字
{
d=0;
do
{
d=10*d+ch-'0';
}
while((ch=expr[exindex++])!='#');
stindex++;
st[stindex]=d;//數字進棧
}
else//運算符操作
{
switch(ch)
{
case'+':st[stindex-1]=st[stindex-1]+st[stindex];
break;
case'-':st[stindex-1]=st[stindex-1]-st[stindex];
break;
case'*':st[stindex-1]=st[stindex-1]*st[stindex];
break;
case'/':
if(st[stindex]!=0)
{st[stindex-1]=st[stindex-1]/st[stindex];}
elsereturn0;//除0錯誤!
break;
}
stindex--;
}
}
(*n)=st[stindex];
return1;
}

voidmain()
{
charstr[100];//存儲原來算術表達式
charexpr[100];//存儲轉換成的後綴表達式
intn;
cout<<"輸入算術表達式:"<<endl;
cin>>str;
if(tran(str,expr)==0)
{
cout<<"原算術表達式不正確!"<<endl;
}
else
{
cout<<"轉換成後綴表達式輸出:"<<endl<<expr<<endl;
if(compvalue(expr,&n)==1)
{
cout<<"表達式求值:"<<endl<<n<<endl;
}
else
{
cout<<"計算錯誤!"<<endl;
}

}

H. 演算法手記Dijkstra雙棧算術表達式求值演算法

這兩天看到的內容是關於棧和隊列,在棧的模塊發現了Dijkstra雙棧算術表達式求值演算法,可以用來實現計算器類型的app。

編程語言系統一般都內置了對算術表達式的處理,但是他們是如何在內部實現的呢?為了了解這個過程,我們可以自行搭建一套簡易的算術表達式處理機制,這里就用到棧特性和本篇提到的Dijkstra演算法。

概述:
算術表達式可能是一個數、或者是由一個左括弧、一個算術表達式、一個運算符、另一個算術表達式和一個右括弧組成的表達式。為了簡化問題,這里定義的是未省略括弧的算術表達式,它明確地說明了所有運算符的操作數,形式如下:

(1+((2+3)*(4*5)))

思路:

表達式由括弧、運算符和操作數構成,我們根據以下4中情況從左至右逐個將這些實體送入棧處理:

1.將操作數壓入操作數棧;

2.將運算符壓入運算符棧;

3.忽略左括弧;

4.在遇到右括弧時,彈出一個運算符,彈出所需數量的操作數,並將運算後的結果壓入操作數棧;

在處理完最後一個右括弧時,操作數棧上只會剩下一個值,它就是表達式的計算結果。這種方法咋一看難理解,但要證明它能計算得到正確的值很簡單:

每當演算法遇到一個括弧包圍,並由一個運算符和兩個操作數組成的子式時,他都將運算符和操作數運算結果壓入操作數棧。這樣的結果就像是在輸入中用這個值代替了該子表達式,因此用這個值代替子表達式得到的結果和原表達式相同。我們可以反復應用這個規律並得到一個最終值。

例如:

(1+((2+3)*(4*5)))

(1+(5*(4*5)))

(1+(5*20))

(1+100)

101

代碼實現:

這里我採用C#來實現,最終運行效果完全符合預期,證明了此演算法的正確性,代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Evaluate
{
class Program
{
static void Main(string[] args)
{
string testExpress = "(1+((2+3)*(4*5)))";
Console.WriteLine(Evaluate(testExpress));
}

//DijkStra
static double Evaluate(string express)
{
var expressChars = express.ToArray<char>();
Stack<char> ops = new Stack<char>();
Stack<double> vals = new Stack<double>();
if (express.Length > 0)
{
foreach (var opt in expressChars)
{
switch (opt)
{
case '+':
case '-':
case '*':
case '/':
ops.Push(opt);
break;
case ')':
var op = ops.Pop();
var v = vals.Pop();
switch (op)
{
case '+':
v += vals.Pop();
break;
case '-':
v = vals.Pop() - v;
break;
case '*':
v *= vals.Pop();
break;
case '/':
v = vals.Pop() / v;
break;
}
vals.Push(v);
break;
case ' ':
case '(':
break;
default:
vals.Push(double.Parse(opt.ToString()));
break;
}
}
return vals.Pop();

}
return double.MaxValue;
}
}
}
總結:

Dijkstra演算法充分利用了棧的特性,具備較高的執行效率,經過進一步的擴充修改,就完全可以實現具備科學計算功能的復雜計算類app。如果大家還有更好的,更適用的演算法,歡迎在評論中給出地址,謝謝。
轉載

I. 演算法與計算公式的區別請舉例說明

演算法是程序執行的一系列步驟和方法。
計算公式是計算的方法。
計算公式也可以用於演算法當中,演算法不僅是數的運算步驟,也是其他非數的執行的步驟和方法,如華羅庚的燒水,做飯的步驟一樣。計算公式就是用來提供給演算法應用的一種而已。

熱點內容
萬魔斬腳本 發布:2024-10-06 08:23:18 瀏覽:876
華強北耳機連安卓手機下什麼軟體 發布:2024-10-06 08:21:53 瀏覽:251
兒科發現傳染病的應急演練腳本 發布:2024-10-06 08:21:48 瀏覽:598
玩王者榮耀的時候要買哪個配置 發布:2024-10-06 08:19:41 瀏覽:620
imovie怎麼清理緩存 發布:2024-10-06 08:14:30 瀏覽:17
python字典list 發布:2024-10-06 08:14:26 瀏覽:578
amhip訪問 發布:2024-10-06 08:03:54 瀏覽:437
joy加密 發布:2024-10-06 07:53:27 瀏覽:201
結構是由哪種腳本語言填寫的 發布:2024-10-06 07:24:27 瀏覽:744
客戶端反編譯教學 發布:2024-10-06 07:10:42 瀏覽:783