Prezentacja multimedialna
Zapoznaj się z prezentacją przedstawiającą użycie stosu zaimplementowanego za pomocą listy jednokierunkowej niecyklicznej w realizacji algorytmu konwersji zapisu infiksowego na odwrotną notację polskąD8zD8PhYJodwrotną notację polską. Algorytm zapisany w pseudokodzie znajdziesz w e‑materiale Dynamiczne struktury danychDINsybcX5Dynamiczne struktury danych.
Specyfikacja problemu:
Dane:
wyrazenie– łańcuch znaków; zapis infiksowy wyrażenia arytmetycznego, w którym znak spacji występuje przed i po każdym operatorze
Wynik:
wyrażenie infiksowe wypisane w odwrotnej notacji polskiej
Na podstawie informacji z sekcji „Przeczytaj” oraz powyższej prezentacji napisz i uruchom program konwertujący podane wyrażenie infiksowe na postfiksowe. W implementacji do zdefiniowania węzłów listy użyj klasy Wezel zamiast struktury. W metodzie czyOperator() wykorzystaj metodę find() obiektu string.
Specyfikacja problemu:
Dane:
wyrazenie– łańcuch znaków; zapis infiksowy wyrażenia arytmetycznego, w którym znak spacji występuje przed i po każdym operatorze
Wynik:
wyrażenie infiksowe wypisane w odwrotnej notacji polskiej.
Działanie programu przetestuj dla następującego wyrażenia: (31 + 4) * 7.
Przykładowy wynik działania programu:
Wyrażenie infiksowe: 7 * (15 - 5)
Wyrażenie postfiksowe: 7 15 5 - *Kod klasy definiującej węzeł znajdziesz w sekcji „Przeczytaj”. Pamiętaj również o zmodyfikowaniu kodu tworzącego nowy węzeł w metodzie odloz().
#include <iostream>
#include <string>
using namespace std;
class Wezel {
public:
string znak;
Wezel *nastepny;
Wezel(): znak(""), nastepny(nullptr) {}
Wezel(string znak) {
this->znak = znak;
this->nastepny = nullptr;
}
};
class Stos {
Wezel* wierzcholek;
public:
Stos(): wierzcholek(nullptr) {}
bool czyPusty();
string pobierzW();
void odloz(string);
string zdejmij();
void wypisz();
};
bool Stos::czyPusty() {
return !wierzcholek;
}
string Stos::pobierzW() {
if (czyPusty()) return "";
return wierzcholek->znak;
}
void Stos::odloz(string znak) {
Wezel* nowy = new Wezel(znak);
nowy->nastepny = wierzcholek;
wierzcholek = nowy;
}
string Stos::zdejmij() {
if (czyPusty()) return "";
Wezel* pomocniczy = wierzcholek;
string znak = pomocniczy->znak;
wierzcholek = wierzcholek->nastepny;
delete(pomocniczy);
return znak;
}
void Stos::wypisz() {
if (czyPusty()) return;
Wezel* pomocniczy = wierzcholek;
while (pomocniczy != nullptr) {
pomocniczy = pomocniczy->nastepny;
}
}
bool czyOperator(string znak) {
string operatory = "()+-*/%^";
if (operatory.find(znak) != string::npos) {
return true;
}
return false;
}
int priorytet(string znak) {
if (znak == "(") return 0;
else if (znak == "+" || znak == "-") return 1;
else if (znak == "*" || znak == "/" || znak == "%") return 2;
else if (znak == "^") return 3;
return -1;
}
string konwertujDoOnp(string wyrazenie) {
Stos stos = Stos();
string wynik, znak = "";
for (int i=0; i < (int)wyrazenie.length(); i++) {
znak = wyrazenie[i];
if (znak == " " || !czyOperator(znak)) {
wynik += znak;
} else if (znak == "(") {
stos.odloz(znak);
} else if (znak == ")") {
while (stos.pobierzW() != "(")
wynik += " " + stos.zdejmij();
stos.zdejmij();
} else {
while (!stos.czyPusty() &&
(priorytet(stos.pobierzW()) >= priorytet(znak)))
wynik += stos.zdejmij();
stos.odloz(znak);
}
stos.wypisz();
}
while (!stos.czyPusty())
wynik += " " + stos.zdejmij();
return wynik;
}
int main(int argc, char *argv[]) {
string wyrazenie = "(31 + 4) * 7";
cout << "Wyrażenie infiksowe: " << wyrazenie << endl;
string wynik = konwertujDoOnp(wyrazenie);
cout << "Wyrażenie postfiksowe: " << wynik << endl;
return 0;
}Zapoznaj się z prezentacją przedstawiającą użycie jednokierunkowej listy cyklicznej w symulacji problemu Flawiusza. Algorytm zapisany w pseudokodzie znajdziesz w e‑materiale Dynamiczne struktury danychDINsybcX5Dynamiczne struktury danych.
Specyfikacja problemu:
Dane:
n– liczba naturalna; liczba elementów kręguk– liczba naturalna; liczba oznaczająca pierwszy eliminowany element oraz liczbę przejść do następnego eliminowanego elementu
Wynik:
wypisany numer elementu, który pozostał w kręgu
Przyjmijmy, że do symulacji problemu Flawiusza używamy dwukierunkowej listy cyklicznej o znanym rozmiarze n. Zaimplementuj metody dodaj(), usun() oraz wypisz() uwzględniające dwukierunkowość listy. Po uruchomieniu program powinien wypisywać zawartość listy przed każdym usunięciem węzła, a na końcu pozycję węzła, który pozostał na liście.
Specyfikacja problemu:
Dane:
n– liczba naturalna; rozmiar listy cyklicznejk– liczba naturalna; liczba oznaczająca pierwszy eliminowany element oraz liczbę przejść do następnego eliminowanego elementu
Wynik:
zawartość listy przed każdym usunięciem węzła oraz pozycja węzła, który pozostał na liście
Działanie programu przetestuj dla n = 8 i k = 3.
Przykładowy wynik działania programu:
1 2 3 4 5 6 7 8
1 2 4 5 6 7 8
1 2 4 5 7 8
2 4 5 7 8
2 4 7 8
4 7 8
4 7
7#include <iostream>
using namespace std;
typedef struct Wezel {
int pozycja;
Wezel *nastepny;
Wezel *poprzedni;
Wezel(int pozycja) {
this->pozycja = pozycja;
this->nastepny = nullptr;
this->poprzedni = nullptr;
}
} Wezel;
class Lista {
Wezel *glowa;
public:
Lista() { glowa = nullptr; }
void dodaj(int pozycja);
void usun(Wezel*);
Wezel* przejdz(int, Wezel*);
void wypisz(int);
};
Wezel* Lista::przejdz(int o_ile, Wezel* wezel) {
Wezel* pomocniczy = wezel;
if (wezel == nullptr) {
pomocniczy = glowa;
}
for (int i=0; i < o_ile; i++) {
pomocniczy = pomocniczy->nastepny;
}
delete(wezel);
return pomocniczy;
}
void Lista::dodaj(int pozycja) {
Wezel* nowy = new Wezel(pozycja);
if (glowa == nullptr) {
glowa = nowy;
glowa->nastepny = glowa;
glowa->poprzedni = glowa;
return;
}
Wezel* ostatni = glowa->poprzedni;
nowy->nastepny = glowa;
nowy->poprzedni = ostatni;
glowa->poprzedni = nowy;
ostatni->nastepny = nowy;
}
void Lista::usun(Wezel* wezel) {
wezel->nastepny->poprzedni = wezel->poprzedni;
wezel->poprzedni->nastepny = wezel->nastepny;
if (wezel == glowa) {
if (glowa->nastepny != glowa) {
glowa = glowa->nastepny;
} else {
glowa = nullptr;
}
}
}
void Lista::wypisz(int n) {
Wezel* pomocniczy = glowa;
while (n--) {
cout << pomocniczy->pozycja << " ";
pomocniczy = pomocniczy->nastepny;
}
cout << endl;
}
int main(int argc, char *argv[]) {
int n = 8;
int k = 3;
Lista lista;
for (int i=1; i<n+1; i++) {
lista.dodaj(i);
}
Wezel* wezel = lista.przejdz(k - 1, nullptr);
while (wezel->nastepny != wezel) {
lista.wypisz(n--);
lista.usun(wezel);
wezel = lista.przejdz(k, wezel);
}
cout << wezel->pozycja << endl;
return 0;
}Zapoznaj się z prezentacją przedstawiającą użycie niecyklicznej listy dwukierunkowej w algorytmie leksykograficznego sortowania wyrazów. Algorytm zapisany w pseudokodzie znajdziesz w e‑materiale Dynamiczne struktury danychDINsybcX5Dynamiczne struktury danych.
Specyfikacja problemu:
Dane:
wyrazy– tablica lub lista zawierająca ciągi znaków – wyrazy do uporządkowania
Wynik:
wypisane w porządku leksykograficznym wyrazy
Metoda wstaw() zaimplementowana w prezentacji dotyczącej sortowania leksykograficznego wykonuje w pętli while jedno porównanie, które wcześniej wykonywane jest w metodzie sortuj().
Zaimplementuj taką wersję tej metody, która nie wykona zbędnego porównania.
Specyfikacja problemu:
Dane:
wyrazy– tablica lub lista zawierająca ciągi znaków – wyrazy do uporządkowania
Wynik:
wyrazy wypisane przed posortowaniem i po sortowaniu w porządku leksykograficznym
Działanie programu przetestuj dla wyrazów: "dynamiczne", "Struktury", "danych", "cpp".
Przykładowy wynik działania programu:
dynamiczne Struktury danych cpp
cpp danych dynamiczne StrukturyZastanów się nad kolejnością sprawdzania warunków w pętli while, a następnie nad kolejnością sprawdzania warunku zakończenia pętli.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
typedef struct Wezel {
string wyraz;
Wezel *nastepny;
Wezel *poprzedni;
Wezel(string wyraz) {
this->wyraz = wyraz;
this->nastepny = nullptr;
this->poprzedni = nullptr;
}
} Wezel;
class Lista {
Wezel* glowa;
Wezel* ogon;
public:
Lista(): glowa(nullptr), ogon(nullptr) {}
void dodaj(string);
void usun(Wezel*);
int porownaj(Wezel*, Wezel*);
void wstaw(Wezel*);
void sortuj();
void wypisz();
};
void Lista::dodaj(string wyraz) {
Wezel* nowy = new Wezel(wyraz);
if (glowa == nullptr) {
glowa = ogon = nowy;
} else {
ogon->nastepny = nowy;
nowy->poprzedni = ogon;
ogon = nowy;
}
}
void Lista::usun(Wezel* wezel) {
if (wezel == glowa && glowa->nastepny != nullptr) {
glowa = glowa->nastepny;
glowa->poprzedni = nullptr;
return;
}
if (wezel == ogon) {
wezel->poprzedni->nastepny = nullptr;
ogon = wezel->poprzedni;
} else {
wezel->poprzedni->nastepny = wezel->nastepny;
wezel->nastepny->poprzedni = wezel->poprzedni;
}
}
int Lista::porownaj(Wezel* wezel_1, Wezel* wezel_2) {
string wyraz_1 = wezel_1->wyraz;
string wyraz_2 = wezel_2->wyraz;
transform(wyraz_1.begin(), wyraz_1.end(), wyraz_1.begin(),
[](unsigned char c){ return tolower(c); });
transform(wyraz_2.begin(), wyraz_2.end(), wyraz_2.begin(),
[](unsigned char c){ return tolower(c); });
return wyraz_1.compare(wyraz_2);
}
void Lista::sortuj() {
Wezel* pomocniczy = glowa;
while (true) {
if (pomocniczy->nastepny == nullptr)
break;
if (porownaj(pomocniczy, pomocniczy->nastepny) > 0) {
usun(pomocniczy);
wstaw(pomocniczy);
pomocniczy = glowa;
} else {
pomocniczy = pomocniczy->nastepny;
}
}
}
void Lista::wstaw(Wezel* wezel) {
Wezel* pomocniczy = wezel->nastepny;
while (pomocniczy != ogon && porownaj(wezel, pomocniczy->nastepny) >= 0) {
pomocniczy = pomocniczy->nastepny;
}
if (pomocniczy == ogon) {
wezel->nastepny = nullptr;
wezel->poprzedni = ogon;
ogon->nastepny = wezel;
ogon = wezel;
} else {
wezel->poprzedni = pomocniczy;
wezel->nastepny = pomocniczy->nastepny;
pomocniczy->nastepny->poprzedni = wezel;
pomocniczy->nastepny = wezel;
}
}
void Lista::wypisz() {
Wezel* pomocniczy = glowa;
while (pomocniczy != nullptr) {
cout << pomocniczy->wyraz << " ";
pomocniczy = pomocniczy->nastepny;
}
cout << endl;
}
int main(int argc, char *argv[]) {
string dane[] = {"dynamiczne", "Struktury", "danych", "cpp"};
int n = sizeof(dane)/sizeof(dane)[0];
Lista lista;
for(int i = 0; i < n; i++) {
lista.dodaj(dane[i]);
}
lista.wypisz();
lista.sortuj();
lista.wypisz();
return 0;
}