01.
// metoda sprawdza poprawność nawiasów w wyrażeniu infiksowym
02.
private
boolean
czyPoprawneNawiasy() {
03.
// tworzymy stos
04.
Stack<String> stos =
new
Stack<String>();
05.
06.
// dzielimy wyrażenie infiksowe na części na podstawie separatorów
07.
StringTokenizer st =
new
StringTokenizer(wyrazenieInfiksowe,
"()"
,
true
);
08.
09.
// dopóki są elementy w wyrażeniu wejściowym
10.
while
(st.hasMoreTokens()) {
11.
// pobieramy element
12.
String s = st.nextToken();
13.
14.
// jeżeli znak jest nawiasem otwierającym odkładamy go na stos
15.
if
(s.equals(
"("
)) stos.push(s);
16.
// jeżeli znak jest nawiasem zamykającym porównujemy go z wartością ze stosu
17.
if
(s.equals(
")"
)) {
18.
if
(stos.isEmpty())
return
false
;
19.
if
(!stos.pop().equals(
"("
))
return
false
;
20.
}
21.
}
22.
// zwracamy true albo false (stos pusty - wszystkie nawiasy są poprawne)
23.
return
stos.isEmpty();
24.
}
- Inicjalizujemy stos,
- Analizujemy wyrażenie postfiksowe od lewej do prawej strony,
- Jeżeli element jest argumentem to odkładamy go na stos,
- Jeżeli element jest operatorem to ściągamy ze stosu dwie wartości, wykonujemy działanie, odkładamy na stos wynik,
- Jeżeli dotarliśmy do końca wyrażenie postfiksowego, ściągamy wartość ze stosu (jest to obliczona wartość wyrażenia postfiksowego).
Wyrażenie infiksowe: (4*2)+(15/3) Wyrażenie postfiksowe: 4 2 * 15 3 / + kolejny znak stos operacja 4 4 odkładamy na stos 2 4 2 odkładamy na stos * 8 ściągamy ze stosu dwie wartości i obliczamy wartość wyrażenia(4*2), odkładamy ją na stos 15 8 15 odkładamy na stos 3 8 15 3 odkładamy na stos / 8 5 ściągamy ze stosu dwie wartości i obliczamy wartość wyrażenia(15/3), odkładamy ją na stos + 13 ściągamy ze stosu dwie wartości i obliczamy wartość wyrażenia(8+5), odkładamy ją na stos ściągamy ze stosu wynik końcowy (13) Obliczona wartość wyrażenia postfiksowego: 13Poniżej metoda obliczająca wartość wyrażenia postfiksowego. Operujemy na wartościach typu double.
01.
// metoda oblicza wartość wyrażenia postfiksowego
02.
private
double
oblicz() {
03.
04.
// tworzymy pusty stos
05.
Stack<Double> stos =
new
Stack<Double>();
06.
07.
// dzielimy wyrażenie postfiksowe na elementy na podstawie spacji
08.
StringTokenizer st =
new
StringTokenizer(wyrazeniePostfiksowe,
" "
);
09.
10.
// dopóki są elementy w wyrażeniu wejściowym
11.
while
(st.hasMoreTokens()) {
12.
// pobieramy element
13.
String s = st.nextToken();
14.
15.
// jeśli element nie jest operatorem (czyli jest wartością)
16.
if
(!s.equals(
"+"
) && !s.equals(
"*"
) && !s.equals(
"-"
) && !s.equals(
"/"
)) {
17.
// zamieniamy łańcuch na liczbę
18.
double
wartosc = Double.parseDouble(s);
19.
// odkładamy wartość na stos
20.
stos.push(wartosc);
21.
}
22.
else
{
23.
// jeśli element jest operatorem ściągamy dwie wartości ze stosu
24.
double
wartosc1 = stos.pop();
25.
double
wartosc2 = stos.pop();
26.
// w zależności od operatora obliczamy wynik i odkładamy go na stos
27.
switch
(s.charAt(
0
)) {
28.
case
'*'
: {stos.push(wartosc2 * wartosc1);
break
;}
29.
case
'+'
: {stos.push(wartosc2 + wartosc1);
break
;}
30.
case
'-'
: {stos.push(wartosc2 - wartosc1);
break
;}
31.
case
'/'
: {stos.push(wartosc2 / wartosc1);
break
;}
32.
}
33.
}
34.
}
35.
// zwracamy końcowy wynik
36.
return
stos.pop();
37.
}
001.
// wykorzystujemy klasy Scanner, Stack<E> oraz StringTokenizer z pakietu java.util
002.
import
java.util.*;
003.
/**
004.
* Odwrotna Notacja Polska
005.
* Zamiana wyrażeń infiksowych na postfiksowe
006.
* @author kodatnik.blogspot.com
007.
*/
008.
public
class
OdwrotnaNotacjaPolska {
009.
// pola klasy
010.
private
String wyrazenieInfiksowe;
011.
private
String wyrazeniePostfiksowe;
012.
private
double
wynik;
013.
014.
// konstruktor dokonuje przypisania polom wyrażeń
015.
public
OdwrotnaNotacjaPolska(String wyrazenie) {
016.
this
.wyrazenieInfiksowe = wyrazenie;
017.
wyrazeniePostfiksowe =
""
;
018.
wynik =
0.0
;
019.
if
(!czyPoprawneNawiasy())
020.
wyrazeniePostfiksowe =
"Niepoprawne nawiasy w wyrażeniu infiksowym"
;
021.
else
{
022.
// wywołujemy metodę dokonującą konwersji
023.
infiksNaPostfiks();
024.
wynik = oblicz();
025.
}
026.
}
027.
028.
// metoda zwraca wyrażenie w formie infiksowej
029.
public
String pobierzWyrazenieInfiksowe() {
030.
return
wyrazenieInfiksowe;
031.
}
032.
033.
// metoda zwraca wyrażenie w formie postfiksowej
034.
public
String pobierzWyrazeniePostfiksowe() {
035.
return
wyrazeniePostfiksowe;
036.
}
037.
038.
// metoda zwraca obliczoną wartość wyrażenia postfiksowego
039.
public
double
pobierzWynik() {
040.
return
wynik;
041.
}
042.
043.
// metoda sprawdza poprawność nawiasów w wyrażeniu infiksowym
044.
private
boolean
czyPoprawneNawiasy() {
045.
// tworzymy stos
046.
Stack<String> stos =
new
Stack<String>();
047.
048.
// dzielimy wyrażenie infiksowe na części na podstawie separatorów
049.
StringTokenizer st =
new
StringTokenizer(wyrazenieInfiksowe,
"()"
,
true
);
050.
051.
// dopóki są elementy w wyrażeniu wejściowym
052.
while
(st.hasMoreTokens()) {
053.
// pobieramy element
054.
String s = st.nextToken();
055.
056.
// jeżeli znak jest nawiasem otwierającym odkładamy go na stos
057.
if
(s.equals(
"("
)) stos.push(s);
058.
// jeżeli znak jest nawiasem zamykającym porównujemy go z wartością ze stosu
059.
if
(s.equals(
")"
)) {
060.
if
(stos.isEmpty())
return
false
;
061.
if
(!stos.pop().equals(
"("
))
return
false
;
062.
}
063.
}
064.
// zwracamy true albo false (stos pusty - wszystkie nawiasy są poprawne)
065.
return
stos.isEmpty();
066.
}
067.
068.
// metoda konwertuje wyrażenie w postaci infiksowej na postfiksową
069.
// wynik operacji jest zapisywany w polu wyrazeniePostfiksowe
070.
private
void
infiksNaPostfiks() {
071.
072.
// tworzymy pusty stos
073.
Stack<String> stos =
new
Stack<String>();
074.
075.
// dzielimy wyrażenie infiksowe na części na podstawie separatorów
076.
StringTokenizer st =
new
StringTokenizer(wyrazenieInfiksowe,
"+-*/()"
,
true
);
077.
078.
// dopóki są elementy w wyrażeniu wejściowym
079.
while
(st.hasMoreTokens()) {
080.
// pobieramy element
081.
String s = st.nextToken();
082.
083.
// jeżeli element jest operatorem
084.
if
( s.equals(
"+"
) || s.equals(
"*"
) || s.equals(
"-"
) || s.equals(
"/"
)) {
085.
// sprawdzamy priorytety
086.
while
(!stos.empty() && priorytet(stos.peek()) >= priorytet(s))
087.
wyrazeniePostfiksowe += stos.pop() +
" "
;
088.
// odkładamy operator na stos
089.
stos.push(s);
090.
}
091.
// jeżeli element jest nawiasem otwierającym
092.
else
if
(s.equals(
"("
)) stos.push(s);
093.
// jeżeli element jest nawiasem zamykającym
094.
else
if
(s.equals(
")"
)) {
095.
// ściągamy operatory ze stosu, aż do nawiasu otwierajęcego
096.
while
(!stos.peek().equals(
"("
)) wyrazeniePostfiksowe += stos.pop() +
" "
;
097.
// ściągamy nawias otwierający
098.
stos.pop();
099.
}
100.
// jeżeli element nie jest operatorem ani nawiasem dodajemy go do wyrażenia postfiksowego
101.
else
wyrazeniePostfiksowe += s +
" "
;
102.
}
103.
// ściągamy ze stosu pozostałe operatory i dodajemy je do wyrażenia postfiksowego
104.
while
(!stos.empty()) wyrazeniePostfiksowe += stos.pop() +
" "
;
105.
106.
}
107.
108.
// metoda zwraca priorytet operatora
109.
public
static
int
priorytet(String operator) {
110.
// dla '+' i '-' zwracamy 1
111.
if
(operator.equals(
"+"
) || operator.equals(
"-"
))
return
1
;
112.
// dla '*' i '/' zwracamy 2
113.
else
if
(operator.equals(
"*"
) || operator.equals(
"/"
))
return
2
;
114.
// dla pozostałych 0
115.
else
return
0
;
116.
}
117.
118.
// metoda oblicza wartość wyrażenia postfiksowego
119.
private
double
oblicz() {
120.
121.
// tworzymy pusty stos
122.
Stack<Double> stos =
new
Stack<Double>();
123.
124.
// dzielimy wyrażenie postfiksowe na elementy na podstawie spacji
125.
StringTokenizer st =
new
StringTokenizer(wyrazeniePostfiksowe,
" "
);
126.
127.
// dopóki są elementy w wyrażeniu wejściowym
128.
while
(st.hasMoreTokens()) {
129.
130.
// pobieramy element
131.
String s = st.nextToken();
132.
133.
// jeśli element nie jest operatorem (czyli jest wartością)
134.
if
(!s.equals(
"+"
) && !s.equals(
"*"
) && !s.equals(
"-"
) && !s.equals(
"/"
)) {
135.
// zamieniamy łańcuch na liczbę
136.
double
wartosc = Double.parseDouble(s);
137.
// odkładamy wartość na stos
138.
stos.push(wartosc);
139.
}
140.
else
{
141.
// jeśli element jest operatorem ściągamy dwie wartości ze stosu
142.
double
wartosc1 = stos.pop();
143.
double
wartosc2 = stos.pop();
144.
// w zależności od operatora obliczamy wynik i odkładamy go na stos
145.
switch
(s.charAt(
0
)) {
146.
case
'*'
: {stos.push(wartosc2 * wartosc1);
break
;}
147.
case
'+'
: {stos.push(wartosc2 + wartosc1);
break
;}
148.
case
'-'
: {stos.push(wartosc2 - wartosc1);
break
;}
149.
case
'/'
: {stos.push(wartosc2 / wartosc1);
break
;}
150.
}
151.
}
152.
}
153.
// zwracamy końcowy wynik
154.
return
stos.pop();
155.
}
156.
157.
// metoda zwraca nam łańcuch tekstowy z wyrażeniem
158.
// w formie postfiksowej, oraz wynik
159.
public
String toString() {
160.
return
wyrazeniePostfiksowe +
"\nWynik: "
+ wynik;
161.
}
162.
}
01.
public
class
TestONP {
02.
public
static
void
main(String args[]) {
03.
04.
Scanner sc =
new
Scanner(System.in);
05.
System.out.print (
"Podaj wyrażenie infiksowe: "
);
06.
07.
// pobieramy od użytkownika wyrażenie
08.
String wyrazenie = sc.nextLine();
09.
10.
// tworzymy nowy obiekt klasy OdwrotnaNotacjaPolska
11.
// i przekazujemy do konstruktora pobrane od użytkownika wyrażenie
12.
OdwrotnaNotacjaPolska onp =
new
OdwrotnaNotacjaPolska(wyrazenie);
13.
14.
// wyświetlamy wyrażenie w postaci postfiksowej
15.
System.out.println (
"Wyrażenie postfiksowe: "
+ onp);
16.
}
17.
}
Podaj wyrażenie infiksowe: (4*2)+(15/3) Wyrażenie postfiksowe: 4 2 * 15 3 / + Wynik: 13.0
Podaj wyrażenie infiksowe: (3+4)*2) Wyrażenie postfiksowe: Niepoprawne nawiasy w wyrażeniu infiksowym
Podaj wyrażenie infiksowe: ((1+2)-2.5)*8/2 Wyrażenie postfiksowe: 1 2 + 2.5 - 8 * 2 / Wynik: 2.0
Nasza klasa nie obsługuje poprawnie sytuacji wyjątkowych oraz ma małą liczbę operatorów (można się pokusić o dodanie operacji potęgowania, pierwiastkowania czy też funkcji trygonometrycznych).
1 Komentarz - Odwrotna Notacja Polska - część 2
bardzo lubieten blog
Prześlij komentarz
Możesz użyć niektórych tagów HTML, takich jak <b>, <i>, <u>, <a> Nie spamuj :)