棧是一種特殊的線性表,按照「後進先出」的原則處理資料。
棧的基本操作有兩種:一種是入棧(push),即把資料儲存到棧頂,注意在入棧前應該先檢查棧是否已滿,如滿則不能入棧操作,未滿則修改棧頂指標,使其向上移動乙個元素的位置,然後將資料儲存到棧頂指標所指的位置。 一種是出棧(pop),即把棧頂資料彈出,注意在出棧之前檢查棧是否為空,如果棧為空沒有資料則提示不能進行出棧操作,若不空,則修改棧頂指標,使其指向棧中的下乙個元素。
1.編寫操作棧的標頭檔案
typedef struct stack其中data定義棧中元素的資料型別,size表示棧的最大容量,size+1表示棧的資料從下標為1開始,當top為0時,表示棧為空。seqstack;
2.初始化棧
seqstack *seqstackinit()
return null; //申請記憶體失敗
}
初始化棧需要做兩件事,首先按照size指定的大小申請一片記憶體空間,儲存棧中資料,然後設定棧頂指標的值為0,表示空棧。
3.判斷棧的狀態
int seqstackisempty(seqstack *s) //棧是否為空
int seqstackisfull(seqstack *s) //棧是否滿
對棧操作前先判斷棧的狀態,入棧前棧是否滿,出棧前棧是否為空。
4.清空棧 釋放棧所佔的記憶體空間
void seqstackclear(seqstack *s)
void seqstackfree(seqstack *s) //釋放棧的空間
清空棧時,即把棧頂指標top置0,釋放棧時,因為棧是用malloc函式分配的,所以不使用時用free函式釋放分配的記憶體空間。
5.入棧操作
int seqstackpush(seqstack *s,data data)
s->data[++s->top]=data; //修改棧頂指標,把元素入棧
return 1;
}
入棧時,判斷若top已經滿了(s->top==size),則top+1就超出棧的最大記憶體空間,提示棧溢位,做出錯處理。若沒有溢位,則棧頂指標向上移動一位,把資料放入其中,即入棧。
6.出棧操作
int seqstackpop(seqstack *s) //出棧
return (s->data[s->top--]); //從棧頂彈出元素
}
出棧與入棧相反,從棧頂彈出乙個資料元素。先判斷top是否為0,若為0,則表示空棧,提示出錯,若不為0,修改棧頂指標減一,即往下移動一位,返回此時棧頂指標所指位置,原來棧頂元素彈出,即出棧。
7.獲取棧頂元素
data seqstackpeek(seqstack *s) //讀出棧頂元素
return (s->data[s->top]); //返回棧頂元素
}
在出棧操作中,是把原來的棧頂元素彈出(拋棄了),即出棧後棧頂元素就不存在了,若只是讀取一下棧頂的元素而不刪除,就不需要將top指標往下移動,不修改指標位置,這樣返回棧頂後棧頂資料元素還在。
以上為棧的基本操作,下面舉乙個實用例子深入理解棧的相關操作。
棧的實際運用:算術表示式求值
在計算機中輸入乙個算式如:(2+3)*5 容易知道先計算2+3=5,再將5*5=25,,但計算機在讀入算式時的具體過程是怎樣的?
計算機先逐步掃瞄:先是(括號,這時不知道右括號在**出現,所以先儲存起來,然後是2,也不知道該字元下一位是什麼,也先儲存,然後是+,這時知道是加上乙個數,但不知道加什麼,先儲存起來,然後是3,這時知道是2+3,直接相加嗎?不能,如果3後面是*,或者/的高優先順序話就先計算,所以也先儲存,然後是),這時括號內的2+3就可以取出運算了,得出結果5後再儲存起來(由此可以看出加減的優先順序大於()的優先順序),然後是*,儲存起來,然後是5,儲存起來,然後是=號,表示整個算式結束了,將2+3得到的5與5相乘,輸出最終結果。
由上分析可知,程式需要儲存運算元,儲存運算子(+,-,*,/,=,(,)),還需要確定優先順序(乘除大於加減,加減大於括號,括號可以改變優先順序的順序,相同優先順序從左往右計算)。
為了簡化程式,只考慮加減乘除四則運算。
首先呼叫庫函式:
#include#include#include#define size 50
typedef int data; //定義棧元素型別
#include "biaodashi.h"
第六行引用最開始的棧的基本操作程式為標頭檔案,
具體函式模組分析:
1.每次讀取檢查字元是否為運算子
int isoperator(char c) //檢查字元是否為運算子
}
定義isoperator函式,如果字元為+,-,*,/,(,),=,運算子,則返回1,否則返回0,。
2.比較運算子的優先順序:
注:在計算表示式時,為了方便判斷增設「=」為表示式定界符,即以=表示開始,=表示結束
int pri(char oper1,char oper2) //判斷兩個運算子的優先順序
//如果oper1>oper2返回1 如果oper1oper2
break;
case '*':
case '/':
if(oper1=='*'||oper1=='/'||oper1==')')
pri=1; //oper1>oper2
else
pri=-1; //oper1oper2
break;
} return pri;
}
在該函式中對oper1和oper2兩個運算子比較,34到40行表示:oper2為+或-號,
若oper1為(或=號,
oper1oper2,pri=1。41到47行同理。48到55行表示:oper2等於(時,若oper1等於),即)(,這樣右括號後直接左括號是不對的,oper2等於(,
若oper1不為),則oper1oper2,pri=1。 最後返回pri。
3.對於優先順序高的運算子,需要將運算子兩側的資料進行計算,
int calc(int a,int oper,int b) //計算兩個運算元的結果
} }
當為除數時,注意考慮除數不能為0,
4.寫好以上函式部分,就可以開始計算表示式的值:
int calcexp(char exp) //表示式計算函式
switch(pri(x,c)) //判斷運算子優先順序
}else if(c>='0'&&c<='9') //如果輸出的字元在0到9之間
else
x=seqstackpeek(stackoper); //獲取棧頂操作符
} q=seqstackpop(stackdata);
seqstackfree(stackoper);
seqstackfree(stackdata); //釋放記憶體占用空間
return q; //出棧,返回結果
}
該部分註解:
首先是以乙個字串exp為引數,返回乙個整型數(即表示式的結果),乙個標誌變數flag,作用是處理當運算元是多位數時處理多位數的情況(**一次只能從表示式中獲取乙個字元),當運算元是多位數就把每一位獲取後再入棧。flag為0表示沒有運算元入棧,為1表示有運算元需要入棧。
然後將變數x為「=」,將該符號作為表示式的第乙個運算子入棧,然後迴圈諸葛處理表示式字串中的每乙個字元,直到遇到表示式的結束字元「=」為止。
5.主函式
int main()
最後編譯結果:
算術表示式求值(C語言棧)
題目描述 表示式計算是實現程式語言的基本問題之一,也是棧的應用的乙個典型例子。設計乙個程式,演示用運算子優先法對算數表示式求值的過程。基本要求 以字串行的形式從終端輸入語法正確的 不含變數的整數表示式。利用教科書表3.1給出的運算子優先關係,實現對算數四則混合運算表示式的求值,並仿照教科書的例3.1...
順序棧實現表示式求值(C語言實現) 棧
表示式求值一定會出現表示式中運算子的優先順序問題。運算規則 先乘除,後加減 從左算到右 先括號內,後括號外 運算子優先表 上面 中有一些比較特殊的位置 相等 左括號遇到右括號相等說明左右括號匹配。和 遇到的時候也是 我們在表示式的左邊人為的加上乙個 在表示式掃瞄完成之後再加上乙個 表示表示式掃瞄完了...
c語言算術表示式
c語言基本算數運算子如下表 加法運算子 雙目運算子,即應有兩個量參與加法運算。如a b,4 8等。具有右結合性。減法運算子 雙目運算子。但 也可作負值運算子,此時為單目運算,如 x,5等具有左結合性。乘法運算子 雙目運算子,具有左結合性。除法運算子 雙目運算子,具有左結合性。參與運算量均為整型時,結...