<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5790332872166558665</id><updated>2024-11-13T23:51:27.504+01:00</updated><category term="Java"/><category term="Algorytmy"/><category term="Struktury Danych"/><category term="Blogger"/><category term="Podstawy"/><category term="Gadżety"/><category term="Książki"/><category term="Projekt Euler"/><category term="Swing"/><category term="Tutoriale"/><category term="Wątki"/><title type='text'>Kodatnik</title><subtitle type='html'>Kody mniej lub bardziej przydatne...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default?start-index=26&amp;max-results=25'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>55</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-8929202319653922097</id><published>2011-06-07T00:59:00.000+02:00</published><updated>2011-06-07T00:59:47.521+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Podstawy"/><category scheme="http://www.blogger.com/atom/ns#" term="Wątki"/><title type='text'>Wątki w Javie - podstawy</title><content type='html'>Pisząc program dość często zachodzi konieczność wykonywania kilku czynności na raz (np. ściąganie plików, wyświetlanie obrazków, animacja, obsługa użytkownika). W Javie wszystkie te elementy mogą wykonywać się &quot;jednocześnie&quot; poprzez zastosowanie wątków.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Pierwszą czynnością przy tworzeniu wątków jest  stworzenie obiektu klasy implementującej interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Runnable&lt;/span&gt;, interfejs ten ma tylko jedną metodę &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;run()&lt;/span&gt;, w której zamieścimy kod naszego wątku.&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter: false;&quot;&gt;public interface Runnable {
 void run();
}
&lt;/pre&gt;Szkielet klasy implementującej interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Runnable&lt;/span&gt;:&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter: false;&quot;&gt;class Watek implements Runnable {
 void run() {
  // kod, który ma zostać wywołany przez wątek
 }
}
&lt;/pre&gt;Samo utworzenie w pełni sprawnego wątku to stworzenie obiektu klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Thread&lt;/span&gt; z przekazaną do jej konstruktora referencją obiektu klasy implementującej interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Runnable&lt;/span&gt;.&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter: false;&quot;&gt;Runnable obiekt = new Watek();
Thread pierwszyWatek = new Thread(obiekt);
&lt;/pre&gt;Tak utworzony obiekt jest już pełnokrwistym wątkiem. Możemy go uruchomić za pomocą metody &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;start()&lt;/span&gt; (wywołane zostanie ciało metody &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;run()&lt;/span&gt;).&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter: false;&quot;&gt;pierwszyWatek.start();
&lt;/pre&gt;Spróbujmy wykorzystać naszą wiedzę do napisania prostej aplikacji, której zadaniem będzie wyświetlanie na ekranie za pomocą wątków różnych napisów. Każdy napis to osobny wątek. Ciało metody &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;run()&lt;/span&gt; to pętla &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;for&lt;/span&gt;, która co określoną liczbę milisekund wyświetli odpowiedni napis. Wartość opóźnienia w wyświetlaniu będzie losowana z zakresu od 0 do 2000 milisekund (pomiędzy 0 a 2 sekundami). Do losowania liczb wykorzystamy metodę &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;rand()&lt;/span&gt; z klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Math&lt;/span&gt;, a do zatrzymania wątku na określony czas metodę &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;sleep()&lt;/span&gt; dostepną w klasie &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Thread&lt;/span&gt;. Pętla wykona się 10 razy po czym zakończy swoje zadanie, co za tym idzie wątek również zostanie zakończony (koniec metody &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;run()&lt;/span&gt;). &lt;br /&gt;
&lt;pre class=&quot;brush: java;&quot;&gt;/**
 * Wykorzystanie wątków
 * @author kodatnik.blogspot.com
 */

// klasa implementująca interfejs Runnable
class Napis implements Runnable {
 // pole napis przechowujące łańcuch tekstowy
 private String napis;

 // konstruktor klasy
 public Napis(String napis) {
  this.napis = napis;
 }

 // zaimplementowana metoda run
 public void run() {
  // pętla dziesięciokrotna
  for (int i = 0; i &amp;lt; 10; i++) {
   // wyświetlamy napis
   System.out.println(napis);
   try {
    // usypiamy wątek na losową liczbę milisekund (od 0 do 2000)
    Thread.sleep((int)(Math.random()*2000));
   } catch(InterruptedException e){}
   }
  }
}

// klasa tworząca i uruchamiająca wątki
public class Watki {
 public static void main(String [] args) {
  // rozpoczynamy działanie metody main()
  System.out.println(&quot;Tworzenie wątków w Javie.&quot;);
  
  // tworzymy trzy obiekty klasy napis z różnymi łańcuchami tekstowymi
  Napis napisPierwszy = new Napis(&quot;Kodatnik&quot;);
  Napis napisDrugi = new Napis(&quot;Java&quot;);
  Napis napisTrzeci = new Napis(&quot;Wątek&quot;);

  // tworzymy trzy wątki
  Thread watekPierwszy = new Thread(napisPierwszy);
  Thread watekDrugi = new Thread(napisDrugi);
  Thread watekTrzeci = new Thread(napisTrzeci);

  // uruchamiamy wątki
  watekPierwszy.start();
  watekDrugi.start();
  watekTrzeci.start();
  
  // kończymy działanie metody main() wyświetlając komunikat
  System.out.println(&quot;Metoda main(), główny wątek aplikacji, zakończyła swoje działanie.&quot;);
 }
}
&lt;/pre&gt;Poniżej wynik działania aplikacji (za każdym razem będzie on inny). Zauważ, że metoda &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;main()&lt;/span&gt; zakończyła swoje działanie od razu. &lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Tworzenie wątków w Javie.
Metoda main(), główny wątek aplikacji, zakończyła swoje działanie.
Kodatnik
Java
Wątek
Kodatnik
Wątek
Java
Wątek
Kodatnik
Java
Kodatnik
Java
Wątek
Kodatnik
Java
Wątek
Java
Kodatnik
Wątek
Java
Wątek
Kodatnik
Wątek
Java
Wątek
Java
Kodatnik
Kodatnik
Java
Wątek
Kodatnik
Java
Wątek
Wątek
Java
Kodatnik
Wątek
Kodatnik
Java
Kodatnik
Wątek
Java
Kodatnik
Kodatnik
Wątek
Wątek
Java
Kodatnik
Kodatnik
Kodatnik
Java
Wątek
Kodatnik
Wątek
Java
Kodatnik
Wątek
Java
Wątek
Java
Java
&lt;/pre&gt;Możemy dodać nowe wątki z innymi napisami i sprawdzić działanie programu. Inny przykład wykorzystania wątków zaprezentowałem w poście &lt;a href=&quot;http://kodatnik.blogspot.com/2011/06/zegar-w-swingu.html&quot;&gt;Zegar w Swingu&lt;/a&gt;. W kolejnym postach zastanowimy się jak zatrzymywać wątki i jak je synchronizować. &lt;br /&gt;
&lt;div class=&quot;tip&quot;&gt;Innym sposobem tworzenia wątków jest rozszerzenie możliwości klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Thread&lt;/span&gt;. Przesłaniamy metodę &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;run()&lt;/span&gt; i wątek gotowy. Ten sposób ma jednak kilka wad, jeśli nasza klasa będzie dziedziczyć z innej klasy to nie może już rozszerzać możliwości klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Thread&lt;/span&gt; (dziedziczenie w Javie jest jednokrotne). Rozwiązanie z interfejsem nie narzuca nam takich ograniczeń. &lt;/div&gt;&lt;div class=&quot;tip&quot;&gt;Pisząc dowolny program w Javie korzystamy, nawet nie wiedząc o tym, z wątków. Każda aplikacja jest uruchamiana w Wirtualnej Maszynie Javy jako osobny wątek. Możliwe zatem jest jest wstrzymanie za pomocą metody &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Thread.sleep()&lt;/span&gt;. &lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/8929202319653922097/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2011/06/watki-w-javie-podstawy.html#comment-form' title='Komentarze (9)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8929202319653922097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8929202319653922097'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2011/06/watki-w-javie-podstawy.html' title='Wątki w Javie - podstawy'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-9077011185548982620</id><published>2011-06-06T02:24:00.001+02:00</published><updated>2011-06-07T00:49:49.034+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Książki"/><category scheme="http://www.blogger.com/atom/ns#" term="Tutoriale"/><title type='text'>Java - darmowe książki i tutoriale</title><content type='html'>W sieci dostępnych jest kilka darmowych pozycji książkowych dla chcących nauczyć się podstaw programowania w języku Java. Znajdziemy zarówno całe książki jak i przykładowe rozdziały (po polsku i po angielsku). Dobrze jest również znać strony z sensownymi tutorialami.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFwOaXpBMslogwGs1iadGIJE-NQc7rPQaisWdjUn6jgMlNsWR9bN9U0AqWiGCwEEbxhtUAt_DrMFg1T2k37hZRg4Yh_s9A5D9_-lb1e42a0Z_FE1j_i6PAnKW6VqNpggKRRkyGmBeuoSUm/s1600/thinkinginjava.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFwOaXpBMslogwGs1iadGIJE-NQc7rPQaisWdjUn6jgMlNsWR9bN9U0AqWiGCwEEbxhtUAt_DrMFg1T2k37hZRg4Yh_s9A5D9_-lb1e42a0Z_FE1j_i6PAnKW6VqNpggKRRkyGmBeuoSUm/s320/thinkinginjava.jpg&quot; width=&quot;242&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Zacznijmy od książek. &lt;b&gt;Thinking in Java&lt;/b&gt; to to najbardziej znana i popularna książka dotycząca podstaw jak i zaawansowanych możliwości Javy. W wersji angielskiej jest ona dostępna za darmo na stronie autora: &lt;a href=&quot;http://www.mindview.net/Books/TIJ/&quot;&gt;http://www.mindview.net/Books/TIJ/&lt;/a&gt;. Wersja polska niestety nie jest darmowa.&lt;br /&gt;
&lt;br /&gt;
Kolejna pozycja w języku angielskim to dość spore opracowanie &lt;b&gt;How to Think Like a Computer Scientist&lt;/b&gt; dostępne w formie PDF&#39;a pod adresem: &lt;a href=&quot;http://www.greenteapress.com/thinkapjava/thinkapjava.pdf&quot;&gt;http://www.greenteapress.com/thinkapjava/thinkapjava.pdf&lt;/a&gt;. Książka zawiera wprowadzenie do Javy oraz kilka rozdziałów poświęconych algorytmom i strukturom danych. Bardzo ciekawą pozycją jest również &lt;b&gt;Introduction to Programming&lt;/b&gt; &lt;b&gt;in Java&lt;/b&gt; Roberta Sedgewicka i Kevina Wayne&#39;a. Znajdziemy w niej interesujące przykłady jak i nieszablonowe podejście do wielu aspektów programowania (język angielski). Całość dostępna tutaj: &lt;a href=&quot;http://introcs.cs.princeton.edu/java/home/&quot;&gt;http://introcs.cs.princeton.edu/java/home/&lt;/a&gt;. Inną polecaną książkę o tytule&lt;b&gt; Introduction to Programming Using Java&lt;/b&gt; znajdziecie pod adresem: &lt;a href=&quot;http://math.hws.edu/javanotes/&quot;&gt;http://math.hws.edu/javanotes/&lt;/a&gt;. Poza wstępem do programowania autor opisuje zaawansowane struktury danych, strumienie wejścia/wyjścia jak i programowanie z wykorzystaniem graficznego interfejsu użytkownika. Pozostałe pozycje w języku angielskim to:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Data Structures and Algorithms with Object-Oriented Design Patterns in Java&lt;/b&gt; - &lt;a href=&quot;http://www.brpreiss.com/books/opus5/html/book.html&quot;&gt;http://www.brpreiss.com/books/opus5/html/book.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Sams Teach Yourself Java 2 in 24 Hours&lt;/b&gt; - &lt;a href=&quot;http://www.informit.com/library/library.aspx?b=STY_Java2_24hours&quot;&gt;http://www.informit.com/library/library.aspx?b=STY_Java2_24hours&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Tutorial&lt;/b&gt; ze strona Sun&#39;a (teraz już Oracla) - &lt;a href=&quot;http://download.oracle.com/javase/tutorial/&quot;&gt;http://download.oracle.com/javase/tutorial/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;1000 Java Tips&lt;/b&gt; zbiór pytań i odpowiedzi  - &lt;a href=&quot;http://javaa.com/&quot;&gt;http://javaa.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;A Guide to Modern Programming with Java&lt;/b&gt; - &lt;a href=&quot;http://www.roxie.org/books/bleeding/tableofcontents.html&quot;&gt;http://www.roxie.org/books/bleeding/tableofcontents.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;The Java Language Specification&lt;/b&gt; - &lt;a href=&quot;http://java.sun.com/docs/books/jls/index.html&quot;&gt;http://java.sun.com/docs/books/jls/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Objects and Java&lt;/b&gt; kilka rozdziałów - &lt;a href=&quot;http://www.artima.com/objectsandjava/webuscript/index.html&quot;&gt;http://www.artima.com/objectsandjava/webuscript/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Thinking in Patterns with Java&lt;/b&gt; - &lt;a href=&quot;http://www.mindview.net/Books/TIPatterns/&quot;&gt;http://www.mindview.net/Books/TIPatterns/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Java: Classes in Java Applications - An Introduction to Java Programming&lt;/b&gt; - &lt;a href=&quot;http://bookboon.com/pl/student/it/an-introduction-to-java-programming-2&quot;&gt;http://bookboon.com/pl/student/it/an-introduction-to-java-programming-2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Java: The Fundamentals of Objects and Classes - An Introduction to Java Programming&lt;/b&gt; - &lt;a href=&quot;http://bookboon.com/pl/student/it/an-introduction-of-java-programming&quot;&gt;http://bookboon.com/pl/student/it/an-introduction-of-java-programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Java: Graphical User Interfaces - An Introduction to Java Programming&lt;/b&gt; - &lt;a href=&quot;http://bookboon.com/pl/student/it/an-introduction-to-java-programming-3&quot;&gt;http://bookboon.com/pl/student/it/an-introduction-to-java-programming-3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Object Oriented Programming using Java&lt;/b&gt; - &lt;a href=&quot;http://bookboon.com/pl/student/it/object-oriented-programming-using-java&quot;&gt;http://bookboon.com/pl/student/it/object-oriented-programming-using-java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Introduction to Java&lt;/b&gt; tutorial - &lt;a href=&quot;http://www.meshplex.org/wiki/Java/Introduction_to_Java&quot;&gt;http://www.meshplex.org/wiki/Java/Introduction_to_Java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Po polsku wybór pozycji jest znacznie mniejszy. Większość to bardzo dobre tutoriale wprowadzajace do języka jak i również przybliżające trochę bardziej zaawansowane zagadnienia i tak:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Kurs programowania obiektowego&lt;/b&gt; - &lt;a href=&quot;http://wazniak.mimuw.edu.pl/index.php?title=Programowanie_obiektowe&quot;&gt;http://wazniak.mimuw.edu.pl/index.php?title=Programowanie_obiektowe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Zaawansowane programowanie obiektowe&lt;/b&gt; - &lt;a href=&quot;http://wazniak.mimuw.edu.pl/index.php?title=Zaawansowane_projektowanie_obiektowe&quot;&gt;http://wazniak.mimuw.edu.pl/index.php?title=Zaawansowane_projektowanie_obiektowe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Podstawy Javy&lt;/b&gt; - &lt;a href=&quot;http://4programmers.net/Java/Podstawy_Javy&quot;&gt;http://4programmers.net/Java/Podstawy_Javy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Java - nowy standard programowania w Internecie&lt;/b&gt; - &lt;a href=&quot;http://arturt.republika.pl/java/&quot;&gt;http://arturt.republika.pl/java/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Kurs Javy&lt;/b&gt;, podstawy - &lt;a href=&quot;http://javaprogramming.awardspace.com/index.php?pokaz=kurs&quot;&gt;http://javaprogramming.awardspace.com/index.php?pokaz=kurs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Możemy również poczytać rozdziały książek dostępnych w księgarniach internetowych np.:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Obsługa zdarzeń&lt;/b&gt; z książki &lt;i&gt;Java - Podstawy&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/javpd3/javpd3-8.pdf&quot;&gt;http://pdf.helion.pl/javpd3/javpd3-8.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Aplety&lt;/b&gt; z książki &lt;i&gt;Java - Podstawy&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/jv2pod/jv2pod-10.pdf&quot;&gt;http://pdf.helion.pl/jv2pod/jv2pod-10.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Strumienie i pliki&lt;/b&gt; z książki &lt;i&gt;Java - Techniki zaawansowane&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/javtz8/javtz8-1.pdf&quot;&gt;http://pdf.helion.pl/javtz8/javtz8-1.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Wielowątkowość&lt;/b&gt; z ksiażki &lt;i&gt;Java - Techniki zaawansowane&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/jv2te2/jv2te2-1.pdf&quot;&gt;http://pdf.helion.pl/jv2te2/jv2te2-1.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Wycieczka do Obiektowa&lt;/b&gt; z książki &lt;i&gt;Java Rusz głową!&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/javrg2/javrg2-2.pdf&quot;&gt;http://pdf.helion.pl/javrg2/javrg2-2.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Wyjątki&lt;/b&gt; z książki &lt;i&gt;Java - Efektywne programowanie&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/javep2/javep2-9.pdf&quot;&gt;http://pdf.helion.pl/javep2/javep2-9.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;System wejścia-wyjścia&lt;/b&gt; z książki &lt;i&gt;Praktyczny kurs Java&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/pkjav3/pkjav3.pdf&quot;&gt;http://pdf.helion.pl/pkjav3/pkjav3.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Aplikacje i aplety&lt;/b&gt; z książki &lt;i&gt;Praktyczny kurs Java&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/pkjav2/pkjav2-8.pdf&quot;&gt;http://pdf.helion.pl/pkjav2/pkjav2-8.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Wzorzec fasada&lt;/b&gt; z książki &lt;i&gt;Java - Wzorce projektowe&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/javawz/javawz-13.pdf&quot;&gt;http://pdf.helion.pl/javawz/javawz-13.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Typy danych zmienne i tablice&lt;/b&gt; z książki &lt;i&gt;Java - Kompendium programisty&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/javakp/javakp-3.pdf&quot;&gt;http://pdf.helion.pl/javakp/javakp-3.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Wprowadzenie do Javy&lt;/b&gt; z książki &lt;i&gt;Head First Java&lt;/i&gt; - &lt;a href=&quot;http://pdf.helion.pl/hfjava/hfjava-1.pdf&quot;&gt;http://pdf.helion.pl/hfjava/hfjava-1.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
...i jak zawsze zostaje Kodatnik ;)&lt;br /&gt;
&lt;br /&gt;
Jesli znacie jakieś inne ciekawe kursy, darmowe podręczniki to dajcie znać o nich w komentarzach.</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/9077011185548982620/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2011/06/java-darmowe-ksiazki-i-tutoriale.html#comment-form' title='Komentarze (10)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/9077011185548982620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/9077011185548982620'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2011/06/java-darmowe-ksiazki-i-tutoriale.html' title='Java - darmowe książki i tutoriale'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFwOaXpBMslogwGs1iadGIJE-NQc7rPQaisWdjUn6jgMlNsWR9bN9U0AqWiGCwEEbxhtUAt_DrMFg1T2k37hZRg4Yh_s9A5D9_-lb1e42a0Z_FE1j_i6PAnKW6VqNpggKRRkyGmBeuoSUm/s72-c/thinkinginjava.jpg" height="72" width="72"/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-5596271667449651779</id><published>2011-06-05T02:29:00.000+02:00</published><updated>2011-06-05T02:29:33.566+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Swing"/><title type='text'>Zegar w Swingu</title><content type='html'>Chcemy napisać aplikację wyświetlającą prosty zegar. Wykorzystamy do tego celu interfejs graficzny GUI czyli bibliotekę Swing oraz wątki. Całość ma być na tyle uniwersalna, aby możliwe było wykorzystanie zegara w dowolnej aplikacji.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Do naszych celów wykorzystamy klasę &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;JLabel&lt;/span&gt; (standardowa etykieta tekstowa). Rozszerzymy jej możliwości wyposażając ją w obsługę wątków (zaimplementujemy interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Runnable&lt;/span&gt;). Nowa etykieta będzie co określoną liczbę milisekund zmieniała swoją treść, czyli będzie wyświetlała aktualny czas. Najprostsza wersja nowej klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Zegar&lt;/span&gt; wygląda tak:&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.text.*;

/**
 * Prosty zegar w Swingu
 * @author kodatnik.blogspot.com
 */

// nowa klasa Zegar zbudowana w oparciu o klasę JLabel
class Zegar extends JLabel implements Runnable {
 // wątek
 private Thread watek;
 // liczba milisekund pauzy (1000 ms czyli 1 sekunda)
 private int pauza = 1000;

 // konstruktor klasy
 public Zegar() {
  // wyrównamy napisy do środka
  super(&quot;&quot;, SwingConstants.CENTER);
  // wybieramy font do wyświetlenia zagara (podajemy nazwę, styl oraz rozmiar)
  setFont (new Font (&quot;Consolas&quot;, Font.BOLD, 28));
  // ustalamy kolor tła
  setBackground(Color.BLUE);
  // ustalamy kolor tekstu
  setForeground(Color.WHITE);
  // ustawiamy przeźroczystość
  setOpaque(true);
 }

 // metoda start tworzy i uruchamia wątek zegara
 public void start() {
  // jeśli nie ma działającego wątka, utwórz i uruchom nowy
  if (watek == null) {
   watek = new Thread(this);
   watek.start();
  }
 }

 // metoda wywołana po starcie wątku
 public void run() {
  // dopóki zmienna watek wskazuje na bieżący wątek
  while ( watek == Thread.currentThread()) {
   // nowy obiekt klasy Date
   Date time = new Date();
   // formatowanie
   DateFormat df = DateFormat.getTimeInstance(DateFormat.MEDIUM);
   // ustawiamy tekst
   setText(df.format(time));
   try {
    // wstrzymujemy działanie wątku na 1 sekundę
    watek.sleep(pauza);
   } catch (InterruptedException e) {}
  }
 }

 // metoda zatrzymująca zegar (wątek)
 public void stop() {
  // ustawiamy referencję watek na null
  watek = null;
 }
}
&lt;/pre&gt;Gotowa klasa &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Zegar&lt;/span&gt; może zostać użyta w dowolnej aplikacji. Wystarczy tylko dodać ją do odpowiedniego kontenera. Sprawdźmy zatem jej działanie tworząc prostą aplikację w Swingu.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class PrzykladowyZegar extends JFrame {

 // konstruktor
 public PrzykladowyZegar() {
  // tytuł okna
  super(&quot;Zegar w Swingu&quot;);
  // rozmiar okna
  setSize( 350, 100);
  // ustawienie domyślnej akcji przy zamykaniu okna
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  // ustawiamy widoczność okna
  setVisible(true);
  // nie pozwalamy zmieniać rozmiarów okna
  setResizable(false);

  // tworzymy nowy obiekt klasy Zegar
  Zegar zegar = new Zegar();
  // dodajmy go do naszego okna
  add(zegar);

  // startujemy nasz zegar
  zegar.start();
 }

 public static void main(String [] args) {
  // utworzenie obiektu i wywołanie konstruktora
  new PrzykladowyZegar();
 }
}
&lt;/pre&gt;Całość prezentuje się w następujący sposób:&lt;br /&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqvMd26ORhEXXFuO5JzH-H2r8UYzuQ6BcNAJ_xOVREZdKfuLcKlyp23SNE8Oe78UuBE1W0PuxKAIatWiBDCyCANTn58drc-nWofIr79Db3XE472RGtvKZmooZd-26_Sjx5H5nGL0dgEo0m/s1600/zegar.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;97&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqvMd26ORhEXXFuO5JzH-H2r8UYzuQ6BcNAJ_xOVREZdKfuLcKlyp23SNE8Oe78UuBE1W0PuxKAIatWiBDCyCANTn58drc-nWofIr79Db3XE472RGtvKZmooZd-26_Sjx5H5nGL0dgEo0m/s320/zegar.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class=&quot;tip&quot;&gt;Klasa &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Zegar&lt;/span&gt;, aż prosi się o rozbudowę. Powinniśmy mieć możliwość określenia fontu, kolorów, formatu czy też strefy czasowej podczas tworzenia obiektu. Wystarczy dodać odpowiednie konstruktory i już można będzie wykorzystać kod do tworzenia stoperów czy zegarów wskazujących czas w różnych strefach czasowych.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/5596271667449651779/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2011/06/zegar-w-swingu.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/5596271667449651779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/5596271667449651779'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2011/06/zegar-w-swingu.html' title='Zegar w Swingu'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqvMd26ORhEXXFuO5JzH-H2r8UYzuQ6BcNAJ_xOVREZdKfuLcKlyp23SNE8Oe78UuBE1W0PuxKAIatWiBDCyCANTn58drc-nWofIr79Db3XE472RGtvKZmooZd-26_Sjx5H5nGL0dgEo0m/s72-c/zegar.jpg" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-3710674182594652539</id><published>2011-06-05T01:40:00.000+02:00</published><updated>2011-06-05T01:40:58.518+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blogger"/><title type='text'>Dodajemy przycisk +1 do Bloggera</title><content type='html'>Odpowiedzią Google na Facebookowe&amp;nbsp; &lt;i&gt;&quot;Lubię to&quot;&lt;/i&gt; jest przycisk &lt;i&gt;&quot;+1&quot;&lt;/i&gt;. Możemy obdarzyć plusem strony, które nam się podobają i zwiększyć ich popularność w sieci. Oczywiście musimy być zalogowani na konto w dowolnej usłudze Google. Standardowo Blogger obsługuje nowy przycisk w domyślnych szablonach (wystarczy włączyć odpowiednią opcję). Sytuacja wygląda gorzej jeśli korzystamy z własnych szablonów.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTARldQP38o2a0q6DJypYOEawZnKzHxjY-UtquKaPaCgTxx3f32aojoFoxFf_XbJr6tYCKMfUbYvdE7ROOlACv30B6f4jwRUgYMj3GbL9Abj3-eIuOhkiQx7cor_5MFkGDLIrTgVSoAzlP/s1600/przyciski.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;23&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTARldQP38o2a0q6DJypYOEawZnKzHxjY-UtquKaPaCgTxx3f32aojoFoxFf_XbJr6tYCKMfUbYvdE7ROOlACv30B6f4jwRUgYMj3GbL9Abj3-eIuOhkiQx7cor_5MFkGDLIrTgVSoAzlP/s320/przyciski.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Spróbujmy zatem zaimplementować nowość Google na naszych blogach. Potrzebujemy dwóch wpisów w szablonie bloga. Logujemy się do Bloggera, wybieramy &lt;b&gt;Projekt&lt;/b&gt;/&lt;b&gt;Edytuj kod HTML&lt;/b&gt;. Pierwszy wpis umieszczamy zaraz przez końcem sekcji &lt;b&gt;head&lt;/b&gt;, szukamy (&lt;i&gt;Ctrl+F&lt;/i&gt;) znacznika zamykającego &amp;lt;/head&amp;gt; i powyżej dodajemy:&lt;br /&gt;
&lt;pre class=&quot;brush: xml: gutter: false;&quot;&gt;&amp;lt;script type=&quot;text/javascript&quot; src=&quot;http://apis.google.com/js/plusone.js&quot;&amp;gt;
 {lang: &#39;pl&#39;}
&amp;lt;/script&amp;gt;
&lt;/pre&gt;Parametr &lt;b&gt;lang&lt;/b&gt; umożliwia obsługę danego języka (w naszym przypadku wybraliśmy język polski). Drugi wpis to już umieszczenie kodu samego przycisku w odpowiednim miejscu.&lt;br /&gt;
&lt;pre class=&quot;brush: xml;gutter: false;wrap-lines:true;&quot;&gt;&amp;lt;g:plusone expr:href=&#39;data:post.url&#39; size=&#39;medium&#39;/&amp;gt;
&lt;/pre&gt;Pytanie gdzie dodać ten kod. Możliwości jest kilka. Na moim blogu przycisk pojawia się zaraz przed treścią wpisu (tak samo jak przyciski facebooka i wykopu). Aby to osiągnąć znajdź w kodzie szablonu znajdź linię:&lt;br /&gt;
&lt;pre class=&quot;brush: xml;gutter: false;wrap-lines:true;&quot;&gt;&amp;lt;div class=&#39;post-body entry-content&#39;&amp;gt;
&lt;/pre&gt;i wstaw powyżej tej linii kod przycisku. Jeśli nie chcesz wyświetlać przycisku na stronie głównej, a tylko przy wpisie zastosuj wyrażenie warunkowe:&lt;br /&gt;
&lt;pre class=&quot;brush: xml;gutter: false;wrap-lines:true;&quot;&gt;&amp;lt;b:if cond=&#39;data:blog.pageType != &quot;index&quot;&#39;&amp;gt;
 ...kod przycisku...
&amp;lt;/b:if&amp;gt;
&lt;/pre&gt;Efekt widoczny na moim blogu.&lt;br /&gt;
&lt;div class=&quot;tip&quot;&gt;W kodzie przycisku możesz użyć różnych wartości parametru &lt;b&gt;size&lt;/b&gt;: standard, small, medium i tall. Możesz również zmienić pozycjonowanie przycisku umieszczając go w divie (np. do prawej: &amp;lt;div style=&#39;float:right&#39;&amp;gt;&amp;lt;/div&amp;gt;)&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/3710674182594652539/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2011/06/dodajemy-przycisk-1-do-bloggera.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/3710674182594652539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/3710674182594652539'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2011/06/dodajemy-przycisk-1-do-bloggera.html' title='Dodajemy przycisk +1 do Bloggera'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTARldQP38o2a0q6DJypYOEawZnKzHxjY-UtquKaPaCgTxx3f32aojoFoxFf_XbJr6tYCKMfUbYvdE7ROOlACv30B6f4jwRUgYMj3GbL9Abj3-eIuOhkiQx7cor_5MFkGDLIrTgVSoAzlP/s72-c/przyciski.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-8456346793186926923</id><published>2010-10-22T23:21:00.000+02:00</published><updated>2010-10-22T23:21:09.752+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Gra w życie</title><content type='html'>Gra w życie to przykład automatu komórkowego wymyślonego przez matematyka Johna Conwaya. Gra jest prowadzona w macierzy elementów, komórek. Każda z komórek może być żywa lub martwa. O stanie komórki w kolejnym etapie gry decyduje kilka zasad.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;jeśli komórka jest martwa i ma dokładnie trzech sąsiadów żywych, staje się żywą&lt;/li&gt;
&lt;li&gt;jeśli komórka jest żywa i ma dwóch lub trzech sąsiadów żywych, żyje dalej&lt;/li&gt;
&lt;li&gt;jeśli komórka jest żywa i ma jednego lub mniej sąsiadów lub więcej niż trzech sąsiadów żywych, umiera (odpowiednio z samotności i przeludnienia).&lt;/li&gt;
&lt;/ul&gt;Poniżej prosta implementacja &lt;i&gt;Gry w życie&lt;/i&gt;. Podstawowym założeniem jest wykorzystanie macierzy przechowującej typ logiczny. Komórki żywe to elementy z wartościami &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;true&lt;/span&gt;, a martwe z wartościami &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;false&lt;/span&gt;. Po każdym etapie rozwoju wyświetlana jest plansza z aktualnym stanem naszej populacji komórek. Przejście do następnego etapu to naciśnięcie klawisza &lt;b&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Enter&lt;/span&gt;&lt;/b&gt;, dowolny znak - koniec gry.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.util.Scanner;

/**
 * Prosta implementacja Gry w życie
 * @author kodatnik.blogspot.com
 */
public class GraWZycie {

 // stałe symbolizujące żywą i martwą komórkę
 private final char ZYWA = &#39;#&#39;;
 private final char MARTWA = &#39;.&#39;;
 // pola przechowujące rozmiar naszej planszy
 private int wiersze;
 private int kolumny;
 // deklaracja macierzy z planszą gry
 private boolean[][] plansza;

 // konstruktor, podajemy liczbę wierszy i kolumn planszy
 public GraWZycie(int wiersze, int kolumny) {
  // inicjalizujemy pola naszej klasy
  this.wiersze = wiersze;
  this.kolumny = kolumny;
  // tworzymy odpowiednią macierz, domyślnie wypełniona jest ona wartościami false
  plansza = new boolean[wiersze][kolumny];
 }

 // metoda pokazująca planszę na ekranie
 public void pokazPlansze(){
  // wyświetlamy każdy element planszy, w zależności od zawartości na ekranie pojawi się odpowiedni znak
  for(boolean wiersz[] : plansza){
   for(boolean element : wiersz)
    System.out.print((element) ? ZYWA : MARTWA);
   System.out.println();
  }
 }

 // przykładowa metoda uzupełniająca planszę populacją początkową
 public void utworzDaneTestowe() {
  // tworzymy populację początkową (standardowy Exploder)
  plansza[5][5] = true; plansza[5][7] = true; plansza[5][9] = true;
  plansza[6][5] = true; plansza[6][9] = true;
  plansza[7][5] = true; plansza[7][9] = true;
  plansza[8][5] = true; plansza[8][9] = true;
  plansza[9][5] = true; plansza[9][7] = true; plansza[9][9] = true;
 }

 // metoda zwraca liczbę żywych sąsiadów konkretnej komórki
 // w wywołaniu podajemy współrzędne komórki
 private int liczbaSasiadow(int x, int y) {

  // zmienna przechowująca liczbę sąsiadów
  int sasiedzi = 0;

  // sprawdzamy komórki na około naszej
  for(int i = x-1; i &amp;lt;= x+1; i++) {
   // jeżeli przekraczamy zakres planszy (wiersz) idziemy dalej
   if(i &amp;lt; 0 || i &amp;gt; wiersze-1) continue;
   for(int j = y-1; j &amp;lt;= y+1; j++) {
    // jeżeli przekraczamy zakres planszy (kolumna), lub jesteśmy w komórce(x,y) idziemy dalej
    if(j &amp;lt; 0 || j &amp;gt; kolumny-1 || (i == x &amp;amp;&amp;amp; j == y)) continue;
    // jeśli sąsiad jest żywy to zwiększamy naszą zmienną
    if(plansza[i][j]) sasiedzi++;
   }
  }
  // zwracamy zmienną
  return sasiedzi;
 }

 // metoda sprawdza czy dana komórka będzie żywa czy też martwa w następnym etapie
 // w wywołaniu podajemy współrzędne komórki
 private boolean ewolucja(int x, int y) {

  // sprawdzamy liczbę żywych sąsiadów
  int sasiedzi = liczbaSasiadow(x, y);

  // jeżeli nasza komórka jest żywa
  if(plansza[x][y]) {
   // jeśli liczba sąsiadów jest mniejsza lub równa jeden lub większa od trzech to nasza komórka będzie martwa
   if(sasiedzi &amp;lt;= 1 || sasiedzi &amp;gt; 3) return false;
   // jeśli liczba sąsiadów jest równa trzy lub dwa to nasza komórka będzie żywa
   if(sasiedzi == 3 || sasiedzi == 2) return true;
  } else {
   // jeśli nasza komórka jest martwa i ma dokładnie trzech żywych sąsiadów to będzie żyła
   if(sasiedzi == 3) return true;
  }
  // w każdym innym przypadku zwracamy fałsz (komórka jest martwa)
  return false;
 }

 // metoda tworzy następną populację/pokolenie komórek
 public void nastepnePokolenie() {
  // tworzymy planszę tymczasową o takim samy rozmiarze jak nasza
  boolean[][] planszaTymczasowa = new boolean[wiersze][kolumny];

  // uzupełniamy nową planszę wartościami na podstawie ogólnych zasad
  for(int i = 0; i &amp;lt; wiersze; i++)
   for(int j = 0; j &amp;lt; kolumny; j++) 
    planszaTymczasowa[i][j] = ewolucja(i, j);

  // nasza główna plansza staje się planszą tymczasową
  plansza = planszaTymczasowa;
 }

 public static void main(String[] args) {

  // wyświetlamy napisy informacyjne
  System.out.println(&quot;Gra w życie - [Enter] generuje następne pokolenie, dowolny znak i [Enter] kończy grę.&quot;);

  // obsługujemy wejście
  Scanner sc = new Scanner(System.in);

  // tworzymy nowy obiekt przekazując do konstruktora rozmiar planszy
  GraWZycie gra = new GraWZycie(15, 15);
  // wypełniamy naszą planszę wartościami testowymi
  gra.utworzDaneTestowe();
  // wyświetlamy planszę na ekranie
  gra.pokazPlansze();

  // dopóki użytkownik będzie naciskał klawisz Enter
  while(sc.nextLine().equals(&quot;&quot;)) {
   // generujemy następne pokolenie
   gra.nastepnePokolenie();
   // wyświetlamy go na ekranie
   gra.pokazPlansze();
  }
 }
}
&lt;/pre&gt;Pojawianie się następnych etapów naszej populacji może odbywać się automatycznie (bez konieczności naciskania klawisza &lt;b&gt;Enter&lt;/b&gt;). Poniżej zmodyfikowana wersja pętli &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;while&lt;/span&gt; z metody &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;main&lt;/span&gt;. Mankamentem tego rozwiązania jest to, iż zakończenie programu odbywa się jedynie poprzez jego przerwanie np. za pomocą kombinacji &lt;i&gt;Ctrl+C&lt;/i&gt;. &lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;while(true) {
 gra.nastepnePokolenie();
 gra.pokazPlansze();
 try {
  Thread.sleep(300); // długość pauzy w milisekundach
 } catch (Exception e) {}
}
&lt;/pre&gt;Uruchomiona aplikacja, początkowa populacja:  &lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Gra w życie - [Enter] generuje następne pokolenie, dowolny znak i [Enter] kończy grę.
...............
...............
...............
...............
...............
.....#.#.#.....
.....#...#.....
.....#...#.....
.....#...#.....
.....#.#.#.....
...............
...............
...............
...............
...............
&lt;/pre&gt;Populacja w następnych etapach: &lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;...............
...............
...............
...............
...............
......#.#......
....##...##....
....###.###....
....##...##....
......#.#......
...............
...............
...............
...............
...............
&lt;/pre&gt;&lt;pre class=&quot;console&quot;&gt;...............
...............
...............
...............
...............
.....#...#.....
....#.....#....
...#..#.#..#...
....#.....#....
.....#...#.....
...............
...............
...............
...............
...............
&lt;/pre&gt;&lt;div class=&quot;tip&quot;&gt;Gra wygląda znacznie lepiej w środowisku graficznym ;) &lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/8456346793186926923/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/10/gra-w-zycie.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8456346793186926923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8456346793186926923'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/10/gra-w-zycie.html' title='Gra w życie'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-7429673093066552274</id><published>2010-09-15T23:38:00.001+02:00</published><updated>2010-09-15T23:39:10.125+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Projekt Euler"/><title type='text'>Projekt Euler - Problem numer 1</title><content type='html'>Projekt Euler (&lt;a href=&quot;http://projecteuler.net/&quot; target=&quot;_blank&quot;&gt;http://projecteuler.net&lt;/a&gt;) to strona internetowa zawierająca pokaźny zbiór (ponad 300) problemów obliczeniowych, do rozwiązania których potrzebny jest (w większości przypadków) komputer oraz dowolny język programowania. Rozwiązaniem każdego zadania jest wynik, który podajemy, aby sprawdzić czy nasz sposób obliczeń jest poprawny. Oczywiście sednem zabawy jest opracowanie odpowiedniego dla danego problemu algorytmu. Przyjrzyjmy się zatem pierwszemu zadaniu.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;i&gt;Weźmy wszystkie liczby naturalne mniejsze od 10, które są wielokrotnościami liczb 3 lub 5. Otrzymamy liczby: 3, 5, 6, 9. Ich suma wynosi 25. Znajdź sumę wielokrotności liczb 3 lub 5 mniejszych od 1000.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Najprostszy z możliwych algorytm powinien sprawdzić wszystkie liczby z podanego zakresu oraz zsumować tylko te, które są wielokrotnościami liczb 3 lub 5.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
 * Projekt Euler - Problem nr 1
 * @author kodatnik.blogspot.com
 */
public class PEProblem1 {
 public static void main(String args[]) {
  // zmienna przechowująca sumę
  int suma = 0;

  // pętla dla liczb naturalnych mniejszych od 1000 (zaczynamy od 3)
  for(int i = 3; i &amp;lt; 1000; i++)
   // jeśli liczba jest podzielna przez 3 lub 5 dodajemy ją do sumy
   if((i % 3 == 0) || (i % 5 == 0))
    suma += i;
        
  //wyświetlamy wynik
  System.out.println(&quot;Suma wynosi: &quot; + suma);
 }
}
&lt;/pre&gt;Otrzymany wynik to: &lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Suma wynosi: 233168
&lt;/pre&gt;Pozostaje kwestia optymalizacji algorytmu. Czy można prościej, szybciej? Oczywiście. Pytanie tylko czy dla górnego zakresu (1000) jest to opłacalne?</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/7429673093066552274/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/09/projekt-euler-problem-numer-1.html#comment-form' title='Komentarze (10)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/7429673093066552274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/7429673093066552274'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/09/projekt-euler-problem-numer-1.html' title='Projekt Euler - Problem numer 1'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-7916643643889000150</id><published>2010-06-17T00:22:00.001+02:00</published><updated>2013-12-09T21:06:21.182+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Odległość Levenshteina - podobieństwo łańcuchów</title><content type='html'>Do obliczania podobieństwa łańcuchów tekstowych wykorzystuje się algorytm Levenshteina (&lt;i&gt;Vladimir Levenshtein - rosyjski uczony&lt;/i&gt;), znany również jako odległość edycyjna, albo odległość Levenshteina. Otrzymana w wyniku działania algorytmu liczba symbolizuje ile działań prostych musimy wykonać, aby dokonać konwersji/zamiany jednego łańcucha na drugi. Działania proste to wstawienie znaku, usunięcie znaku oraz zamiana znaku na inny. Dla łańcucha &lt;i&gt;&quot;kot&quot;&lt;/i&gt; i &lt;i&gt;&quot;kod&quot;&lt;/i&gt; odległość edycyjna wynosi 1. Musimy dokonać tylko jednej zamiany znaku. Im większa odległość tym bardziej różne są łańcuchy znaków.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Jak działa sam algorytm:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;ustalamy długość łańcuchów znaków (&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;dlugoscP &lt;/span&gt;- długość łańcucha pierwszego, &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;dlugoscD &lt;/span&gt;- długość łańcucha drugiego),&lt;/li&gt;
&lt;li&gt;tworzymy macierz o rozmiarze &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;(dlugoscP+1) x (dlugoscD+1)&lt;/span&gt;,&lt;/li&gt;
&lt;li&gt;inicjalizujemy pierwszy wiersz wartościami od &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;0&lt;/span&gt; do &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;dlugoscP&lt;/span&gt;,&lt;/li&gt;
&lt;li&gt;inicjalizujemy pierwszą kolumnę wartościami od &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;0&lt;/span&gt; do &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;dlugoscD&lt;/span&gt;,&lt;/li&gt;
&lt;li&gt;sprawdzamy każdy znak z łańcucha pierwszego (indeks &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;i&lt;/span&gt; od &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;1&lt;/span&gt; do &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;dlugoscP&lt;/span&gt;),&lt;/li&gt;
&lt;li&gt;sprawdzamy każdy znak z łańcucha drugiego (indeksy &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;j&lt;/span&gt; od &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;1&lt;/span&gt; do &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;dlugoscD&lt;/span&gt;),&lt;/li&gt;
&lt;li&gt;jeżeli znak na pozycji &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;i&lt;/span&gt; równa się znakowi na pozycji &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;j&lt;/span&gt; to koszt jest równy zero,&lt;/li&gt;
&lt;li&gt;jeżeli znak na pozycji &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;i&lt;/span&gt; jest różny od znaku na pozycji &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;j&lt;/span&gt; to koszt wynosi 1,&lt;/li&gt;
&lt;li&gt;ustawiamy wartość komórki &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;i,j&lt;/span&gt; jako minimum:&lt;/li&gt;

&lt;ul&gt;&lt;li&gt;komórka powyżej + 1,&lt;/li&gt;
&lt;li&gt;komórka z lewej + 1,&lt;/li&gt;
&lt;li&gt;komórka po skosie (góra, lewo) + koszt.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;algorytm powtarzamy dla wszystkich znaków, całkowity koszt otrzymamy w komórce o indeksie &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;dlugoscP&lt;/span&gt;, &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;dlugoscD&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
Sprawdźmy działanie algorytmu na przykładzie dwóch łańcuchów: &lt;i&gt;&quot;notatnik&quot;&lt;/i&gt; i &lt;i&gt;&quot;kodatnik&quot;&lt;/i&gt;. Poniżej utworzona została macierz i obliczone zostały odpowiednie wartości komórek.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;n o t a t n i k&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;0 1 2 3 4 5 6 7 8&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;k 1 1 2 3 4 5 6 7 7&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;o 2 2 1 2 3 4 5 6 7&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;d 3 3 2 2 3 4 5 6 7&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;a 4 4 3 3 2 3 4 5 6&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;t 5 5 4 3 3 2 3 4 5&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;n 6 5 5 4 4 3 2 3 4&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;i 7 6 6 5 5 4 3 2 3&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;k 8 7 7 6 6 5 4 3 2&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Odczytana odległość edycyjna wynosi zatem 2 (wartość komórki o indeksie &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;[8][8]&lt;/span&gt;). Dodatkowo możemy określić podobieństwo wyrazów stosując następujący wzór:&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;1 / (1 + OL)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
gdzie &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;OL&lt;/span&gt; to odległość Levenshteina dla dwóch łańcuchów obliczona zgodnie z powyższym algorytmem. Dla naszego przykładu podobieństwo wynosi: &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;1/3&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
Poniżej prosty program liczący odległość Levenshteina oraz podobieństwo łańcuchów.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.util.Scanner;

/**
 * Obliczanie odległości Levenshteina (odległości edycyjnej)
 * Wyznaczanie podobieństwa łancuchów znaków
 * @author kodatnik.blogspot.com
 */
public class Levenshtein {

 public static int obliczOdleglosc(String p, String d) {
  // określamy długości łańcuchów znaków
  int dlugoscP = p.length();
  int dlugoscD = d.length();

  // tworzymy odpowiednią macierz
  int[][] macierz = new int[dlugoscP + 1][dlugoscD + 1];

  // uzupełniamy pierwszy wiersz i pierwszą kolumnę
  for(int i = 0; i &amp;lt;= dlugoscP; macierz[i][0] = i++);
  for(int j = 1; j &amp;lt;= dlugoscD; macierz[0][j] = j++);

  // sprawdzamy poszczególne znaki
  for(int i = 1; i &amp;lt;= dlugoscP; i++) {
   char znak = p.charAt(i - 1);
   for(int j = 1; j &amp;lt;= dlugoscD; j++) {
    // obliczamy koszt
    int koszt = macierz[i - 1][j - 1];
    if(d.charAt(j - 1) !=  znak ) koszt++;
    // wstawiamy minimum
    macierz[i][j] = Math.min( Math.min( macierz[i - 1][j] + 1, macierz[i][j - 1] + 1), koszt);
   }
  }
  // zwracamy całkowity koszt, odległość Levenshteina
  return macierz[dlugoscP][dlugoscD];
 }

 public static double obliczPodobienstwo(String lancuchPierwszy, String lancuchDrugi) {
  // obliczamy i zwracamy podobieństwo łańcuchów
  return (1.0/(1.0 + obliczOdleglosc(lancuchPierwszy, lancuchDrugi)));
 }

 public static void main(String[] args) {
  String lancuchPierwszy, lancuchDrugi;

  // pobieramy dane
  Scanner wejscie = new Scanner(System.in);
  System.out.print(&quot;Podaj pierwszy ciąg znaków: &quot;);
  lancuchPierwszy = wejscie.nextLine();
  System.out.print(&quot;Podaj drugi ciąg znaków: &quot;);
  lancuchDrugi = wejscie.nextLine();

  // wyświetlamy obliczone wyniki
  System.out.println(&quot;Odległość Levenshteina: &quot; + obliczOdleglosc(lancuchPierwszy, lancuchDrugi));
  System.out.println(&quot;Podobieństwo ciągów znaków: &quot; + obliczPodobienstwo(lancuchPierwszy, lancuchDrugi));
 }
}
&lt;/pre&gt;Wynik działania programu dla przykładowych danych. &lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Podaj pierwszy ciąg znaków: notatnik
Podaj drugi ciąg znaków: kodatnik
Odległość Levenshteina: 2
Podobieństwo ciągów znaków: 0.3333333333333333
&lt;/pre&gt;&lt;div class=&quot;tip&quot;&gt;Praktyczne wykorzystanie algorytmu to między innymi sprawdzanie pisownii, rozpoznawanie mowy, analiza DNA, wykrywanie plagiatów itp. &lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/7916643643889000150/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/06/odlegosc-levenshteina-podobienstwo.html#comment-form' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/7916643643889000150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/7916643643889000150'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/06/odlegosc-levenshteina-podobienstwo.html' title='Odległość Levenshteina - podobieństwo łańcuchów'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-3162203762671259086</id><published>2010-04-17T00:37:00.001+02:00</published><updated>2010-04-17T00:39:32.297+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Algorytm Luhna</title><content type='html'>Algorytm Luhna (autor: Hans Peter Luhn - naukowiec z IBM) jest najczęściej wykorzystywanym sposobem sprawdzenia poprawności ciągu liczb. Jego zastosowanie to sprawdzanie numerów kart kredytowych i innych np. lojalnościowych, numerów IMEI, numerów ubezpieczeń itd. Algorytm działa na pojedynczych cyfrach od prawej do lewej strony sprawdzanej liczby. Sam schemat jest bardzo prosty i sprowadza się do kilku kroków:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;sumujemy cyfry nieparzyste (pierwszą, trzecią, piąta itd.),&lt;/li&gt;
&lt;li&gt;podwajamy cyfry parzyste (drugą, czwartą, szóstą itd.), jeśli podwojona wartość jest większa od 9, sumujemy cyfry (np. podwajamy 8, dostajemy 16, wartość większa od 9, sumujemy cyfry 1+6, dostajemy wynik 7),&lt;/li&gt;
&lt;li&gt;sumujemy otrzymane cyfry z kroku drugiego,&lt;/li&gt;
&lt;li&gt;dodajemy dwie sumy (dla cyfr parzystych i nieparzystych), jeśli wynik modulo 10 daje 0 to liczba jest poprawna, w przeciwnym przypadku niepoprawna.&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Przeanalizujmy algorytm na prostym przykladzie. Mamy numer karty: 4853928344613904. Poruszamy się od prawej do lewej strony. Obliczamy sumę cyfr nieparzystych:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;sumaNieparzystych = 4 + 9 + 1 + 4 + 3 + 2 + 3 + 8 = 34
&lt;/pre&gt;Obliczamy sumę podwojonych cyfr parzystych (jeśli podwojona wartość jest większa od 9 dodajemy poszczególne cyfry):&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;sumaParzystych = 0 + 6 + (1+2) + 8 + (1+6) + (1+8) + (1+0) + 8 = 42
&lt;/pre&gt;Dodajemy otrzymane wyniki:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;sumaParzystych + sumaNieparzystych = 76
&lt;/pre&gt;Reszta z dzielenia 76 przez 10 (76 modulo 10) nie jest zerem więc nasz numer nie jest poprawny.&lt;br /&gt;
&lt;br /&gt;
Zapiszmy algorytm wykorzystując Javę. Metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;czyPoprawna()&lt;/span&gt; zwróci nam wartość logiczną świadczącą o poprawności bądź też nie sprawdzanego ciągu cyfr.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
 * Implementacja algorytmu Luhna
 * @author kodatnik.blogspot.com
 */
public class AlgorytmLuhna {

 public static boolean czyPoprawna(String liczba){
  // zmienne przechowujące odpowiednie sumy
  int sumaParzystych = 0, sumaNieparzystych = 0;

  // odwracamy liczbę dla uproszczenia obliczeń
  String odwroconaLiczba = new StringBuilder(liczba).reverse().toString();
        
  // pętla dla poszczególnych cyfr
  for(int i = 0 ;i &amp;lt; odwroconaLiczba.length(); i++){

   // zamieniamy znak cyfry na wartość liczbową
   int cyfra = Integer.parseInt(odwroconaLiczba.substring(i, i + 1));
            
   // cyfra na pozycji nieparzystej
   if(i % 2 == 0) { 
    // zwiększamy sumę 
    sumaNieparzystych += cyfra;
   } 
   // cyfra na pozycji parzystej
   else {  
    // podwajamy cyfrę
    cyfra = cyfra * 2;
                
    // jeśli wynik większy od 9 to sumujemy cyfry wyniku
    if (cyfra &amp;gt; 9) cyfra = (cyfra%10)+1;

    // zwiększamy sumę
    sumaParzystych += cyfra;
   }
  }
  // zwracamy prawdę lub fałsz w zależności od wyniku modulo 10
  return (sumaParzystych + sumaNieparzystych) % 10 == 0;
 }

 public static void main(String[] args) {
  System.out.println(czyPoprawna(&quot;4853928344613904&quot;));
  System.out.println(czyPoprawna(&quot;4408041234567893&quot;));
 }
}
&lt;/pre&gt;Uruchomiona aplikacja:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;false
true
&lt;/pre&gt;Czyli pierwsza liczba jest niepoprawna, a druga poprawna (oczywiście według algorytmu Luhna).</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/3162203762671259086/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/04/algorytm-luhna.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/3162203762671259086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/3162203762671259086'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/04/algorytm-luhna.html' title='Algorytm Luhna'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-8698515816070746401</id><published>2010-04-16T20:49:00.000+02:00</published><updated>2010-04-16T20:49:35.748+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Struktury Danych"/><title type='text'>Wyświetlanie drzewa na konsoli</title><content type='html'>W poprzednich postach utworzyliśmy strukturę drzewa (&lt;a href=&quot;http://kodatnik.blogspot.com/2010/02/drzewo-ogolna-implementacja.html&quot; target=&quot;_blank&quot;&gt;Ogólna implementacja&lt;/a&gt;) oraz poznaliśmy metody umożliwiające przejście przez wszystkie jego węzły w określonej kolejności (&lt;a href=&quot;http://kodatnik.blogspot.com/2010/03/trawersowanie-drzewa-metody-preorder.html&quot; target=&quot;_blank&quot;&gt;Trawersowanie drzewa&lt;/a&gt;). Kolejnym krokiem będzie przedstawienie struktury drzewa w jakiejś czytelnej formie na ekranie komputera. Wykorzystamy do tego celu konsolę. Jest kilka sposobów prezentacji drzewa, najczęściej wykorzystuje się zapis, gdzie poszczególne elementy są w odpowiednich kolumnach lub zapis z nawiasami, które symbolizują dzieci danego elementu. Przyjrzyjmy się naszemu drzewu jeszcze raz w formie graficznej.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiSAgVUylYlCT1wcPoQ2XJtwWJ_TDy_7QpRZeL6o-r1ocH33uGrC6HYtSu9cFKQrRI28Rt5R4eblXb5KapBlcQxf_86WBkWEGjrn0qU4ms-Ov9fe6PFWaBSpX6VdZO36AqhM7dk9mTnTU/s1600/Drzewo1%20(1).jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;160&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiSAgVUylYlCT1wcPoQ2XJtwWJ_TDy_7QpRZeL6o-r1ocH33uGrC6HYtSu9cFKQrRI28Rt5R4eblXb5KapBlcQxf_86WBkWEGjrn0qU4ms-Ov9fe6PFWaBSpX6VdZO36AqhM7dk9mTnTU/s320/Drzewo1%20(1).jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
W postaci konsolowej możemy zapisać jego strukturę tak:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Adam
        Ewa
                Jurek
                Max
                Iza
        Jarek
                Iwona
        Marta
                Rafał
                Ola
&lt;/pre&gt;lub tak:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Adam(Ewa(Jurek, Max, Iza), Jarek(Iwona), Marta(Rafał, Ola))
&lt;/pre&gt;W obu przypadkach odczytujemy:  Adam jest korzeniem i ma trójkę &quot;dzieci&quot; (Ewa, Jarek oraz Marta), Ewa ma trójkę &quot;dzieci&quot; (Jurek, Max oraz Iza), Jarek ma jedno &quot;dziecko&quot; (Iwona), Marta ma dwójkę &quot;dzieci&quot; (Rafał i Ola).&lt;br /&gt;
&lt;br /&gt;
Jak utworzyć metody, które wyświetlą nam odpowiednią kolejność elementów oraz zapewnią formatowanie? Przyjrzyjmy się najpierw kolejności elementów....tak dokładnie to jest kolejność preorder. Wystarczy teraz tylko odpowiednio dokonać formatowania oraz wyświetlić zawartość elementów. Pierwszy sposób wymaga dopisania metody, która będzie dla danego elementu zwracać jego poziom (odległość od korzenia drzewa). Napiszemy w klasie &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Tree&amp;lt;T&amp;gt;&lt;/span&gt; prostą metodę rekurencyjną &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;getLevel()&lt;/span&gt;:&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false&quot;&gt;public int getLevel(Node&amp;lt;T&amp;gt; n) {
 if (n == root) return 0;
 else return 1 + getLevel(n.getParent());
}
&lt;/pre&gt;Dodatkowo dodamy do naszej klasy pole output typu &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;StringBuilder&lt;/span&gt; (taki dynamiczny &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;String&lt;/span&gt;). W tej zmiennej będziemy przechowywać widok naszego drzewa. Metoda, która przygotuje nam ten widok działa bardzo podobnie jak metoda trawersująca typu preorder. Jedyne modyfikacje to pobieranie poziomu węzła i dodawanie odpowiedniej ilości znaków tabulacji (symulacja kolumn).&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false&quot;&gt;private void makeTreeStringOutline(Node&amp;lt;T&amp;gt; n) {
 for(int i=0; i &amp;lt; getLevel(n); i++) output.append(&quot;\t&quot;);
 output.append(n + &quot;\n&quot;);
 Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
 while (temp != null) {
  makeString(temp);
  temp = temp.getRightSibling();
 }
}
&lt;/pre&gt;Drugi sposób prezentacji drzewa zostanie zrealizowany bardzo podobnie. Opieramy się na trawersowaniu preorder oraz wstawiamy w odpowiednie miejsca znaki nawiasów (otwierające i zamykające).&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false&quot;&gt;private void makeTreeStringBrackets(Node&amp;lt;T&amp;gt; n) {
 output.append(n);
 Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
 if( temp != null) output.append(&quot;(&quot;);
 while (temp != null) {
  makeStringPar(temp);
  temp = temp.getRightSibling();
  if (temp != null) output.append(&quot;, &quot;);
  else output.append(&quot;)&quot;);
 }
}
&lt;/pre&gt;Wywołanie tych metod możemy umieścić w dowolnej metodzie. Najlepiej będzie wykorzystać do tego celu metodę &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;toString()&lt;/span&gt;. Przesłonięta wersja tej metody poniżej (prezentacja drzewa możliwa jest na dwa sposoby, jeden jest ujęty w komentarz).&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false&quot;&gt;public String toString() {
 output = new StringBuilder();

 makeTreeStringOutline(root); // wersja &quot;drzewiasta&quot;
 //makeTreeStringBrackets(root); // wersja z nawiasami

 return output.toString();
}
&lt;/pre&gt;Pozostaje tylko sprawdzenie czy nasz kod działa. Utwórzmy drzewo i wyświetlmy je na konsoli.&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false&quot;&gt;Node&amp;lt;String&amp;gt; korzen = new Node&amp;lt;String&amp;gt;(null, &quot;Adam&quot;);
Node&amp;lt;String&amp;gt; n1 = korzen.addChild(&quot;Ewa&quot;);
Node&amp;lt;String&amp;gt; n2 = korzen.addChild(&quot;Jarek&quot;);
Node&amp;lt;String&amp;gt; n3 = korzen.addChild(&quot;Marta&quot;);

n1.addChild(&quot;Jurek&quot;);
n1.addChild(&quot;Max&quot;);
n1.addChild(&quot;Iza&quot;);

n2.addChild(&quot;Iwona&quot;);

n3.addChild(&quot;Rafał&quot;);
n3.addChild(&quot;Ola&quot;);

Tree&amp;lt;String&amp;gt; drzewo = new Tree&amp;lt;String&amp;gt;(korzen);

System.out.println (drzewo);
&lt;/pre&gt;Efekt działania:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Adam
        Ewa
                Jurek
                Max
                Iza
        Jarek
                Iwona
        Marta
                Rafał
                Ola
&lt;/pre&gt;Poniżej cały kod drzewa wraz ze wszystkimi klasami i metodami.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;import java.util.*;

/**
 * Klasa Node&amp;lt;T&amp;gt; - węzeł drzewa
 * @author kodatnik.blogspot.com
 */
class Node&amp;lt;T&amp;gt; {
 private T data;
 private Node&amp;lt;T&amp;gt; parent;
 private LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; children;

 public Node() {
  parent = null;
  children = new LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt;();
 }

 public Node(Node&amp;lt;T&amp;gt; parent) {
  this();
  this.parent = parent;
 }

 public Node(Node&amp;lt;T&amp;gt; parent, T data) {
  this(parent);
  this.data = data;
 }

 public Node&amp;lt;T&amp;gt; getParent(){
  return parent;
 }

 public void setParent(Node&amp;lt;T&amp;gt; parent) {
  this.parent = parent;
 }

 public T getData() {
  return data;
 }

 public void setData(T data) {
  this.data = data;
 }

 public int getDegree() {
  return children.size();
 }

 public boolean isLeaf(){
  return children.isEmpty();
 }

 public Node&amp;lt;T&amp;gt; addChild(Node&amp;lt;T&amp;gt; child) {
  child.setParent(this);
  children.add(child);
  return child;
 }

 public Node&amp;lt;T&amp;gt; addChild(T data) {
  Node&amp;lt;T&amp;gt; child = new Node&amp;lt;T&amp;gt;(this, data);
  children.add(child);
  return child;
 }

 public Node&amp;lt;T&amp;gt; getChild(int i){
  return children.get(i);
 }

 public Node&amp;lt;T&amp;gt; removeChild(int i) {
  return children.remove(i);
 }

 public void removeChildren() {
  children.clear();
 }

 public LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; getChildren() {
  return children;
 }

 public Node&amp;lt;T&amp;gt; getLeftMostChild() {
  if (children.isEmpty()) return null;
  return children.get(0);
 }

 public Node&amp;lt;T&amp;gt; getRightSibling() {
  if (parent != null) {
   LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; parentsChildren = parent.getChildren();
   int pos = parentsChildren.indexOf(this);
   if (pos &amp;lt; (parentsChildren.size()-1))
    return parentsChildren.get(pos+1);
  }
  return null;
 }

 public String toString() {
  return data.toString();
 }
}

/**
 * Klasa Tree&amp;lt;T&amp;gt; - drzewo
 * @author kodatnik.blogspot.com
 */
class Tree&amp;lt;T&amp;gt; {

 private Node&amp;lt;T&amp;gt; root;
 private StringBuilder output;

 public Tree() {
  root = null;
 }

 public Tree(Node&amp;lt;T&amp;gt; root) {
  this.root = root;
 }

 public Node&amp;lt;T&amp;gt; getRoot() {
  return root;
 }

 public void preOrder() {
  preOrder(root);
 }

 public void postOrder() {
  postOrder(root);
 }

 public void inOrder() {
  inOrder(root);
 }

// metoda wyświetla węzły w kolejności preorder
public void preOrder(Node&amp;lt;T&amp;gt; n) {
 //najpierw korzeń
 System.out.print(n + &quot; &quot;);
 // potem lewe skrajne poddrzewo, a później prawe
 Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
 while (temp != null) {
  preOrder(temp);
  temp = temp.getRightSibling();
 }
}

// metoda wyświetla węzły w kolejności postorder
public void postOrder(Node&amp;lt;T&amp;gt; n) {
 // najpierw lewe skrajne poddrzewo, potem prawe
 Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
 while (temp != null) {
  postOrder(temp);
  temp = temp.getRightSibling();
 }
 // na końcu korzeń
 System.out.print(n + &quot; &quot;);
}

// metoda wyświetla węzły w kolejności inorder
public void inOrder(Node&amp;lt;T&amp;gt; n) {
 if (n.isLeaf())
  System.out.print(n + &quot; &quot;);
 else {
  // najpierw lewe skrajne poddrzewo
  Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
  inOrder(temp);
  // potem korzeń
  System.out.print(n + &quot; &quot;);
  // potem prawe
  temp = temp.getRightSibling();
  while (temp != null) {
   inOrder(temp);
   temp = temp.getRightSibling();
  }
 }
}

 // metoda zwraca poziom węzła
 public int getLevel(Node&amp;lt;T&amp;gt; n) {
  if (n == root) return 0;
  else return 1 + getLevel(n.getParent());
 }

 private void makeTreeStringOutline(Node&amp;lt;T&amp;gt; n) {
  for(int i=0; i &amp;lt; getLevel(n); i++) output.append(&quot;\t&quot;);
  output.append(n + &quot;\n&quot;);
  Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
  while (temp != null) {
   makeTreeStringOutline(temp);
   temp = temp.getRightSibling();
  }
 }

 private void makeTreeStringBrackets(Node&amp;lt;T&amp;gt; n) {
  output.append(n);
  Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
  if( temp != null) output.append(&quot;(&quot;);
  while (temp != null) {
   makeTreeStringBrackets(temp);
   temp = temp.getRightSibling();
   if (temp != null) output.append(&quot;, &quot;);
   else output.append(&quot;)&quot;);
  }
 }

 public String toString() {
  output = new StringBuilder();

  makeTreeStringOutline(root); // reprezentacja drzewiasta
  //makeTreeStringBrackets(root); // reprezentacja z nawiasami

  return output.toString();
 }
}

public class NaszeDrzewo {
 public static void main(String args[]) {

  // tworzymy węzeł będący korzeniem
  Node&amp;lt;String&amp;gt; korzen = new Node&amp;lt;String&amp;gt;(null, &quot;Adam&quot;);

  // dodajemy do niego kolejne węzły
  Node&amp;lt;String&amp;gt; n1 = korzen.addChild(&quot;Ewa&quot;);
  Node&amp;lt;String&amp;gt; n2 = korzen.addChild(&quot;Jarek&quot;);
  Node&amp;lt;String&amp;gt; n3 = korzen.addChild(&quot;Marta&quot;);

  n1.addChild(&quot;Jurek&quot;);
  n1.addChild(&quot;Max&quot;);
  n1.addChild(&quot;Iza&quot;);

  n2.addChild(&quot;Iwona&quot;);

  n3.addChild(&quot;Rafał&quot;);
  n3.addChild(&quot;Ola&quot;);

  // tworzymy drzewo i wskazujemy, który węzeł jest korzeniem
  Tree&amp;lt;String&amp;gt; drzewo = new Tree&amp;lt;String&amp;gt;(korzen);

  System.out.println(drzewo);
 }
}
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/8698515816070746401/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/04/wyswietlanie-drzewa-na-konsoli.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8698515816070746401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8698515816070746401'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/04/wyswietlanie-drzewa-na-konsoli.html' title='Wyświetlanie drzewa na konsoli'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiSAgVUylYlCT1wcPoQ2XJtwWJ_TDy_7QpRZeL6o-r1ocH33uGrC6HYtSu9cFKQrRI28Rt5R4eblXb5KapBlcQxf_86WBkWEGjrn0qU4ms-Ov9fe6PFWaBSpX6VdZO36AqhM7dk9mTnTU/s72-c/Drzewo1%20(1).jpg" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-5249529466562646405</id><published>2010-04-01T00:55:00.005+02:00</published><updated>2010-04-01T01:18:41.931+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Podstawy"/><title type='text'>Klasa Arrays - przykłady zastosowań</title><content type='html'>Dość często korzystamy z tablic jedno i wielowymiarowych. Klasa &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;java.util.Arrays&lt;/span&gt; dostarcza wielu ciekawych metod ułatwiających pracę z tymi strukturami danych. Większość z nich jest przeciążona obsługując wiele typów danych (metoda przeciążona - metoda o takiej samej nazwie, ale różnej ilości lub rodzaju argumentów). Poniżej kilka przykładów wykorzystania tych metod (pamietaj o imporcie odpowiedniego pakietu - &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;import java.util.*&lt;/span&gt;).&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Wyświetlanie tablicy - metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;toString()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;toString()&lt;/span&gt; zwraca tablicą jednowymiarową w formie tekstowej. Poszczególne elementy oddzielone są przecinkami. Jako parametr wywołania podajemy interesującą nas tablicę.&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;int[] tablica = {3, 8, 5, 6, 9, 2, 7, 4, 1};
System.out.println(Arrays.toString(tablica));
&lt;/pre&gt;Wynik:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[3, 8, 5, 6, 9, 2, 7, 4, 1]
&lt;/pre&gt;Jest to znaczące ułatwienie wyświetlania wszelkiego rodzaju tablic (nie musimy juz stosować pętli &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;for&lt;/span&gt;). Dla tablic wielowymiarowych istnieje rekurencyjna wersja tej metody o nazwie &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;deepToString()&lt;/span&gt;.&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;int[][] macierz = { { 3, 8, 5},
                    { 5, 9, 2},
                    { 7, 4, 1} };
  
System.out.println(Arrays.deepToString(macierz));
&lt;/pre&gt;Wynik:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[[3, 8, 5], [5, 9, 2], [7, 4, 1]]
&lt;/pre&gt;&lt;b&gt;Wypełnianie tablicy wartością - metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;fill()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Gdy chcemy wypełnić zawartość tablicy jakąś wartością możemy wykorzystać metodę &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;fill()&lt;/span&gt;. Ma ona dwa parametry, pierwszy tablicę i drugi wartość jaką chcemy ją wypełnić.&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;int[] tablica = {3, 8, 5, 6, 9, 2, 7, 4, 1};
System.out.println(Arrays.toString(tablica));  
   
Arrays.fill(tablica, 14);
System.out.println(Arrays.toString(tablica));
&lt;/pre&gt;Wynik:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[3, 8, 5, 6, 9, 2, 7, 4, 1]
[14, 14, 14, 14, 14, 14, 14, 14, 14]
&lt;/pre&gt;Możemy również wykorzystać wypełnianie tylko części tablicy określoną wartością. Wykorzystamy do tego inną wersję metody &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;fill()&lt;/span&gt; z czterema parametrami (dwa dodatkowe to indeks pierwszego i ostatniego elementu, który będziemy zmieniać, w przykładzie wartości 2 i 5).&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;int[] tablica = {3, 8, 5, 6, 9, 2, 7, 4, 1};
System.out.println(Arrays.toString(tablica));  
   
Arrays.fill(tablica, 2, 5, 14);
System.out.println(Arrays.toString(tablica));  
&lt;/pre&gt;Wynik:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[3, 8, 5, 6, 9, 2, 7, 4, 1]
[3, 8, 14, 14, 14, 2, 7, 4, 1]
&lt;/pre&gt;&lt;b&gt;Sortowanie tablicy - metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;sort()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Tablice możemy sortować za pomocą metody &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;sort()&lt;/span&gt; (wykorzystywany jest algorytm sortowania szybkiego - &lt;i&gt;quickSort&lt;/i&gt;).&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;int[] tablica = {3, 8, 5, 6, 9, 2, 7, 4, 1};
System.out.println(Arrays.toString(tablica));  

Arrays.sort(tablica);    
System.out.println(Arrays.toString(tablica));    
&lt;/pre&gt;Wynik:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[3, 8, 5, 6, 9, 2, 7, 4, 1]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
&lt;/pre&gt;Przeciążona wersja metody &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;sort()&lt;/span&gt; (z trzema parametrami) umożliwia sortowanie tylko części tablicy. Dodatowo podajemy indeks pierwszego i ostatniego elementu do sortowania. Jeżeli nasza tablica zawiera obiekty to muszą one implementować interfejs &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Comparable&lt;/span&gt; (pisałem o nim w poście  &lt;a href=&quot;http://kodatnik.blogspot.com/2010/01/porownujemy-obiekty-interfejs.html&quot; target=&quot;_blank&quot;&gt;Porównujemy obiekty - interfejs Comparable&amp;lt;T&amp;gt;&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Wyszukiwanie elementu - metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;binarySearch()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Znalezienie szukanej wartości w tablicy to zadanie dla metody &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;binarySearch()&lt;/span&gt;. Ponieważ wykorzystuje ona wyszukiwanie binarne to tablica musi być już wstępnie posortowana. Metoda zwraca numer indeksu, na którym znajduje się poszukiwany element  lub wartośc &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;-1&lt;/span&gt; jeśli taki element nie występuje w  tablicy. Poniższy przykład sortuje tablicę oraz szuka w niej wartości &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;4&lt;/span&gt;.&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;int[] tablica = {3, 8, 5, 6, 9, 2, 7, 4, 1};
System.out.println(Arrays.toString(tablica));  
   
Arrays.sort(tablica);    
System.out.println(Arrays.toString(tablica));    
         
System.out.println(Arrays.binarySearch(tablica, 4));   
&lt;/pre&gt;Wynik (tablica nieposortowana, posortowana oraz indeks na którym znajduje się wartość&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt; 4&lt;/span&gt;):&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[3, 8, 5, 6, 9, 2, 7, 4, 1]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
3
&lt;/pre&gt;Możemy również wykorzystać przeciążoną wersję metody &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;binarySearch()&lt;/span&gt; wyszukującą tylko w określonej części posortowanej tablicy.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Porównywanie zawartości tablic - metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;equals()&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Sprawdzenie czy dwie tablice są takie same (zawierają takie same elementy) realizowane jest za pomocą metody &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;equals()&lt;/span&gt;. Zwraca ona prawdę (wartość &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;true&lt;/span&gt;) jeśli tak i fałsz (wartość&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt; false&lt;/span&gt;) jeśli nie.&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;int[] tablicaA = {3, 8, 5, 6, 9, 2, 7, 0, 1};
int[] tablicaB = {3, 8, 5, 6, 9, 2, 7, 4, 1};         
   
if(Arrays.equals(tablicaA, tablicaB)) 
 System.out.println (&quot;Tablice są takie same.&quot;);
else 
 System.out.println (&quot;Tablice są różne.&quot;);
&lt;/pre&gt;Wynik:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Tablice są różne.
&lt;/pre&gt;Dla tablic wielowymiarowych odpowiednią metodą porównującą jest &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;deepEquals()&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Mieszanie zawartości tablicy...&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Ostatnia przydatna rzecz to możliwość pomieszania elementów występujących w tablicy. Nie do końca ma to związek z klasą &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Arrays&lt;/span&gt;, ale... Załóżmy, że mamy taką tablicę:&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;String[] imiona = { &quot;Adam&quot;, &quot;Marek&quot;, &quot;Iwona&quot;, &quot;Patryk&quot;, &quot;Dorota&quot;, &quot;Ewa&quot;};
&lt;/pre&gt;W klasie obsługującej kolekcje (&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Collections&lt;/span&gt;) istnieje metoda, która miesza (&lt;i&gt;ang. shuffle&lt;/i&gt;) elementy danej kolekcji (kolekcja to pojemnik przechowujący jakieś dane). Gdyby udało nam się zamienić naszą tablicę na kolekcję to moglibyśmy wykorzystać metodę mieszającą. Z pomocą przychodzi metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;toList()&lt;/span&gt; z klasy &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Arrays&lt;/span&gt;. Zamienia ona naszą tablicę w listę (obiekt klasy &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;List&lt;/span&gt;), która jest już częścią kolekcji i daje nam możliwość wykorzystania metody &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;shuffle()&lt;/span&gt;.&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;Collections.shuffle(Arrays.asList(imiona));
System.out.println(Arrays.toString(imiona));
&lt;/pre&gt;Przykładowa zawartość naszej tablicy po wymieszaniu elementów:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[Marek, Patryk, Ewa, Dorota, Adam, Iwona]
&lt;/pre&gt;Elementami kolekcji mogą być tylko typy obiektowe. Gdybyśmy chcieli pomieszać typy prymitywne to wystarczy użyć klas opakowujących i tak na przykład dla tablicy z wartościami typu &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;int&lt;/span&gt; możemy użyć poniższego kodu (konwersja między typem &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;int&lt;/span&gt;, a &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Integer&lt;/span&gt; jest automatyczna).&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter:false&quot;&gt;Integer[] tablica = {3, 8, 5, 6, 9, 2, 7, 4, 1};
Collections.shuffle(Arrays.asList(tablica));
System.out.println(Arrays.toString(tablica));
&lt;/pre&gt;Przykładowy wynik:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[1, 9, 6, 3, 7, 2, 5, 4, 8]
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/5249529466562646405/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/04/klasa-arrays-przykady-zastosowan.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/5249529466562646405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/5249529466562646405'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/04/klasa-arrays-przykady-zastosowan.html' title='Klasa Arrays - przykłady zastosowań'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-7493435889401494679</id><published>2010-03-31T00:35:00.002+02:00</published><updated>2010-03-31T00:37:37.330+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Struktury Danych"/><title type='text'>Trawersowanie drzewa - metody preorder, postoder i inorder</title><content type='html'>W poprzednim poście (&lt;a href=&quot;http://kodatnik.blogspot.com/2010/02/drzewo-ogolna-implementacja.html&quot; target=&quot;_blank&quot;&gt;Drzewo ogólna implementacja&lt;/a&gt;) przedstawiłem podstawy tworzenia struktury drzewa. Dziś zajmiemy się sposobami trawersowanie drzewa czyli odwiedzenia wszystkich jego węzłów w ściśle określonej kolejności. Dla drzew ogólnych mamy dwie metody odwiedzania &lt;b&gt;preorder&lt;/b&gt; oraz &lt;b&gt;postorder&lt;/b&gt;, w przypadku drzew binarnych (gdzie węzeł może posiadać maksymalnie dwóch potomków) istnieje jeszcze metoda &lt;b&gt;inorder&lt;/b&gt;.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Metoda &lt;b&gt;preorder&lt;/b&gt; odwiedza węzły w następującej kolejności:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;najpierw korzeń,&lt;/li&gt;
&lt;li&gt;potem lewe skrajne poddrzewo,&lt;/li&gt;
&lt;li&gt;potem prawe skrajne poddrzewo.&lt;/li&gt;
&lt;/ul&gt;Trawersowanie za pomocą &lt;b&gt;postorder&lt;/b&gt;:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;najpierw lewe skrajne poddrzewo,&lt;/li&gt;
&lt;li&gt;potem prawe skrajne poddrzewo,&lt;/li&gt;
&lt;li&gt;i na końcu korzeń.&lt;/li&gt;
&lt;/ul&gt;Metoda&lt;b&gt; inorder&lt;/b&gt;:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;najpierw lewe skrajne poddrzewo,&lt;/li&gt;
&lt;li&gt;potem korzeń,&lt;/li&gt;
&lt;li&gt;potem prawe skrajne poddrzewo.&lt;/li&gt;
&lt;/ul&gt;Dla naszego przykładowego drzewa ogólnego metody preorder i postorder zwrócą następującą kolejność węzłów.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiSAgVUylYlCT1wcPoQ2XJtwWJ_TDy_7QpRZeL6o-r1ocH33uGrC6HYtSu9cFKQrRI28Rt5R4eblXb5KapBlcQxf_86WBkWEGjrn0qU4ms-Ov9fe6PFWaBSpX6VdZO36AqhM7dk9mTnTU/s1600-h/Drzewo1+(1).jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;160&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiSAgVUylYlCT1wcPoQ2XJtwWJ_TDy_7QpRZeL6o-r1ocH33uGrC6HYtSu9cFKQrRI28Rt5R4eblXb5KapBlcQxf_86WBkWEGjrn0qU4ms-Ov9fe6PFWaBSpX6VdZO36AqhM7dk9mTnTU/s320/Drzewo1+(1).jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;preorder: Adam Ewa Jurek Max Iza Jarek Iwona Marta Rafał Ola 
postorder: Jurek Max Iza Ewa Iwona Jarek Rafał Ola Marta Adam
&lt;/pre&gt;&lt;br /&gt;
Gdybyśmy utworzyli drzewo binarne z następującą strukturą (takie drzewo nazywane jest drzewem wyrażeń arytmetycznych):&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuNPSFRRBc32CQItb-An1kZmmmJqFujtSl5rXU3LVwkLKQTHo6CvfwsG5Hkhix3mnLIJ7fx6jJaDlWJHLZBMZKOLZTYh08mDQxaLjq42I6faYCmp2lryOao1c5olfqDzh_bCWQaVUCFTVG/s1600-h/Drzewoary.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuNPSFRRBc32CQItb-An1kZmmmJqFujtSl5rXU3LVwkLKQTHo6CvfwsG5Hkhix3mnLIJ7fx6jJaDlWJHLZBMZKOLZTYh08mDQxaLjq42I6faYCmp2lryOao1c5olfqDzh_bCWQaVUCFTVG/s1600/Drzewoary.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter: false&quot;&gt;Node&amp;lt;String&amp;gt; korzen = new Node&amp;lt;String&amp;gt;(null, &quot;*&quot;);
Node&amp;lt;String&amp;gt; n1 = korzen.addChild(&quot;+&quot;);
Node&amp;lt;String&amp;gt; n2 = korzen.addChild(&quot;-&quot;);     
     
n1.addChild(&quot;7&quot;);
n1.addChild(&quot;3&quot;);     
      
n2.addChild(&quot;6&quot;);      
n2.addChild(&quot;2&quot;);            
     
Tree&amp;lt;String&amp;gt; drzewo = new Tree&amp;lt;String&amp;gt;(korzen); 
&lt;/pre&gt;&lt;br /&gt;
to przejście przez wszystkie jego elementy wyglądałoby w następujący sposób:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;preorder: * + 7 3 - 6 2 
postorder: 7 3 + 6 2 - * 
Inorder: 7 + 3 * 6 - 2 
&lt;/pre&gt;&lt;br /&gt;
Jak łatwo zauważyć dla drzew zawierających wyrażenia arytmetyczne poszczególne metody odwiedzania węzłów odpowiadają odpowiedniej notacji. Preorder to notacja prefiksowa (notacja polska), postorder to notacja postfiksowa (odwrotna notacja polska), a inorder to zwykła notacja infiksowa. &lt;br /&gt;
&lt;br /&gt;
Poniżej trzy metody rekurencyjne realizujące poszczególne sposoby trawersowania drzewa (umieszczamy je w ciele klasy Tree&amp;lt;T&amp;gt; z poprzedniego postu).&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false&quot;&gt;/**
 * Metody trawersowania drzewa
 * @author kodatnik.blogspot.com 
 */ 

// metoda wyświetla węzły w kolejności preorder
public void preOrder(Node&amp;lt;T&amp;gt; n) {
 //najpierw korzeń
 System.out.print(n + &quot; &quot;);        
 // potem lewe skrajne poddrzewo, a później prawe
 Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
 while (temp != null) {
  preOrder(temp);
  temp = temp.getRightSibling();
 }
}  
  
// metoda wyświetla węzły w kolejności postorder
public void postOrder(Node&amp;lt;T&amp;gt; n) {
 // najpierw lewe skrajne poddrzewo, potem prawe
 Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
 while (temp != null) {
  postOrder(temp);
  temp = temp.getRightSibling();
 }
 // na końcu korzeń
 System.out.print(n + &quot; &quot;);
}  

// metoda wyświetla węzły w kolejności inorder
public void inOrder(Node&amp;lt;T&amp;gt; n) {
 if (n.isLeaf())
  System.out.print(n + &quot; &quot;);
 else {
  // najpierw lewe skrajne poddrzewo
  Node&amp;lt;T&amp;gt; temp = n.getLeftMostChild();
  inOrder(temp);
  // potem korzeń
  System.out.print(n + &quot; &quot;);  
  // potem prawe
  temp = temp.getRightSibling();   
  while (temp != null) {
   inOrder(temp);
   temp = temp.getRightSibling();
  }
 } 
}  
&lt;/pre&gt;Mając już opanowane sposoby &quot;chodzenia&quot; po drzewie możemy zastanowić się nad prezentacją jego struktury na ekranie. To wszystko już w następnym poście.</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/7493435889401494679/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/03/trawersowanie-drzewa-metody-preorder.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/7493435889401494679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/7493435889401494679'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/03/trawersowanie-drzewa-metody-preorder.html' title='Trawersowanie drzewa - metody preorder, postoder i inorder'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiSAgVUylYlCT1wcPoQ2XJtwWJ_TDy_7QpRZeL6o-r1ocH33uGrC6HYtSu9cFKQrRI28Rt5R4eblXb5KapBlcQxf_86WBkWEGjrn0qU4ms-Ov9fe6PFWaBSpX6VdZO36AqhM7dk9mTnTU/s72-c/Drzewo1+(1).jpg" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-350001536505682937</id><published>2010-03-17T02:37:00.000+01:00</published><updated>2010-03-17T02:37:05.632+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Zamiana liczb rzymskich na arabskie i na odwrót</title><content type='html'>Konwersja między różnymi formatami zapisu liczb zawsze jest dobrą wprawką programistyczną. Przyjrzyjmy się dwóm systemom zapisu. System arabski wykorzystuje cyfry od 0 do 9 i jest stosowany powszechnie na całym świecie. System rzymski opiera się na 7 znakach literowych (I - 1, V - 5, X - 10, L - 50, C - 100, D - 500, M - 1000). Poszczególne wartości są tworzone za pomocą odpowiednich zestawień znaków. Np. MCMXCIV odpowiada liczbie 1994. W jaki sposób prawidłowo odczytać wartość, znaki jednakowe są dodawane (np. XX - 10+10 = 20), znaki mniejsze stojące przed większymi są od nich odejmowane (np. IV - 5-1 = 4), znaki mniejsze stojące za większymi są do nich dodawane (np. VI - 5+1 = 6).&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Dodatkowo jest kilka założeń, które powinny być przestrzegane: &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;nie można znaku stanowiącego jednostki (I), dziesiątki(X) lub setki(C) (nie dotyczy to znaku tysięcy - M) użyć więcej niż trzy razy, np. IIII jest niedozwolone,&lt;/li&gt;
&lt;li&gt;znaki, które nie są symbolami jednostek (I), dziesiątek(X), setek (C), tysięcy (M) mogą występować tylko pojedynczo, np. LL jest niedozwolone,&lt;/li&gt;
&lt;li&gt;znaki które można odejmować od znaków większych to tylko I, X, C, ale tylko jeśli znak większy nie jest więcej niż 10 razy większy, np. IC jest niedozwolone.&lt;/li&gt;
&lt;/ul&gt;Zasady wyglądają strasznie ;) Poniżej algorytm, który dokona zamiany podanej przez użytkownika liczby w systemie rzymskim na system arabski i odwrotnie. W dwóch tablicach zapisane zostały podstawowe wartości w systemie rzymskim (7 podstawowych znaków plus dla uproszczenia algorytmu kilka wyjątków) oraz odpowiadające im wartości systemu arabskiego. Dodatkowo program sprawdza poprawność podawanych liczb. Dla systemu arabskiego jest sprawdzany zakres liczby (tylko liczby od 1 do 3999), a dla rzymskiego jej poprawność. Dla pominięcia wszelkich zawiłości związanych ze sprawdzeniem czy dana liczba rzymska została poprawnie podana przez użytkownika, metoda &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;czyPoprawnaRzymska()&lt;/span&gt; dokonuje zamiany podanej liczby rzymskiej na arabską, a później dla uzyskanego wyniku z powrotem na rzymską. Jeśli wynik zgadza się z tym który podał użytkownik, program uznaje zapis za poprawny.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;// wykorzystujemy klasę Scanner z pakietu java.util
import java.util.*;

/**
 * Zamiana liczb zapisanych w systemie rzymskim i arabskim
 * @author kodatnik.blogspot.com
 */
public class RzymskieArabskie {

 // tablica liczb rzymskich (podstawowe + dozwolone)
 private static String[] rzymskie = {&quot;M&quot;, &quot;CM&quot;, &quot;D&quot;, &quot;CD&quot;, &quot;C&quot;,&quot;XC&quot;, &quot;L&quot;, &quot;XL&quot;, &quot;X&quot;, &quot;IX&quot;, &quot;V&quot;, &quot;IV&quot;, &quot;I&quot;};
 // tablica odpowiadających im liczb arabskich
 private static int[] arabskie   = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};

 // metoda sprawdza czy podana liczba rzymska jest poprawna
 public static boolean czyPoprawnaRzymska(String liczba) {
  
  // konwertujemy liczbę na duże znaki (takie mamy w tablicy)
  liczba = liczba.toUpperCase();  
  
  // jeśli liczba jest pusta zwracamy fałsz
  if (liczba.length() == 0) return false;
  // jeśli wartość tego co dostajemy od użytkownika z tym co 
  // sami obliczymy (zamiana na arabską i ponowna na rzymską) jest różna zwracamy fałsz 
  if (!liczba.equals(naRzymska(naArabska(liczba)))) return false;
  // w każdym innym przypadku zwracamy prawdę
  return true;
 }

 // metoda sprawdza czy podana liczba arabska jest poprawna
 public static boolean czyPoprawnaArabska(int liczba) {
  // sprawdzamy zakres
  if (liczba &amp;lt; 1 || liczba &amp;gt; 3999) return false;  
  // jeśli w porządku zwracamy prawdę
  else return true;
 }
 
 // metoda zamienia liczbę arabską na rzymską
 public static String naRzymska(int liczba) {
 
  // zmienna wyjście będzie zawierała liczbę rzymską
  String wyjscie = &quot;&quot;;
  
  // sprawdzamy w pętli naszą liczbę z poszczególnymi
  // elementami tablicy liczb arabskich
  for (int i = 0; i &amp;lt; arabskie.length; i++) {
   // dopóki liczba jest większa
   while (liczba &amp;gt;= arabskie[i]) {
    // tworzymy liczbę rzymską dodając odpowiedną wartość z tablicy rzymskie
    wyjscie += rzymskie[i];
    // zmniejszamy liczbę arabską o odpowiednią wartość
    liczba -= arabskie[i];
   }
  }
  // zwracamy liczbę rzymską (łańcuch tekstowy)
  return wyjscie;
}
 
 // meoda zamienia liczbę rzymską na arabską
 public static int naArabska(String liczba) {
  
  // konwertujemy liczbę na duże znaki (takie mamy w tablicy)
  liczba = liczba.toUpperCase();
      
  // zmienna wyjście będzie zawierała liczbę arabską
  int wyjscie = 0;
 
  // zmienna index umożliwi nam przemieszczanie się po liczbie rzymskiej
  int index = 0;      
      
  // sprawdzamy w pętli naszą liczbę z poszczególnymi
  // elementami tablicy liczb rzymskich
  for (int i = 0; i &amp;lt; rzymskie.length; i++) {
   // dopóki liczba zaczyna się z odpowiednią liczbą rzymską
   while (liczba.startsWith(rzymskie[i], index)) {
    // tworzymy liczbę arabską dodając odpowiedną wartość z tablicy arabskie
    wyjscie += arabskie[i];
    // przechodzimy do następnej pozycji w liczbie rzymskiej
    index += rzymskie[i].length();
   }
  }  
  // zwracamy liczbę arabską 
  return wyjscie;
 } 
  
   
 public static void main (String[] args) {
     
  Scanner wejscie = new Scanner(System.in);
     
  System.out.print (&quot;Podaj liczbę z zakresu (1-3999) w systemie rzymskim: &quot;);
     
  // pobieramy od użytkownika łańcuch tekstowy (liczbę rzymską)
  String rzymska = wejscie.nextLine();
     
  // sprawdzamy poprawność i wyświetlamy wynik konwersji lub komunikat o błędzie
  if(czyPoprawnaRzymska(rzymska)) {
   System.out.println (&quot;Liczba zapisana w systemie arabskim: &quot; + naArabska(rzymska));
  } else {
   System.out.println (&quot;Niepoprawna liczba.&quot;);      
  }
     
  System.out.print (&quot;Podaj liczbę z zakresu (1-3999) w systemie arabskim: &quot;);
  
  // pobieramy od użytkownika liczbę (liczbę arabska)     
  int arabska = wejscie.nextInt();
     
  // sprawdzamy poprawność i wyświetlamy wynik konwersji lub komunikat o błędzie     
  if(czyPoprawnaArabska(arabska)) {
   System.out.println (&quot;Liczba zapisana w systemie rzymskim: &quot; + naRzymska(arabska));
  } else {
   System.out.println (&quot;Niepoprawna liczba.&quot;);
  }
 }
}
&lt;/pre&gt;Przykłady uruchomień aplikacji: &lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Podaj liczbę z zakresu (1-3999) w systemie rzymskim: MCMXCIV
Liczba zapisana w systemie arabskim: 1994
Podaj liczbę z zakresu (1-3999) w systemie arabskim: 666
Liczba zapisana w systemie rzymskim: DCLXVI
&lt;/pre&gt;&lt;pre class=&quot;console&quot;&gt;Podaj liczbę z zakresu (1-3999) w systemie rzymskim: ICVI
Niepoprawna liczba.
Podaj liczbę z zakresu (1-3999) w systemie arabskim: 978
Liczba zapisana w systemie rzymskim: CMLXXVIII
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/350001536505682937/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/03/zamiana-liczb-rzymskich-na-arabskie-i.html#comment-form' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/350001536505682937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/350001536505682937'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/03/zamiana-liczb-rzymskich-na-arabskie-i.html' title='Zamiana liczb rzymskich na arabskie i na odwrót'/><author><name>Devon</name><uri>http://www.blogger.com/profile/04678973948963129159</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBc9MXCDJ6MGJSH8wj3yOa7rMjmFOP7jSQ6zKGG4PerGGJP_e28hSg6-Ap6Hatx3mJO6pByPJx49Snq-iR5gJlzNzF1j1Mxet__SMaqUjds_yjoAPoENT0Uo6P7ekMTf0/s220/test1.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-1905589028846799823</id><published>2010-02-24T21:09:00.004+01:00</published><updated>2010-02-27T17:40:02.203+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Struktury Danych"/><title type='text'>Drzewo - ogólna implementacja</title><content type='html'>Struktury drzewiaste są dość często wykorzystywane w informatyce. Java nie posiada żadnej gotowej klasy do obsługi drzew. Dzisiaj prosta implementacja dowolnego drzewa ogólnego (każdy element drzewa może posiadać nieograniczoną liczbę potomków). Samo drzewo to struktura elementów, węzłów (&lt;i&gt;ang. node&lt;/i&gt;) pozostających w zależności hierarchicznej tak jak na poniższym diagramie.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5GX5u82Yan_LGw0gu55vxj6SbFYW2QTbmwyyCfpeSSG_mRV3sLnBNN-3gdgfZr0BhgGQaZ6T8XEjMNeJDLUg3dzsuZObwGl3jgY4wylzwSed4sQoav-ys1_Z6neq63n1g89i-Zyn0BcI/s1600-h/Drzewo1%20(1).jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5GX5u82Yan_LGw0gu55vxj6SbFYW2QTbmwyyCfpeSSG_mRV3sLnBNN-3gdgfZr0BhgGQaZ6T8XEjMNeJDLUg3dzsuZObwGl3jgY4wylzwSed4sQoav-ys1_Z6neq63n1g89i-Zyn0BcI/s400/Drzewo1%20(1).jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Szczególnym elementem drzewa jest &lt;b&gt;korzeń&lt;/b&gt; (&lt;i&gt;ang. root&lt;/i&gt;) czyli element nie posiadający rodzica (elementu nadrzędnego). Dodatkowe pojęcia związane z drzewem to &lt;b&gt;liść &lt;/b&gt;(element nie posiadający dzieci), &lt;b&gt;stopień węzła&lt;/b&gt; (liczba potomków węzła), &lt;b&gt;elementy siostrzane&lt;/b&gt; węzła (elementy mające tego samego rodzica co dany węzeł), &lt;b&gt;wysokość węzła&lt;/b&gt; (długość najdłuższej ścieżki od danego węzła do liścia),  &lt;b&gt;poziom węzła&lt;/b&gt; (długość ścieżki od korzenia do danego węzła). Patrząc na powyższy diagram możemy ustalić, że każdy węzeł:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;przechowuje jakieś dane,&lt;/li&gt;
&lt;li&gt;posiada referencję do węzła będącego jego rodzicem (w przypadku korzenia będzie to wartość &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;null&lt;/span&gt;),&lt;/li&gt;
&lt;li&gt;ma listę swoich dzieci (czyli listę referencji do węzłów będących jego potomkami).&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Wykorzystując typy generyczne (pisałem o nich wcześniej: &lt;a href=&quot;http://kodatnik.blogspot.com/2009/12/typy-generyczne.html&quot;&gt;Typy generyczne&lt;/a&gt;) oraz listę powiązaną (też wspominałem: &lt;a href=&quot;http://kodatnik.blogspot.com/2009/12/klasa-linkedlist-przykad-zastosowania.html&quot;&gt;LinkedList przykład wykorzystania&lt;/a&gt;) jesteśmy w stanie stosunkowo łatwo zbudować klasę odpowiadającą pojedynczemu węzłowi:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;class Node&amp;lt;T&amp;gt; {
 // dane przechowywane w węźle
 private T data; 
 // referencja do rodzica
 private Node&amp;lt;T&amp;gt; parent; 
 // lista dzieci
 private LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; children; 
}
&lt;/pre&gt;&lt;br /&gt;
Dodajemy potrzebne konstruktory, domyślny (węzeł bez rodzica i z pustą listą dzieci), jednoparametrowy (węzeł z ustawionym rodzicem) i dwuparametrowy (węzeł z rodzicem i danymi):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public Node() {
 // brak referencji do rodzica
 parent = null; 
 // tworzymy pustą listę dzieci
 children = new LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt;(); 
}

public Node(Node&amp;lt;T&amp;gt; parent) {
 // wywołujemy konstruktor domyślny
 this(); 
 // ustawiamy rodzica
 this.parent = parent; 
} 

public Node(Node&amp;lt;T&amp;gt; parent, T data) {
 // wywołujemy konstruktor jednoparametrowy
 this(parent); 
 // ustawiamy dane
 this.data = data; 
} 
&lt;/pre&gt;&lt;br /&gt;
Dodajmy również do klasy podstawowe metody dostępowe i modyfikujące dla danych i rodzica:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public Node&amp;lt;T&amp;gt; getParent(){
 // zwracamy referencję do rodzica
 return parent; 
}

public void setParent(Node&amp;lt;T&amp;gt; parent) {
 // ustawiamy rodzica
 this.parent = parent; 
}

public T getData() {
 // zwracamy przechowywane dane
 return data; 
}

public void setData(T data) {
 // ustawiamy dane
 this.data = data; 
} 
&lt;/pre&gt;&lt;br /&gt;
Stopień węzła, czyli liczbę jego potomków możemy łatwo określić zwracając rozmiar listy przechowującej referencję dzieci.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public int getDegree() {
 // zwracamy rozmiar listy przechowującej potomków węzła
 return children.size();
}
&lt;/pre&gt;&lt;br /&gt;
Tak samo sprawdzenie czy dany węzeł jest liściem (&lt;i&gt;ang. leaf&lt;/i&gt;). Jeśli jego lista dzieci jest pusta, jest liściem.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public boolean isLeaf(){
 // jeśli lista dzieci jest pusta zwracamy true (węzeł jest liściem)
 return children.isEmpty();
}
&lt;/pre&gt;&lt;br /&gt;
Do węzła możemy dodawać dzieci. Jeden sposób to dodanie do listy potomków referencji węzła przekazanego jako parametr. Musimy pamiętać o ustawieniu w &quot;dziecku&quot; naszego &quot;ojcostwa&quot; (węzeł będący na liście naszych dzieci musi wiedzieć, że jesteśmy jego rodzicem).&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public Node&amp;lt;T&amp;gt; addChild(Node&amp;lt;T&amp;gt; child) {
 // ustawiamy w dziecku rodzica (wskazujemy na nas)
 child.setParent(this);
 // dodajemy dziecko do listy naszych dzieci
 children.add(child);
 // zwracamy dziecko
 return child;
}
&lt;/pre&gt;&lt;br /&gt;
Drugi sposób wygodniejszy podczas tworzenia struktury drzewa to dodatnie do węzła dziecka z określonymi danymi. Nasza metoda utworzy na podstawie przekazanych danych nowy węzeł oraz doda go do listy jego dzieci.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public Node&amp;lt;T&amp;gt; addChild(T data) {
 //tworzymy nowy węzeł (ustawiamy od razu rodzica i dane)
 Node&amp;lt;T&amp;gt; child = new Node&amp;lt;T&amp;gt;(this, data); 
 // dopisujemy węzeł do listy naszych dzieci
 children.add(child);
 // zwracamy dziecko
 return child;
}
&lt;/pre&gt;&lt;br /&gt;
Dodatkowe operacje związane z dziećmi to pobranie i-tego dziecka z listy, usunięcia konkretnego dziecka, oraz usunięcie wszystkich dzieci węzła. Wykorzystamy metody dostępne w klasie &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;LinkedList&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public Node&amp;lt;T&amp;gt; getChild(int i){
 // zwracamy referencję do i-tego dziecka (metoda get(int) z klasy LinkedList)
 return children.get(i);
}

public Node&amp;lt;T&amp;gt; removeChild(int i) {
 // usuwamy i-te dziecko (metoda remove(int) z klasy LinkedList)
 return children.remove(i);
}

public void removeChildren() {
 // usuwamy wszystkie nasze dzieci, czyścimy listę(metoda clear() z klasy LinkedList)
 children.clear();
}
&lt;/pre&gt;&lt;br /&gt;
Możemy również napisać metodę dostępową zwracającą listę dzieci węzła.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; getChildren() {
 // zwracamy referencję do listy naszych dzieci
 return children;
}
&lt;/pre&gt;&lt;br /&gt;
Pozostają nam jeszcze dwie metody, które przydadzą się do implementacji sposobów trawersowania drzewa. Pierwsza z nich zwróci nam najbardziej wysunięte w lewo dziecko węzła (czyli pierwszego potomka z listy o ile tylko taki istnieje).&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public Node&amp;lt;T&amp;gt; getLeftMostChild() {
 // jeśli nie mamy dzieci zwrócimy null
 if (children.isEmpty()) return null;
 // w przciwnym wypadku pierwsze dziecko z listy naszych dzieci
 return children.get(0);
}
&lt;/pre&gt;&lt;br /&gt;
Druga zwraca prawy element siostrzany (o ile istnieje) węzła.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public Node&amp;lt;T&amp;gt; getRightSibling() {
 // jeśli nie jesteśmy korzeniem
 if (parent != null) {
  // pobieramy listę dzieci naszego rodzica
  LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; parentsChildren = parent.getChildren();
  // szukamy się na tej liście
  int pos = parentsChildren.indexOf(this);
  // sprawdzamy czy są jeszcze jakieś dzieci za nami
  if (pos &amp;lt; (parentsChildren.size()-1))
   // jesli tak zwracamy kolejne dziecko
   return parentsChildren.get(pos+1);
 }
 // zwracamy null jak węzeł jest korzeniem, albo nie ma już elementu siostrzanego po prawej
 return null;
}
&lt;/pre&gt;&lt;br /&gt;
Ostatnią częścią naszej klasy będzie przesłonięcie metody &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;toString()&lt;/span&gt;. Zwrócimy po prostu dane przechowywane w węźle.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public String toString() {
 // zwracamy dane w formie łańcucha tekstowego
 return data.toString();
}
&lt;/pre&gt;&lt;br /&gt;
Poniżej cała gotowa klasa &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Node&amp;lt;T&amp;gt;&lt;/span&gt; opisująca węzeł naszego drzewa (komentarze zostały pominięte).&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java;&quot;&gt;/**
 * Klasa Node&amp;lt;T&amp;gt; - węzeł drzewa
 * @author kodatnik.blogspot.com
 */
class Node&amp;lt;T&amp;gt; {
 private T data;
 private Node&amp;lt;T&amp;gt; parent;
 private LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; children;

 public Node() {
  parent = null;
  children = new LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt;();
 }

 public Node(Node&amp;lt;T&amp;gt; parent) {
  this();
  this.parent = parent;
 } 

 public Node(Node&amp;lt;T&amp;gt; parent, T data) {
  this(parent);
  this.data = data;
 } 

 public Node&amp;lt;T&amp;gt; getParent(){
  return parent;
 }

 public void setParent(Node&amp;lt;T&amp;gt; parent) {
  this.parent = parent;
 }

 public T getData() {
  return data;
 }

 public void setData(T data) {
  this.data = data;
 } 

 public int getDegree() {
  return children.size();
 }

 public boolean isLeaf(){
  return children.isEmpty();
 }

 public Node&amp;lt;T&amp;gt; addChild(Node&amp;lt;T&amp;gt; child) {
  child.setParent(this);
  children.add(child);
  return child;
 }

 public Node&amp;lt;T&amp;gt; addChild(T data) {
  Node&amp;lt;T&amp;gt; child = new Node&amp;lt;T&amp;gt;(this, data); 
  children.add(child);
  return child;
 }

 public Node&amp;lt;T&amp;gt; getChild(int i){
  return children.get(i);
 }

 public Node&amp;lt;T&amp;gt; removeChild(int i) {
  return children.remove(i);
 }

 public void removeChildren() {
  children.clear();
 }

 public LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; getChildren() {
  return children;
 }

 public Node&amp;lt;T&amp;gt; getLeftMostChild() {
  if (children.isEmpty()) return null;
  return children.get(0);
 }

 public Node&amp;lt;T&amp;gt; getRightSibling() {
  if (parent != null) {
   LinkedList&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; parentsChildren = parent.getChildren();
   int pos = parentsChildren.indexOf(this);
   if (pos &amp;lt; (parentsChildren.size()-1))
    return parentsChildren.get(pos+1);
  }
  return null;
 }

 public String toString() {
  return data.toString();
 }
}
&lt;/pre&gt;&lt;br /&gt;
Ostatnią czynnością będzie zbudowanie konkretnego drzewa. Sam proces sprowadza się do utworzenia odpowiednich węzłów, połączenie ich w strukturę hierarchiczną oraz wskazania węzła będącego korzeniem. Nasza klasa będzie posiadała tylko jedno pole, referencję do węzła będącego korzeniem. Dwa konstruktory, domyślny puste drzewo i jednoparametrowy ustawiający referencję do korzenia.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java;&quot;&gt;/**
 * Klasa Tree&amp;lt;T&amp;gt; - drzewo
 * @author kodatnik.blogspot.com
 */
class Tree&amp;lt;T&amp;gt; {
 // referencja do węzła będącego korzeniem
 private Node&amp;lt;T&amp;gt; root;

 public Tree() {
  // brak korzenia
  root = null;
 }

 public Tree(Node&amp;lt;T&amp;gt; root) {
  // ustawiamy korzeń
  this.root = root;
 } 
}
&lt;/pre&gt;&lt;br /&gt;
Wykorzystajmy gotowe klasy &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Node&amp;lt;T&amp;gt;&lt;/span&gt; oraz &lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Tree&amp;lt;T&amp;gt;&lt;/span&gt; &amp;nbsp;do budowy drzewa z diagramu.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java;&quot;&gt;public class NaszeDrzewo {
 public static void main(String args[]) {

  // tworzymy węzeł będący korzeniem
  Node&amp;lt;String&amp;gt; korzen = new Node&amp;lt;String&amp;gt;(null, &quot;Adam&quot;);

  // dodajemy do niego kolejne węzły
  Node&amp;lt;String&amp;gt; n1 = korzen.addChild(&quot;Ewa&quot;);
  Node&amp;lt;String&amp;gt; n2 = korzen.addChild(&quot;Jarek&quot;);     
  Node&amp;lt;String&amp;gt; n3 = korzen.addChild(&quot;Marta&quot;);      
  
  n1.addChild(&quot;Jurek&quot;);
  n1.addChild(&quot;Max&quot;);     
  n1.addChild(&quot;Iza&quot;);            

  n2.addChild(&quot;Iwona&quot;);      

  n3.addChild(&quot;Rafał&quot;);
  n3.addChild(&quot;Ola&quot;);      

  // tworzymy drzewo i wskazujemy, który węzeł jest korzeniem
  Tree&amp;lt;String&amp;gt; drzewo = new Tree&amp;lt;String&amp;gt;(korzen);
 }
}
&lt;/pre&gt;&lt;br /&gt;
Zbudowaliśmy strukturę drzewa. Pozostaje wyświetlenie naszego drzewa na ekranie oraz przedstawienie sposobów poruszania się po drzewie. To wszystko w następnej części...</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/1905589028846799823/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/02/drzewo-ogolna-implementacja.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/1905589028846799823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/1905589028846799823'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/02/drzewo-ogolna-implementacja.html' title='Drzewo - ogólna implementacja'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5GX5u82Yan_LGw0gu55vxj6SbFYW2QTbmwyyCfpeSSG_mRV3sLnBNN-3gdgfZr0BhgGQaZ6T8XEjMNeJDLUg3dzsuZObwGl3jgY4wylzwSed4sQoav-ys1_Z6neq63n1g89i-Zyn0BcI/s72-c/Drzewo1%20(1).jpg" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-4973059801281116572</id><published>2010-01-22T14:20:00.000+01:00</published><updated>2010-01-22T14:20:55.099+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Podstawy"/><title type='text'>Metody o zmiennej liczbie argumentów</title><content type='html'>Po poprzednich wpisach dzisiaj coś lekkiego :) Poznamy metody, które mogą mieć zmienną liczbę argumentów (&lt;i&gt;ang. varargs&lt;/i&gt;). Przed Javą 1.5 (inaczej zwaną 5.0) jedyną możliwością przesłania do metody zmiennej liczby argumentów było wykorzystanie tablic, w Javie 5.0 wprowadzono nowy sposób zapisu argumentu: &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Typ...&lt;/span&gt; Przykładowy nagłówek metody o zmiennej liczbie argumentów:&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public static void metoda(String napis, String... napisy);
&lt;/pre&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Argument o zmiennej liczbie danych musi występować zawsze jako ostatni na liście argumentów metody. Trzy kropki oznaczają, że argument może zostać przekazany jako tablica albo lista wartości oddzielonych przecinkami. Jeżeli wykorzystany wartości oddzielone od siebie przecinkami, to kompilator Javy automatycznie skonwertuje je do postaci tablicy i prześle do metody. Dostęp do poszczególnych argumentów jest możliwy za pomocą na przykład pętli iteracyjnej czy też zwykłego dostępu do elementów tablicy (np. rozmiar takiej tablicy - pole &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;length&lt;/span&gt;). Poniżej przykładowa aplikacja zawierająca metodę wykorzystującą zmienną liczbę argumentów.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
 * Zmienna liczba argumentów w metodzie
 * @author kodatnik.blogspot.com
 */
public class ZmiennaLiczbaArgumentow {
 
 // ostatni argument metody może mieć zmienną liczbę danych
 public static void wyswietl(String napis, String... napisy) {
  
  // wyświetlamy pierwszy argument
  System.out.println (napis);

  // wyświetlamy liczbę argumentów przekazanych jako drugi parametr
  System.out.println (&quot;Liczba zmiennych argumentów: &quot; + napisy.length);

  // w pętli iteracyjnej wyświetlamy poszczególne elementy
  for (String lancuch : napisy) {
   System.out.println (lancuch);
  }
 }
 
 public static void main (String[] args) {
  // tworzymy tablicę łańcuchów znaków
  String[] lancuchy = {&quot;Kasia&quot;, &quot;Romek&quot;, &quot;Andrzej&quot;, &quot;Ola&quot;, &quot;Tadeusz&quot;};
  
  // wywołujemy metodę wyświetl z 4 argumentami
  wyswietl(&quot;Koleżanki&quot;, &quot;Ania&quot;, &quot;Ola&quot;, &quot;Iwona&quot;);
  // wywołujemy metodę wyświetl z 2 argumentami
  wyswietl(&quot;Kolega&quot;, &quot;Wiktor&quot;);
  // wywołujemy metodę wyświetl z 5 argumentami
  wyswietl(&quot;Znajomi&quot;, &quot;Ania&quot;, &quot;Ola&quot;, &quot;Iwona&quot;, &quot;Leszek&quot;);
  
  // wywołujemy metodę wyświetl z 2 argumentami
  // drugi argument jest tablicą z łańcuchami tekstowymi
  wyswietl(&quot;Pracownicy&quot;, lancuchy);
 }
}
&lt;/pre&gt;Uruchomiona aplikacja:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Koleżanki
Liczba zmiennych argumentów: 3
Ania
Ola
Iwona
Kolega
Liczba zmiennych argumentów: 1
Wiktor
Znajomi
Liczba zmiennych argumentów: 4
Ania
Ola
Iwona
Leszek
Pracownicy
Liczba zmiennych argumentów: 5
Kasia
Romek
Andrzej
Ola
Tadeusz
&lt;/pre&gt;Musimy pamiętać, że zamiana przez kompilator argumentów na tablicę pozbawia nas możliwości przeciążenia powyższej metody na taką:&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public static void wyswietl(String napis, String[] napisy);
&lt;/pre&gt;A co się stanie jeśli zdefiniujemy naszą metodę w ten sposób:&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public static void wyswietl(String napis1, String napis2);
&lt;/pre&gt;Która wersja metody zostanie wywołana dla takiego kodu?&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;wyswietl(&quot;Marek&quot;, &quot;Wiktor&quot;);
&lt;/pre&gt;Metoda &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;wyswietl(String, String)&lt;/span&gt; jest bardziej wyspecjalizowana (inaczej mówiąc szczegółowa), więc ona zostanie wywołana domyślnie.</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/4973059801281116572/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/01/metody-o-zmiennej-liczbie-argumentow.html#comment-form' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/4973059801281116572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/4973059801281116572'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/01/metody-o-zmiennej-liczbie-argumentow.html' title='Metody o zmiennej liczbie argumentów'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-3593139380417847243</id><published>2010-01-21T02:33:00.002+01:00</published><updated>2010-01-21T02:35:07.013+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Struktury Danych"/><title type='text'>Przeglądamy kolekcję - interfejs Iterable&amp;lt;T&amp;gt;</title><content type='html'>Od Javy 5.0 wprowadzono pętlę iteracyjną (znaną w innych językach programowania jako pętla &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;foreach&lt;/span&gt;) umożliwiającą przeglądnięcie wszystkich elementów należących do danej kolekcji. Pętla ta może być stosowana z tablicami oraz wszystkim klasami, które implementują interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Iterable&amp;lt;T&amp;gt;&lt;/span&gt;.&lt;br /&gt;
Ogólny format pętli iteracyjnej:&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;for (T wartosc : kolekcja) {
 // dla każdego elementu z kolekcji dostępnego 
 // pod zmienną wartosc typu T
 // gdzie T jest typem generycznym
}
&lt;/pre&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Powyższy zapis jest równoznaczny z uzyskaniem dla danej kolekcji iteratora (obiekt klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Iterator&amp;lt;T&amp;gt;&lt;/span&gt;) oraz wykorzystania metod, które on udostępnia (np. &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;hasNext()&lt;/span&gt;,&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt; next()&lt;/span&gt;).&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;Iterator&amp;lt;T&amp;gt; iterator = kolekcja.iterator();

while(iterator.hasNext()) {
 T wartosc = iterator.next();
 
 // dla każdego elementu z kolekcji dostępnego 
 // pod zmienną wartosc typu T
 // gdzie T jest typem generycznym
}
&lt;/pre&gt;Jak utworzyć klasę, która będzie umożliwiała nam przejście przez wszystkie elementy za pomocą czy to pętli iteracyjnej for czy też &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;while&lt;/span&gt;? Odpowiedź jest stosunkowo prosta. Musimy zaimplementować w naszej klasie interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Iterable&amp;lt;T&amp;gt;&lt;/span&gt; (&quot;powiadamia&quot; on o tym, że naszą klasę można przeglądać). Interfejs ten posiada tylko jedną metodę: &lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public Iterator&amp;lt;T&amp;gt; iterator();
&lt;/pre&gt;zwracającą referencję do obiektu klasy implementującej interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Iterator&amp;lt;T&amp;gt;&lt;/span&gt;. Interfejs ten posiada trzy metody:&lt;br /&gt;
&lt;pre class=&quot;brush: java; gutter: false;&quot;&gt;public boolean hasNext(); // sprawdza czy są jeszcze elementy w kolekcji
public T next();          // zwraca kolejny element
public void remove();     // usuwa kolejny element
&lt;/pre&gt;Zazwyczaj implementuje się w pełni tylko dwie pierwsze metody. Trzecią zostawia się pustą (ma ona bezpośredni wpływ na zawartość kolekcji i nie ma sensu w ten sposób usuwać elementów, od tego powinny być metody dostępne w samej kolekcji). Zobaczmy prosty przykład wykorzystania interfejsu &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Iterable&amp;lt;T&amp;gt;&lt;/span&gt; na podstawie klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Lista&amp;lt;T&amp;gt;&lt;/span&gt; odzwierciedlającej listę jednostronną jednokierunkową. Najpierw klasa pojedynczego węzła/elementu listy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Wezel&amp;lt;T&amp;gt;&lt;/span&gt;.&lt;br /&gt;
&lt;pre class=&quot;brush: java;&quot;&gt;/**
 * Węzeł - element listy 
 * @author kodatnik.blogspot.com
 */
class Wezel&amp;lt;T&amp;gt; {
 // pole przechowujące wartość znajdującą się w węźle
 private T obiekt;
 // referencja do następnego elementu listy
 private Wezel&amp;lt;T&amp;gt; nastepny;
 
 // konstruktor domyślny;
 public Wezel() {
  // wywołanie konstruktora dwuparametrowego)
  this(null, null);
 }
 
 // konstruktor dwuparametrowy
 // wartość oraz referencja do następnego węzła
 public Wezel(T obiekt, Wezel&amp;lt;T&amp;gt; nastepny) {
  this.obiekt = obiekt;
  this.nastepny = nastepny;
 }
  
 // metoda zwraca referencję do następnego węzła
 public Wezel&amp;lt;T&amp;gt; pobierzNastepny() {
  return nastepny;
 }
 
 // metoda zwraca przechowywaną w węźle wartość
 public T pobierzObiekt() {
  return obiekt;
 }
}
&lt;/pre&gt;oraz klasa główna&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt; Lista&amp;lt;T&amp;gt;&lt;/span&gt;:&lt;br /&gt;
&lt;pre class=&quot;brush: java;&quot;&gt;// wykorzystujemy klasę Iterator z pakietu java.util
import java.util.Iterator;

/**
 * Przykład wykorzystania iteratora
 * Lista jednostronna jednokierunkowa
 * @author kodatnik.blogspot.com
 */
class Lista&lt;t&gt; implements Iterable&amp;lt;T&amp;gt; {

 // pole przechowujące referencję do początku listy
 private Wezel&amp;lt;T&amp;gt; poczatek;
 
 // konstruktor bezparametrowy
 public Lista () {
  // ustawiamy początek na null (lista pusta)
  poczatek = null;
 }
 
 // metoda wstawia dane na początek listy
 public void wstawNaPoczatek(T dane) {
  // tworzymy nowy węzeł oraz ustawiamy 
  // zmienną poczatek tak aby go wskazywała
  poczatek = new Wezel&amp;lt;T&amp;gt;(dane, poczatek);
 }
 
 // metoda usuwa element znajdujący się na początku listy
 // oraz zwraca referencję do niego
 public Wezel&amp;lt;T&amp;gt; usunZPoczatku() {
  // zapamiętujemy element z początku listy
  Wezel&amp;lt;T&amp;gt; temp = poczatek;
  // zmieniamy referencje początku listy
  // na następny element (pomijamy pierwszy)
  poczatek = poczatek.pobierzNastepny();
  // zwracamy zapamiętaną referencję
  return temp; 
 }
 
 // metoda zwraca referencję do obiektu klasy
 // implementującej interfejs Iterator&amp;lt;T&amp;gt;
 public Iterator&amp;lt;T&amp;gt; iterator() {
  // tworzymy nowy obiekt wewnętrznej klasy IteratorListy
  // i zwracamy jego referencję
  return new IteratorListy();
 }
 
 // prywatna klasa wewnętrzna implementująca interfejs Iterator&amp;lt;T&amp;gt;
 private class IteratorListy implements Iterator&amp;lt;T&amp;gt; {
  
  // pole przechowujące referencję do pierwszego elementu naszej listy
  private Wezel&amp;lt;T&amp;gt; temp = poczatek;
  
  // metoda zwraca wartość logiczną czy są jeszcze elementy w kolekcji
  public boolean hasNext() {
   return temp != null;
  }
  
  // metoda zwraca wartość elementu przechowywanego w kolejnym węźle
  public T next() {
   // pobieramy wartość (obiekt typu T)
   T obiekt = temp.pobierzObiekt();
   // przechodzimy na następny element listy
   temp = temp.pobierzNastepny();
   // zwracamy wartość
   return obiekt;
  }
  
  // metoda usuwająca element z kolekcji
  public void remove() {
   // ciało metody puste (patrz opis)
  }
 }
}
&lt;/t&gt;&lt;/pre&gt;Zaimplementowaliśmy w klasie interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Iterable&amp;lt;T&amp;gt;&lt;/span&gt; (metoda&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt; &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;iterator()&lt;/span&gt;&lt;/span&gt;) oraz utworzyliśmy wewnętrzną prywatną klasę&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt; &lt;/span&gt;IteratorListy&lt;/span&gt; implementującą interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Iterator&amp;lt;T&amp;gt;&lt;/span&gt;. Sprawdźmy działanie naszej klasy:&lt;br /&gt;
&lt;pre class=&quot;brush: java;&quot;&gt;// wykorzystujemy klasę Iterator z pakietu java.util
import java.util.Iterator;

/**
 * Test listy
 * @author kodatnik.blogspot.com
 */
public class TestIteratora {
  
 public static void main (String[] args) {
 
  // tworzymy pierwszą listę (parametryzujemy typem String)
  Lista&amp;lt;String&amp;gt; listaPierwsza = new Lista&amp;lt;String&amp;gt;();
  
  // dodajemy elementy na początek listy
  listaPierwsza.wstawNaPoczatek(&quot;Adam&quot;);
  listaPierwsza.wstawNaPoczatek(&quot;Marek&quot;);
  listaPierwsza.wstawNaPoczatek(&quot;Kasia&quot;);
  
  // pobieramy iterator z listy
  Iterator&amp;lt;String&amp;gt; iterator = listaPierwsza.iterator();
  
  // dopóki są jeszcze elementy
  while(iterator.hasNext()) {
   // pobieramy je i wyświetlamy je na ekranie
   System.out.println (iterator.next());
  }
  
  // tworzymy drugą listę (parametryzujemy typem Integer)
  Lista&amp;lt;Integer&amp;gt; listaDruga = new Lista&amp;lt;Integer&amp;gt;();
  
  // dodajemy elementy do początek listy
  listaDruga.wstawNaPoczatek(10);
  listaDruga.wstawNaPoczatek(45);
  listaDruga.wstawNaPoczatek(83);
  
  // w pętli iteracyjnej wyświetlamy po kolei wszystkie elementy
  for (Integer wartosc: listaDruga) {
   System.out.println (wartosc);
  }
 }
}
&lt;/pre&gt;Uruchomiona aplikacja:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Kasia
Marek
Adam
83
45
10
&lt;/pre&gt;Kiedy korzystać z iteratora? Wtedy gdy nasza klasa przechowuje większą liczbę takich samych elementów, mówiąc inaczej jest kolekcją jakiś elementów. Implementacja interfejsu &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Iterable&amp;lt;T&amp;gt;&lt;/span&gt; znacznie uprości obsługę takiej klasy.</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/3593139380417847243/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/01/przegladamy-kolekcje-interfejs-iterable.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/3593139380417847243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/3593139380417847243'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/01/przegladamy-kolekcje-interfejs-iterable.html' title='Przeglądamy kolekcję - interfejs Iterable&amp;lt;T&amp;gt;'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-4399722215806986151</id><published>2010-01-18T14:13:00.004+01:00</published><updated>2010-01-18T15:29:08.390+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Porównujemy obiekty - interfejs Comparable&amp;lt;T&amp;gt;</title><content type='html'>Często chcemy porównać ze sobą dwa obiekty jakiejś klasy. Oczywiście możemy porównać odpowiednie pola klasy i zwrócić wynik, ale.... rozwiązanie idealne polega na zaimplementowaniu w naszej klasie interfejsu &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Comparable&amp;lt;T&amp;gt;&lt;/span&gt;. Dzięki implementacji interfejsu, obiekty powstałe na bazie naszej klasy będą mogły być porównywane ze sobą. Taki sposób porównywania (mówiąc inaczej uporządkowania obiektów) jest wykorzystywany przez Javę np. w kolekcjach. Standardowe klasy np. klasa &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;String&lt;/span&gt; również implementują ten interfejs. Dzięki temu porównując dwa łańcuchy tekstowe wiemy który jest &quot;mniejszy&quot;, a który &quot;większy&quot; (w tym przypadku wykorzystywane jest uporządkowanie alfabetyczne). Wróćmy do interfejsu &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Comparable&amp;lt;T&amp;gt;&lt;/span&gt;, ma on tylko jedną metodę:&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter: false;&quot;&gt;public int compareTo(T obiekt);
&lt;/pre&gt;Metoda &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;compareTo()&lt;/span&gt; może zwracać wartość ujemną, dodatnią albo zero odpowiednio dla obiektów mniejszych, większych lub równych obiektowi przekazanemu jako parametr jej wywołania. Wykorzystajmy interfejs &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Comparable&amp;lt;T&amp;gt;&lt;/span&gt; w przykładowej klasie Student. Nasza klasa będzie posiadać trzy pola: imię, nazwisko oraz numer albumu. Chcemy aby obiekty tworzone na jej podstawie można było porównywać ze sobą według nazwiska. Zastosowanie typów generycznych w interfejsie umożliwia nam swobodniejszy dostęp do obiektów, nie musimy wykonywać rzutowania (więcej o typach generycznych - &lt;a href=&quot;http://kodatnik.blogspot.com/2009/12/typy-generyczne.html&quot;&gt;Typy generyczne&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
* Klasa Student
* Przykład wykorzystania interfejsu Comparable&amp;lt;T&amp;gt;
* @author kodatnik.blogspot.com
*/

// klasa Student implementuje interfejs Comparable&amp;lt;T&amp;gt;
// czyli musi mieć wszystkie metody związane z tym interfejsem
class Student implements Comparable&amp;lt;Student&amp;gt; {
 // pola prywatne
 private String imie;
 private String nazwisko;
 private int nrAlbumu;

 // konstruktor klasy
 public Student(String imie, String nazwisko, int nrAlbumu) {
  this.imie = imie;
  this.nazwisko = nazwisko;
  this.nrAlbumu = nrAlbumu;
 }

 // metoda wymagana przez interfejs Comparable&amp;lt;T&amp;gt;
 public int compareTo(Student obiekt) {
  // zwracamy wynik porównania dwóch pól nazwisko
  // (korzystamy z porównania dostępnego w klasie String)
  return nazwisko.compareTo(obiekt.nazwisko);
 }

 // metoda przesłonięta, zwraca nam tekstową reprezentację obiektu
 public String toString() {
  return (nazwisko + &quot; &quot; + imie + &quot; &quot; + nrAlbumu);
 }
}
&lt;/pre&gt;Poniżej przykład wykorzystania klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Student&lt;/span&gt;. Tworzymy tablicę obiektów, sortujemy ją i wyświetlamy na ekranie.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
* Klasa TestPorownania
* Przykład wykorzystania klasy implementującej interfejs Comparable&amp;lt;T&amp;gt;
* @author kodatnik.blogspot.com
*/

// wykorzystujemy klasę Arrays (obsługa tablic)
import java.util.Arrays;

public class TestPorownania {
 public static void main(String[] args) {
  // tworzymy tablicę studentów o rozmiarze 6
  Student[] studenci = new Student[6];

  // wypełniamy poszczególne elementy tablicy obiektami typu Student
  studenci[0] = new Student(&quot;Marek&quot;, &quot;Zielony&quot;, 4325);
  studenci[1] = new Student(&quot;Jacek&quot;, &quot;Mruczek&quot;, 7453);
  studenci[2] = new Student(&quot;Iwona&quot;, &quot;Lonkis&quot;, 2644);
  studenci[3] = new Student(&quot;Marta&quot;, &quot;Annas&quot;, 1632);
  studenci[4] = new Student(&quot;Adam&quot;, &quot;Mruczek&quot;, 3856);
  studenci[5] = new Student(&quot;Marek&quot;, &quot;Zielony&quot;, 4287);

  // sortujemy tablicę za pomocą metody sort dostępnej w klasie Arrays
  // elementy tablicy zostaną posortowane według metody compareTo()
  Arrays.sort(studenci);

  // wyświetlamy zawartość posortowanej tablicy
  for (Student st: studenci){
   System.out.println(st);
  }
 }
}
&lt;/pre&gt;Uruchomiona aplikacja:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Annas Marta 1632
Lonkis Iwona 2644
Mruczek Jacek 7453
Mruczek Adam 3856
Zielony Marek 4325
Zielony Marek 4287
&lt;/pre&gt;Możemy poszerzyć zakres porównania dla studentów o takich samych nazwiskach. W ich przypadku będziemy porównywać również imiona, a gdy one również będą takie same numery albumu. Poprawiona metoda &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;compareTo()&lt;/span&gt; przedstawia się następująco:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java;gutter: false;&quot;&gt;public int compareTo(Student obiekt) {
 // jeżeli nazwiska są takie same
 if (nazwisko.compareTo(obiekt.nazwisko) == 0)
  // sprawdzamy imiona
  if(imie.compareTo(obiekt.imie) == 0)
   // jeśli są takie same zwracamy różnicę z numerów albumu (dla takich samych będzie to zero)
   return nrAlbumu - obiekt.nrAlbumu;
  else
   // w przeciwnym wypadku zwracamy porównanie imion
   return imie.compareTo(obiekt.imie);
 else
  // w przeciwnym wypadku zwracamy porównanie nazwisk
  return nazwisko.compareTo(obiekt.nazwisko);
}
&lt;/pre&gt;Wynik działania ze zmienioną metodą &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;compareTo()&lt;/span&gt;:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Annas Marta 1632
Lonkis Iwona 2644
Mruczek Adam 3856
Mruczek Jacek 7453
Zielony Marek 4287
Zielony Marek 4325
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/4399722215806986151/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2010/01/porownujemy-obiekty-interfejs.html#comment-form' title='Komentarze (7)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/4399722215806986151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/4399722215806986151'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2010/01/porownujemy-obiekty-interfejs.html' title='Porównujemy obiekty - interfejs Comparable&amp;lt;T&amp;gt;'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-1585077809029805361</id><published>2009-12-12T23:28:00.003+01:00</published><updated>2009-12-12T23:35:24.316+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Struktury Danych"/><title type='text'>Odwrotna Notacja Polska - część 2</title><content type='html'>W poprzedniej części (&lt;a href=&quot;http://kodatnik.blogspot.com/2009/12/odwrotna-notacja-polska-czesc-1.html&quot;&gt;Odwrotna Notacja Polska - część 1&lt;/a&gt;) dokonaliśmy zamiany wyrażenia w formie infiksowej na postać postfiksową (czyli formę w Odwrotnej Notacji Polskiej). W tym wpisie spróbujemy dokonać sprawdzenia poprawności nawiasów występujących w wyrażeniu infiksowym oraz obliczymy wartość wyrażenia postfiksowego. Do sprawdzenia poprawności nawiasów w wyrażeniu infiksowym użyjemy stosu (więcej na ten temat - &lt;a href=&quot;http://kodatnik.blogspot.com/2009/11/sprawdzanie-poprawnosci-nawiasow.html&quot;&gt;Sprawdzanie poprawności nawiasów&lt;/a&gt;). Jeśli wyrażenie nie będzie poprawne pod wartość wyrażenia postfiksowego podstawimy odpowiedni napis (klasa &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;String&lt;/span&gt; - &quot;Niepoprawne nawiasy w wyrażeniu infiksowym&quot;). Nasza metoda sprawdzająca poprawność nawiasów będzie metodą prywatną:&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;// metoda sprawdza poprawność nawiasów w wyrażeniu infiksowym
private boolean czyPoprawneNawiasy() {
 // tworzymy stos
 Stack&amp;lt;String&amp;gt; stos = new Stack&amp;lt;String&amp;gt;();

 // dzielimy wyrażenie infiksowe na części na podstawie separatorów
 StringTokenizer st = new StringTokenizer(wyrazenieInfiksowe, &quot;()&quot;, true);
        
 // dopóki są elementy w wyrażeniu wejściowym
 while(st.hasMoreTokens()) {
  // pobieramy element
  String s = st.nextToken();
            
  // jeżeli znak jest nawiasem otwierającym odkładamy go na stos
  if(s.equals(&quot;(&quot;)) stos.push(s);
  // jeżeli znak jest nawiasem zamykającym porównujemy go z wartością ze stosu            
  if(s.equals(&quot;)&quot;)) {
   if (stos.isEmpty()) return false;
   if (!stos.pop().equals(&quot;(&quot;)) return false;
  }
 }
 // zwracamy true albo false (stos pusty - wszystkie nawiasy są poprawne)
 return stos.isEmpty();         
}
&lt;/pre&gt;Po sprawdzeniu poprawności nawiasów możemy już dokonać obliczenia wartości wyrażenia postfiksowego według następującego algorytmu:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Inicjalizujemy stos,&lt;/li&gt;
&lt;li&gt;Analizujemy wyrażenie postfiksowe od lewej do prawej strony,&lt;/li&gt;
&lt;li&gt;Jeżeli element jest argumentem to odkładamy go na stos,&lt;/li&gt;
&lt;li&gt;Jeżeli element jest operatorem to ściągamy ze stosu dwie wartości, wykonujemy działanie, odkładamy na stos wynik,&lt;/li&gt;
&lt;li&gt;Jeżeli dotarliśmy do końca wyrażenie postfiksowego, ściągamy wartość ze stosu (jest to obliczona wartość wyrażenia postfiksowego).&lt;/li&gt;
&lt;/ul&gt;Przykład obliczenia wartości wyrażenia postfiksowego:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;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: 13
&lt;/pre&gt;Poniżej metoda obliczająca wartość wyrażenia postfiksowego. Operujemy na wartościach typu &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;double&lt;/span&gt;.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;// metoda oblicza wartość wyrażenia postfiksowego
private double oblicz() {
  
 // tworzymy pusty stos
 Stack&amp;lt;Double&amp;gt; stos = new Stack&amp;lt;Double&amp;gt;();
        
 // dzielimy wyrażenie postfiksowe na elementy na podstawie spacji
 StringTokenizer st = new StringTokenizer(wyrazeniePostfiksowe, &quot; &quot;);
        
 // dopóki są elementy w wyrażeniu wejściowym
 while(st.hasMoreTokens()) {
  // pobieramy element
  String s = st.nextToken();
  
  // jeśli element nie jest operatorem (czyli jest wartością)
  if (!s.equals(&quot;+&quot;) &amp;amp;&amp;amp; !s.equals(&quot;*&quot;) &amp;amp;&amp;amp; !s.equals(&quot;-&quot;) &amp;amp;&amp;amp; !s.equals(&quot;/&quot;)) {
   // zamieniamy łańcuch na liczbę
   double wartosc = Double.parseDouble(s);
   // odkładamy wartość na stos
   stos.push(wartosc);
  }
  else {
   //  jeśli element jest operatorem ściągamy dwie wartości ze stosu
   double wartosc1 = stos.pop();
   double wartosc2 = stos.pop();
   // w zależności od operatora obliczamy wynik i odkładamy go na stos
   switch(s.charAt(0)) {
    case &#39;*&#39;: {stos.push(wartosc2 * wartosc1); break;}
    case &#39;+&#39;: {stos.push(wartosc2 + wartosc1); break;}
    case &#39;-&#39;: {stos.push(wartosc2 - wartosc1); break;}
    case &#39;/&#39;: {stos.push(wartosc2 / wartosc1); break;}
   }
  }
 }
 // zwracamy końcowy wynik
 return stos.pop();
}
&lt;/pre&gt;Cała klasa &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;OdwrotnaNotacjaPolska&lt;/span&gt;:&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;// wykorzystujemy klasy Scanner, Stack&amp;lt;E&amp;gt; oraz StringTokenizer z pakietu java.util
import java.util.*;  
/**
 * Odwrotna Notacja Polska
 * Zamiana wyrażeń infiksowych na postfiksowe
 * @author kodatnik.blogspot.com
 */
public class OdwrotnaNotacjaPolska {
 // pola klasy
 private String wyrazenieInfiksowe;
 private String wyrazeniePostfiksowe; 
 private double wynik;   
 
 // konstruktor dokonuje przypisania polom wyrażeń
 public OdwrotnaNotacjaPolska(String wyrazenie) {
  this.wyrazenieInfiksowe = wyrazenie;
  wyrazeniePostfiksowe = &quot;&quot;;
  wynik = 0.0;
  if(!czyPoprawneNawiasy())
   wyrazeniePostfiksowe = &quot;Niepoprawne nawiasy w wyrażeniu infiksowym&quot;;
  else {
   // wywołujemy metodę dokonującą konwersji
   infiksNaPostfiks();
   wynik = oblicz();
  }   
 }

 // metoda zwraca wyrażenie w formie infiksowej
 public String pobierzWyrazenieInfiksowe() {
  return wyrazenieInfiksowe;
 }

 // metoda zwraca wyrażenie w formie postfiksowej
 public String pobierzWyrazeniePostfiksowe() {
  return wyrazeniePostfiksowe;
 }
 
 // metoda zwraca obliczoną wartość wyrażenia postfiksowego
 public double pobierzWynik() {
  return wynik;
 }
 
 // metoda sprawdza poprawność nawiasów w wyrażeniu infiksowym
 private boolean czyPoprawneNawiasy() {
  // tworzymy stos
  Stack&amp;lt;String&amp;gt; stos = new Stack&amp;lt;String&amp;gt;();

  // dzielimy wyrażenie infiksowe na części na podstawie separatorów
  StringTokenizer st = new StringTokenizer(wyrazenieInfiksowe, &quot;()&quot;, true);
        
  // dopóki są elementy w wyrażeniu wejściowym
  while(st.hasMoreTokens()) {
   // pobieramy element
   String s = st.nextToken();
            
   // jeżeli znak jest nawiasem otwierającym odkładamy go na stos
   if(s.equals(&quot;(&quot;)) stos.push(s);
   // jeżeli znak jest nawiasem zamykającym porównujemy go z wartością ze stosu            
   if(s.equals(&quot;)&quot;)) {
    if (stos.isEmpty()) return false;
    if (!stos.pop().equals(&quot;(&quot;)) return false;
   }
  }
  // zwracamy true albo false (stos pusty - wszystkie nawiasy są poprawne)
  return stos.isEmpty();         
 }

 // metoda konwertuje wyrażenie w postaci infiksowej na postfiksową
 // wynik operacji jest zapisywany w polu wyrazeniePostfiksowe
 private void infiksNaPostfiks() {
        
  // tworzymy pusty stos
  Stack&amp;lt;String&amp;gt; stos = new Stack&amp;lt;String&amp;gt;();
        
  // dzielimy wyrażenie infiksowe na części na podstawie separatorów
  StringTokenizer st = new StringTokenizer(wyrazenieInfiksowe, &quot;+-*/()&quot;, true);
        
  // dopóki są elementy w wyrażeniu wejściowym
  while(st.hasMoreTokens()) {
   // pobieramy element
   String s = st.nextToken();
         
   // jeżeli element jest operatorem
   if( s.equals(&quot;+&quot;) || s.equals(&quot;*&quot;) || s.equals(&quot;-&quot;) || s.equals(&quot;/&quot;)) {
    // sprawdzamy priorytety
    while(!stos.empty() &amp;amp;&amp;amp; priorytet(stos.peek()) &amp;gt;= priorytet(s)) 
     wyrazeniePostfiksowe += stos.pop()  + &quot; &quot;;
    // odkładamy operator na stos
    stos.push(s);
   }
   // jeżeli element jest nawiasem otwierającym
   else if(s.equals(&quot;(&quot;)) stos.push(s);
   // jeżeli element jest nawiasem zamykającym
   else if(s.equals(&quot;)&quot;)) {
    // ściągamy operatory ze stosu, aż do nawiasu otwierajęcego
    while(!stos.peek().equals(&quot;(&quot;)) wyrazeniePostfiksowe += stos.pop() + &quot; &quot;;
    // ściągamy nawias otwierający
    stos.pop();
   }
   // jeżeli element nie jest operatorem ani nawiasem dodajemy go do wyrażenia postfiksowego
   else wyrazeniePostfiksowe += s  + &quot; &quot;;
  }
  // ściągamy ze stosu pozostałe operatory i dodajemy je do wyrażenia postfiksowego
  while(!stos.empty()) wyrazeniePostfiksowe += stos.pop()  + &quot; &quot;;
        
 } 
  
 // metoda zwraca priorytet operatora
 public static int priorytet(String operator) {
  // dla &#39;+&#39; i &#39;-&#39; zwracamy 1
  if(operator.equals(&quot;+&quot;) || operator.equals(&quot;-&quot;)) return 1;
  // dla &#39;*&#39; i &#39;/&#39; zwracamy 2
  else if(operator.equals(&quot;*&quot;) || operator.equals(&quot;/&quot;)) return 2;
  // dla pozostałych 0
  else return 0;
 }
 
 // metoda oblicza wartość wyrażenia postfiksowego
 private double oblicz() {
  
  // tworzymy pusty stos
  Stack&amp;lt;Double&amp;gt; stos = new Stack&amp;lt;Double&amp;gt;();
        
  // dzielimy wyrażenie postfiksowe na elementy na podstawie spacji
  StringTokenizer st = new StringTokenizer(wyrazeniePostfiksowe, &quot; &quot;);
        
  // dopóki są elementy w wyrażeniu wejściowym
  while(st.hasMoreTokens()) {

   // pobieramy element
   String s = st.nextToken();
  
   // jeśli element nie jest operatorem (czyli jest wartością)
   if (!s.equals(&quot;+&quot;) &amp;amp;&amp;amp; !s.equals(&quot;*&quot;) &amp;amp;&amp;amp; !s.equals(&quot;-&quot;) &amp;amp;&amp;amp; !s.equals(&quot;/&quot;)) {
    // zamieniamy łańcuch na liczbę
    double wartosc = Double.parseDouble(s);
    // odkładamy wartość na stos
    stos.push(wartosc);
   }
   else {
    //  jeśli element jest operatorem ściągamy dwie wartości ze stosu
    double wartosc1 = stos.pop();
    double wartosc2 = stos.pop();
    // w zależności od operatora obliczamy wynik i odkładamy go na stos
    switch(s.charAt(0)) {
     case &#39;*&#39;: {stos.push(wartosc2 * wartosc1); break;}
     case &#39;+&#39;: {stos.push(wartosc2 + wartosc1); break;}
     case &#39;-&#39;: {stos.push(wartosc2 - wartosc1); break;}
     case &#39;/&#39;: {stos.push(wartosc2 / wartosc1); break;}
    }
   }
  }
  // zwracamy końcowy wynik
  return stos.pop();
 }
 
 // metoda zwraca nam łańcuch tekstowy z wyrażeniem 
 // w formie postfiksowej, oraz wynik
 public String toString() {
  return wyrazeniePostfiksowe + &quot;\nWynik: &quot; + wynik;
 }
}
&lt;/pre&gt;Poniżej przykład wykorzystania klasy.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class TestONP {
 public static void main(String args[]) {

  Scanner sc = new Scanner(System.in);
  System.out.print (&quot;Podaj wyrażenie infiksowe: &quot; );
  
  // pobieramy od użytkownika wyrażenie
  String wyrazenie = sc.nextLine();

  // tworzymy nowy obiekt klasy OdwrotnaNotacjaPolska 
  // i przekazujemy do konstruktora pobrane od użytkownika wyrażenie
  OdwrotnaNotacjaPolska onp = new OdwrotnaNotacjaPolska(wyrazenie);

  // wyświetlamy wyrażenie w postaci postfiksowej
  System.out.println (&quot;Wyrażenie postfiksowe: &quot; + onp);
 }
}
&lt;/pre&gt;Wyniki działania aplikacji:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Podaj wyrażenie infiksowe: (4*2)+(15/3)
Wyrażenie postfiksowe: 4 2 * 15 3 / + 
Wynik: 13.0
&lt;/pre&gt;&lt;pre class=&quot;console&quot;&gt;Podaj wyrażenie infiksowe: (3+4)*2)
Wyrażenie postfiksowe: Niepoprawne nawiasy w wyrażeniu infiksowym
&lt;/pre&gt;&lt;pre class=&quot;console&quot;&gt;Podaj wyrażenie infiksowe: ((1+2)-2.5)*8/2
Wyrażenie postfiksowe: 1 2 + 2.5 - 8 * 2 / 
Wynik: 2.0
&lt;/pre&gt;&lt;div class=&quot;tip&quot;&gt;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).&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/1585077809029805361/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/12/odwrotna-notacja-polska-czesc-2.html#comment-form' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/1585077809029805361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/1585077809029805361'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/12/odwrotna-notacja-polska-czesc-2.html' title='Odwrotna Notacja Polska - część 2'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-5588735892100401510</id><published>2009-12-06T14:49:00.014+01:00</published><updated>2009-12-06T16:12:20.361+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blogger"/><category scheme="http://www.blogger.com/atom/ns#" term="Gadżety"/><title type='text'>Piszemy gadżet do Bloggera - część 2</title><content type='html'>W poprzedniej części (&lt;a href=&quot;http://kodatnik.blogspot.com/2009/11/piszemy-gadzet-do-bloggera-czesc-1.html&quot;&gt;Piszemy gadżet do Bloggera - część 1&lt;/a&gt;) poznaliśmy podstawy pisania gadżetu oraz jego strukturę. Dzisiaj poznamy sposoby jego konfigurowania przez użytkownika. Pozwolimy użytkownikowi na podanie dodatkowych informacji podczas dodawania gadżetu do bloga. Dzięki temu użytkownik będzie mógł zdecydować np. o kolorach, napisach czy innych opcjach związanych z konkretnym gadżetem. Sekcją odpowiedzialną za preferencje jest &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;UserPref&amp;gt;&lt;/span&gt;. Opisuje ona pola, które będzie mógł modyfikować użytkownik podczas konfiguracji gadżetu. Pola mogą mieć następujące atrybuty:&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;name&lt;/span&gt; - nazwa którą będziemy się posługiwać w gadżecie,&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;display_name&lt;/span&gt; - nazwa wyświetlana użytkownikowi (jej brak powoduje wyświetlenie atrybutu name),&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;datatype&lt;/span&gt; - typ danych (&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;string&lt;/span&gt; - łańcuch tekstowy, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;bool&lt;/span&gt; - wartość logiczna, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;enum&lt;/span&gt; - typ wyliczeniowy, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;hidden&lt;/span&gt; - pole ukyte, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;list&lt;/span&gt; - dynamiczna lista), domyślnym typem jest &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;string&lt;/span&gt;,&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;required&lt;/span&gt; - atrybut logiczny określający czy dane pole jest wymagane,&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;default_value&lt;/span&gt; - domyślna wartość dla pola&lt;/li&gt;
&lt;/ul&gt;Przykładowe pole preferencji pobierające od użytkownika łańcuch tekstowy (jego imię):&lt;br /&gt;
&lt;pre class=&quot;brush: xml; gutter: false;&quot;&gt;&amp;lt;UserPref name=&quot;imie&quot; display_name=&quot;Podaj swoje imię:&quot; /&amp;gt;
&lt;/pre&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0zKWMznyGD-4Gb9x2ORY-ZtJdIIGMUuZqOD51P95XJc4RuvoHAc92dBKv6x_jkpLr6fpLHjB3O1Ols2i72jV-_KhrNrqGg-BbSPFdnTxKrfdM-oCcYAgmWJ008QdhUI7Y56CGSsaMOkY/s1600-h/konfiguracja1.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0zKWMznyGD-4Gb9x2ORY-ZtJdIIGMUuZqOD51P95XJc4RuvoHAc92dBKv6x_jkpLr6fpLHjB3O1Ols2i72jV-_KhrNrqGg-BbSPFdnTxKrfdM-oCcYAgmWJ008QdhUI7Y56CGSsaMOkY/s1600/konfiguracja1.jpg&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
W przypadku wybrania jako atrybutu pola preferencji typu enum, musimy określić dodatkowo opcje, z których może wybierać użytkownik. Opcje te podajemy za pomocą znacznika &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;EnumValue&amp;gt;&lt;/span&gt;. Posiada on dwa parametry:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;value&lt;/span&gt; - wartość opcji,&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;display_value&lt;/span&gt; - nazwa wyświetlana użytkownikowi (jej brak powoduje wyświetlenie atrybutu &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;value&lt;/span&gt;).&lt;/li&gt;
&lt;/ul&gt;Przykładowe pole preferencji pobierające od użytkownika kierunek geograficzny (domyślnie południe):&lt;br /&gt;
&lt;pre class=&quot;brush: xml; gutter: false;&quot;&gt;&amp;lt;UserPref name=&quot;kierunek&quot; display_name=&quot;Kierunek geogr.&quot; default_value=&quot;south&quot; datatype=&quot;enum&quot; &amp;gt;
 &amp;lt;EnumValue value=&quot;south&quot; display_value=&quot;Południe&quot; /&amp;gt;
 &amp;lt;EnumValue value=&quot;north&quot; display_value=&quot;Północ&quot; /&amp;gt;
 &amp;lt;EnumValue value=&quot;west&quot; display_value=&quot;Zachód&quot; /&amp;gt;
 &amp;lt;EnumValue value=&quot;east&quot; display_value=&quot;Wschód&quot; /&amp;gt;
&amp;lt;/UserPref&amp;gt;
&lt;/pre&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjh9q9Rtqggb9kaJKLjc5MKXlxCOw9l-hM-NbVgkNMzQjKOVzy9KrCw3bEBggGHiMxCVhATX-eOf-uSife24rRCgD8Jigy5rWgBhVcCjX0ijWJ-IaHBbMp7xtIZb8YQvUOdF0gyp6V-8rs/s1600-h/konfiguracja2.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjh9q9Rtqggb9kaJKLjc5MKXlxCOw9l-hM-NbVgkNMzQjKOVzy9KrCw3bEBggGHiMxCVhATX-eOf-uSife24rRCgD8Jigy5rWgBhVcCjX0ijWJ-IaHBbMp7xtIZb8YQvUOdF0gyp6V-8rs/s1600/konfiguracja2.jpg&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
Dostęp do preferencji z poziomu kodu gadżetu odbywa się z wykorzystaniem &lt;i&gt;JavaScript&#39;u&lt;/i&gt;. Poniższy przykład pobierze podane przez użytkownika imię:&lt;br /&gt;
&lt;pre class=&quot;brush: xml; gutter: false;&quot;&gt;var preferencje = new gadgets.Prefs();
var imieUzytkownika = preferencje.getString(&quot;imie&quot;);
&lt;/pre&gt;Wykorzystajmy naszą wiedzę do stworzenia prostego gadżetu umożliwiającego użytkownikowi podanie napisu, ustawienie koloru tła oraz określenie czy wyświetlać dzisiejszą datę czy też nie.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK0oOB3vzHzo_Yp3N8CskzZ0H4G1Ty7A18qDW8UzPIcrdI7KM6-ivB_lNf5yHsKdS7BvgXI0jcCzP0UQjX_j3S1KdQcuGwRCD7uQ_NZmFqJLvXVXaknNzQl5Jzg4e13nW99Rh_7GHLFBg/s1600-h/konfiguracja3.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK0oOB3vzHzo_Yp3N8CskzZ0H4G1Ty7A18qDW8UzPIcrdI7KM6-ivB_lNf5yHsKdS7BvgXI0jcCzP0UQjX_j3S1KdQcuGwRCD7uQ_NZmFqJLvXVXaknNzQl5Jzg4e13nW99Rh_7GHLFBg/s1600/konfiguracja3.jpg&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
Wszystkie operacje związane z wyświetlaniem danych przeprowadzimy z wykorzystaniem &lt;i&gt;JavaScript&#39;u&lt;/i&gt;. Nasz przykładowy gadżet uruchamia się od funkcji &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;init()&lt;/span&gt; (wywołanie &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;gadgets.util.registerOnLoadHandler(init());&lt;/span&gt;) To co ma się pojawić w gadżecie zostało ujęte w sekcję HTML: &lt;br /&gt;
&lt;pre class=&quot;brush: xml; gutter: false;&quot;&gt;&amp;lt;div id=&quot;zawartosc&quot;&amp;gt;&amp;lt;/div&amp;gt; 
&lt;/pre&gt;Korzystając z możliwości &lt;i&gt;JavaScript&#39;u&lt;/i&gt; jesteśmy w stanie zmienić kolor tła tego elementu (&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;element.style.backgroundColor&lt;/span&gt;) jak i również wstawić do niego inne elementy czy to teksty czy też znaczniki HTML&#39;a (&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;element.innerHTML&lt;/span&gt;). Kod naszego gadżetu:&lt;br /&gt;
&lt;pre class=&quot;brush: xml; gutter: false;&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&amp;gt; 
&amp;lt;Module&amp;gt;
 &amp;lt;ModulePrefs 
  title=&quot;Przykładowy gadżet&quot; 
  author=&quot;Devon&quot;&amp;gt; 
  &amp;lt;Require feature=&quot;dynamic-height&quot; /&amp;gt;
 &amp;lt;/ModulePrefs&amp;gt;
 &amp;lt;UserPref name=&quot;napis&quot; display_name=&quot;Napis&quot; default_value=&quot;Nasz drugi gadżet!&quot; /&amp;gt;
 &amp;lt;UserPref name=&quot;data&quot; display_name=&quot;Pokazać datę?&quot; default_value=&quot;true&quot; datatype=&quot;bool&quot; /&amp;gt;
 &amp;lt;UserPref name=&quot;kolor&quot; display_name=&quot;Kolor tła&quot; default_value=&quot;green&quot; datatype=&quot;enum&quot; &amp;gt;
  &amp;lt;EnumValue value=&quot;red&quot; display_value=&quot;Czerwony&quot; /&amp;gt;
  &amp;lt;EnumValue value=&quot;yellow&quot; display_value=&quot;Żółty&quot; /&amp;gt;
  &amp;lt;EnumValue value=&quot;green&quot; display_value=&quot;Zielony&quot; /&amp;gt;
 &amp;lt;/UserPref&amp;gt;
 &amp;lt;Content type=&quot;html&quot;&amp;gt;
  &amp;lt;![CDATA[ 
   &amp;lt;div id=&quot;zawartosc&quot;&amp;gt;&amp;lt;/div&amp;gt;

   &amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
    // pobieramy preferencje
    var preferencje = new gadgets.Prefs();

    // funkcja startowa (nazwa może być dowolna)
    function init() {
     // bierzemy obiekt daty
     var data = new Date();
     // i wyciągamy z niego potrzebne informacje (dzień, miesiąc, rok)
     var dzisiaj = &quot;&amp;lt; br /&amp;gt;Dzisiaj jest: &quot; + data.getDate() + &quot;.&quot; + (data.getMonth()+1) + &quot;.&quot; + data.getFullYear();
     // w tej zmiennej przechowujemy to co później dodamy do gadżetu
     var html = &quot;&quot;;
    
     // pobieramy element zawartosc
     var element = document.getElementById(&#39;zawartosc&#39;);  
     // ustawiamy kolor tła elementu na taki jak podał użytkownik   
     element.style.backgroundColor = preferencje.getString(&quot;kolor&quot;); 

     // dodajemy pobrany napis do zmiennej html
     html += preferencje.getString(&quot;napis&quot;);
   
     // jeżeli użytkownik chce wyświetlać datę
     if (preferencje.getBool(&quot;data&quot;) == true) {
      // to dodajemy ją do zmiennej html
      html += dzisiaj;
     }

     // wklejamy do &quot;elementu&quot; zawartość zmiennej html
     element.innerHTML = html;
    
     // zmieniamy wysokość gadżetu
     gadgets.window.adjustHeight(); 
    }

    // za pomocą tej metody podajemy funkcję, która
    // ma zostać uruchomiona podczas startu gadżetu (tutaj init())
    gadgets.util.registerOnLoadHandler(init()); 
   &amp;lt;/script&amp;gt; 

  ]]&amp;gt;
 &amp;lt;/Content&amp;gt; 
&amp;lt;/Module&amp;gt;
&lt;/pre&gt;Dodatkowo wykorzystaliśmy dynamiczną zmianę wysokości gadżetu (&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;gadgets.window.adjustHeight()&lt;/span&gt;). Jest to możliwe po załadowaniu odpowiedniej biblioteki (&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;Require feature=&quot;dynamic-height&quot; /&amp;gt;&lt;/span&gt;) w sekcji &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;ModulePrefs&amp;gt;&lt;/span&gt;.&lt;br /&gt;
Po dodaniu gadżet prezentuje się następująco:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8E5cqh1_6U1BbJlipHZ36veDLwBScDtLTxN_zMo1WY-A5925YZwXHh0af4MJvwVBM-ngpf-fpUpmvOq2c6rR293TtTMVMiXOqjhhyqaoS5clm0mhfQhOojj_0IjiVJzEhSl8Vi0kdRRI/s1600-h/drugi.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8E5cqh1_6U1BbJlipHZ36veDLwBScDtLTxN_zMo1WY-A5925YZwXHh0af4MJvwVBM-ngpf-fpUpmvOq2c6rR293TtTMVMiXOqjhhyqaoS5clm0mhfQhOojj_0IjiVJzEhSl8Vi0kdRRI/s1600/drugi.jpg&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
Gotowy gadżet jest dostępny do dodania do bloga pod adresem: &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;http://sites.google.com/site/kodatnikfiles/xml/DrugiGadzet.xml&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/5588735892100401510/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/12/piszemy-gadzet-do-bloggera-czesc-2.html#comment-form' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/5588735892100401510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/5588735892100401510'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/12/piszemy-gadzet-do-bloggera-czesc-2.html' title='Piszemy gadżet do Bloggera - część 2'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0zKWMznyGD-4Gb9x2ORY-ZtJdIIGMUuZqOD51P95XJc4RuvoHAc92dBKv6x_jkpLr6fpLHjB3O1Ols2i72jV-_KhrNrqGg-BbSPFdnTxKrfdM-oCcYAgmWJ008QdhUI7Y56CGSsaMOkY/s72-c/konfiguracja1.jpg" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-8486867021920595809</id><published>2009-12-05T00:05:00.003+01:00</published><updated>2009-12-05T00:38:31.514+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Struktury Danych"/><title type='text'>Odwrotna Notacja Polska - część 1</title><content type='html'>Odwrotna Notacja Polska to sposób zapisu wyrażeń arytmetycznych za pomocą notacji postfiksowej. Standardowa notacja, z której korzystamy na codzień to notacja infiksowa, argument operator argument (np. 3 + 4). Notacja postfiksowa nie zmienia kolejności argumentów, natomiast zmienia  położenie operatorów (występują one po argumentach, których dotyczą). Przykładowy zapis w notacji postfiksowej wyglada tak: 3 4 +. Taki sposób zapisu jest o wiele łatwiejszy do analizy poprawności wyrażenia jak i do jego obliczenia. Wykorzystując stos w prosty sposób możemy dokonać zamiany wyrażenia z postaci infiksowej na postać postfiksową. Algorytm zamiany jest następujący:&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Inicjalizujemy stos,&lt;/li&gt;
&lt;li&gt;Analizujemy wyrażenie infiksowe od lewej do prawej strony,&lt;/li&gt;
&lt;li&gt;Jeżeli element jest argumentem to dodajemy go do wyrażenia postfiksowego,&lt;/li&gt;
&lt;li&gt;Jeżeli element jest operatorem i stos jest pusty to odkładamy go na stos,&lt;/li&gt;
&lt;li&gt;Jeżeli element jest operatorem i stos nie jest pusty to sprawdzamy co jest na wierzchołku stosu i porównujemy z odczytanym elementem. Jeśli operator ze stosu ma mniejszy lub równy priorytet z naszym znakiem to wstawiamy odczytany element na stos, jeśli nie to ściągamy operator ze stosu i dodajemy go do wyrażenia postfiksowego oraz odkładamy odczytany element na stos.&lt;/li&gt;
&lt;li&gt;Jeśli nie ma więcej elementów w wyrażeniu infiksowym to ściągamy ze stosu (o ile nie jest pusty)znajdujące się tam operatory i dodajemy je do wyrażenia postfiksowego.&lt;/li&gt;
&lt;/ul&gt;Przykład zamiany wyrażenia infiksowego na postfiksowe:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Wyrażenie infiksowe: 4 * 2 + 7 / 8

Kolejny znak       Stos      Wyrażenie postfiksowe
     4                                 4
     *             *                   4
     2             *                   4 2
     +             +                   4 2 *
     7             +                   4 2 * 7
     /             + /                 4 2 * 7
     8             + /                 4 2 * 7 8
                                       4 2 * 7 8 / +

Wyrażenie postfiksowe: 4 2 * 7 8 / +
&lt;/pre&gt;Dla wyrażeń posiadających nawiasy postępujemy według następującego algorytmu:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Jeżeli odczytany znak jest nawiasem otwierającym to umieszczamy go na stosie,&lt;/li&gt;
&lt;li&gt;Jeżeli odczytany znak jest nawiasem zamykającym to ściągamy ze stosu, aż do napotkania nawiasu otwierającego operatory i dodajemy do wyrażenia postfiksowego, &lt;/li&gt;
&lt;li&gt;Ściągamy ze stosu nawias otwierający.&lt;/li&gt;
&lt;/ul&gt;Przykład zamiany wyrażenia infiksowego z nawiasami na wyrażenie postfiksowe:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Wyrażenie infiksowe: ( 1 + 2 ) * 3

Kolejny znak       Stos      Wyrażenie postfiksowe 
     (             (
     1             (                   1
     +             ( +                 1
     2             ( +                 1 2
     )                                 1 2 +
     *             *                   1 2 +
     3             *                   1 2 + 3
                                       1 2 + 3 *

Wyrażenie postfiksowe: 1 2 + 3 *
&lt;/pre&gt;Poniżej prosta klasa dokonująca konwersji wyrażeń z postaci infiksowej na postfiksową z wykorzystaniem powyższego algorytmu. Jako stos wykorzystałem klasę biblioteczną &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Stack&lt;/span&gt;. Podział danych wejściowych odbywa się za pomocą klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;StringTokenizer&lt;/span&gt; (więcej o tej klasie tu &lt;a href=&quot;http://kodatnik.blogspot.com/2009/11/podzia-ancucha-na-czesci.html&quot;&gt;Podział łańcucha na części&lt;/a&gt;). Dodatkowo metoda &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;priorytet(String)&lt;/span&gt; zwraca priorytet dla poszczególnych operatorów.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;// wykorzystujemy klasy Scanner, Stack oraz StringTokenizer z pakietu java.util
import java.util.*;  
/**
 * Odwrotna Notacja Polska
 * Zamiana wyrażeń infiksowych na postfiksowe
 * @author kodatnik.blogspot.com
 */
public class OdwrotnaNotacjaPolska {
 // pola klasy
 private String wyrazenieInfiksowe;
 private String wyrazeniePostfiksowe; 
 
 // konstruktor dokonuje przypisania polom wyrażeń
 public OdwrotnaNotacjaPolska(String wyrazenie) {
  wyrazenieInfiksowe = wyrazenie;
  wyrazeniePostfiksowe = &quot;&quot;;
  // wywołujemy metodę dokonującą konwersji
  infiksNaPostfiks();
 }

 // metoda konwertuje wyrażenie w postaci infiksowej na postfiksową
 // wynik operacji jest zapisywany w polu wyrazeniePostfiksowe
 private void infiksNaPostfiks() {
        
  // tworzymy pusty stos
  Stack&amp;lt;String&amp;gt; stos = new Stack&amp;lt;String&amp;gt;();
        
  // dzielimy wyrażenie infiksowe na części na podstawie separatorów
  StringTokenizer st = new StringTokenizer(wyrazenieInfiksowe, &quot;+-*/()&quot;, true);
        
  // dopóki są elementy w wyrażeniu wejściowym
  while(st.hasMoreTokens()) {

   // pobieramy element
   String s = st.nextToken();
         
   // jeżeli element jest operatorem
   if( s.equals(&quot;+&quot;) || s.equals(&quot;*&quot;) || s.equals(&quot;-&quot;) || s.equals(&quot;/&quot;)) {
    // sprawdzemy priorytety
    while(!stos.empty() &amp;amp;&amp;amp; priorytet(stos.peek()) &amp;gt;= priorytet(s)) 
     wyrazeniePostfiksowe += stos.pop()  + &quot; &quot;;
     // odkładamy operator na stos
    stos.push(s);
   }
   // jeżeli element jest nawiasem otwierającym
   else if(s.equals(&quot;(&quot;)) stos.push(s);
   // jeżeli element jest nawiasem zamykającym
   else if(s.equals(&quot;)&quot;)) {
    // ściągamy operatory ze stosu, aż do nawiasu otwierajęcego
    while(!stos.peek().equals(&quot;(&quot;)) wyrazeniePostfiksowe += stos.pop() + &quot; &quot;;
    // ściągamy nawias otwierający
    stos.pop();
   }
   // jeżeli element nie jest operatorem ani nawiasem dodajemy go do wyrażenia postfiksowego
   else wyrazeniePostfiksowe += s  + &quot; &quot;;
  }
  // ściągamy ze stosu pozostałe operatory i dodajemy je do wyrażenia postfiksowego
  while(!stos.empty()) wyrazeniePostfiksowe += stos.pop()  + &quot; &quot;;
 } 
  
 // metoda zwraca priorytet operatora
 public static int priorytet(String operator) {
  // dla + i - zwracamy 1
  if(operator.equals(&quot;+&quot;) || operator.equals(&quot;-&quot;)) return 1;
  // dla * i / zwracamy 2
  else if(operator.equals(&quot;*&quot;) || operator.equals(&quot;/&quot;)) return 2;
  // dla pozostałych 0
  else return 0;
 }
 
 // metoda zwraca nam łańcuch tekstowy z wyrażeniem w formie postfiksowej
 public String toString() {
  return wyrazeniePostfiksowe;
 }

 public static void main(String args[]) {

  Scanner sc = new Scanner(System.in);
  System.out.print (&quot;Podaj wyrażenie infiksowe: &quot; );
 
  // pobieramy od użytkownika wyrażenie
  String wyrazenie = sc.nextLine();

  // tworzymy nowy obiekt klasy OdwrotnaNotacjaPolska 
  // i przekazujemy do konstruktora pobrane od użytkownika wyrażenie
  OdwrotnaNotacjaPolska onp = new OdwrotnaNotacjaPolska(wyrazenie);

  // wyświetlamy wyrażenie w postaci postfiksowej
  System.out.println (&quot;Wyrażenie postfiksowe: &quot; + onp);
 }
}
&lt;/pre&gt;Wynik działania aplikacji:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Podaj wyrażenie infiksowe: (4+2)*(3-1)
Wyrażenie postfiksowe: 4 2 + 3 1 - * 
&lt;/pre&gt;Dodatkowo możemy jeszcze sprawdzać poprawność nawiasów w podanym przez użytkownika wyrażeniu infiksowym (zobacz: &lt;a href=&quot;http://kodatnik.blogspot.com/2009/11/sprawdzanie-poprawnosci-nawiasow.html&quot;&gt;Sprawdzanie poprawności nawiasów&lt;/a&gt;). W kolejnej części spróbujemy obliczyć wartość wyrażenia w postaci postfiksowej.</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/8486867021920595809/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/12/odwrotna-notacja-polska-czesc-1.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8486867021920595809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8486867021920595809'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/12/odwrotna-notacja-polska-czesc-1.html' title='Odwrotna Notacja Polska - część 1'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-2040437446753242125</id><published>2009-12-04T19:06:00.001+01:00</published><updated>2009-12-05T01:06:44.003+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Struktury Danych"/><title type='text'>Klasa LinkedList - przykład zastosowania</title><content type='html'>Klasa &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;LinkedList&lt;/span&gt; jest jedną z klas bibliotecznych dostępnych w standardowej Javie. Jest to prosta implementacja listy powiązanej z wykorzystaniem typów generycznych (pisałem o nich tutaj &lt;a href=&quot;http://kodatnik.blogspot.com/2009/12/typy-generyczne.html&quot;&gt;Typy generyczne&lt;/a&gt;). Na jej bazie możemy napisać implementację w pełni dynamicznego stosu (inne sposoby tworzenia stosu to &lt;a href=&quot;http://kodatnik.blogspot.com/2009/11/stos-implementacja-tablicowa.html&quot;&gt;Stos - implementacja tablicowa&lt;/a&gt; oraz &lt;a href=&quot;http://kodatnik.blogspot.com/2009/11/lista-powiazana-wasna-implementacja.html&quot;&gt;Lista powiązana - własna implementacja&lt;/a&gt;). Nasze rozwiązanie dzięki zastosowaniu typów generycznych umożliwi obsługę dowolnych obiektów.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;// wykorzystujemy klasę LinkedList z pakietu java.util
import java.util.*;

/**
 * Stos - implementacja z wykorzystaniem klasy LinkedList
 * @author kodatnik.blogspot.com 
 */ 
public class Stos&amp;lt;E&amp;gt; {
 // lista przechowująca elementy stosu
 // wierzchołek stosu to ostatni element listy
 private LinkedList&amp;lt;E&amp;gt; lista;

 // konstruktor domyślny
 public Stos() {
  // tworzymy nowy obiekt klasy LinkedList
  lista = new LinkedList&amp;lt;E&amp;gt;();
 }
 
 // metoda odkładająca na stosie elementy
 public void push(E element) {
  // dodajemy element do listy
  lista.add(element);
 }

 // metoda ściąga ze stosu element
 public E pop() {
  // zwracamy element znajdujący się na końcu listy
  return lista.removeLast(); 
 }
 
 // metoda sprawdza czy stos jest pusty
 public boolean czyPusty() {
  // zwracamy prawdę lub fałsz
  return (lista.isEmpty());
 }
 
 // metoda &quot;podgląda&quot; co jest na wierzchołku stosu
 public E peek() {
  // zwracamy element z wierzchołka stosu (nie usuwamy go z listy)
  return lista.getLast();
 }
 
 // metoda wyświetla wszystkie elementy stanowiące stos
 public void wyswietl() {
  // wykorzystujemy metodę toString() z klasy LinkedList
  System.out.println(lista);
 }
 
 // metoda zwraca rozmiar stosu (liczbę jego elementów)
 public int rozmiar() {
  return lista.size(); 
 }
}
&lt;/pre&gt;Poniżej przykładowe zastosowanie klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Stos&lt;/span&gt; (przechowujemy na stosie łańcuchy tekstowe czyli obiekty klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;String&lt;/span&gt;).&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class TestujemyStos { 
 public static void main(String args[]) {
    
  // zakładamy nowy stos łańcuchów tekstowych
  Stos&amp;lt;String&amp;gt; s = new Stos&amp;lt;String&amp;gt;();
     
  // odkładamy kolejne elementy na stos
  s.push(&quot;Ala&quot;);
  s.push(&quot;Ola&quot;);
  s.push(&quot;Marcin&quot;);
     
  // wyświetlamy zawartość stosu
  s.wyswietl();

  // wyświetlamy element znajdujący się na szczycie (bez jego ściągania)
  System.out.println(s.peek());
     
  // ściągamy element ze stosu
  s.pop();     
      
  // wyświetlamy zawartość stosu
  s.wyswietl();    
      
  // wyświetlamy rozmiar stosu
  System.out.println (s.rozmiar());
 }
}
&lt;/pre&gt;Uruchomiona aplikacja:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;[Ala, Ola, Marcin]
Marcin
[Ala, Ola]
2
&lt;/pre&gt;&lt;div class=&quot;tip&quot;&gt;W oparciu o klasę &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;LinkedList&lt;/span&gt; można utworzyć wiele innych struktur danych np. Kolejki czy też Drzewa.&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/2040437446753242125/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/12/klasa-linkedlist-przykad-zastosowania.html#comment-form' title='Komentarze (16)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/2040437446753242125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/2040437446753242125'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/12/klasa-linkedlist-przykad-zastosowania.html' title='Klasa LinkedList - przykład zastosowania'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-8343102674251706440</id><published>2009-12-04T18:13:00.007+01:00</published><updated>2011-06-21T00:30:18.588+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Typy generyczne</title><content type='html'>Java od wersji 1.5 obsługuje typy generyczne. Pozwalają one sparametryzować klasę, przez co nie ma konieczności dokonywania później kłopotliwego rzutowania. Sam zapis typu generycznego to duża litera/litery ujęta w nawiasy ostre. Utwórzmy prostą klasę &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Pudelko&lt;/span&gt; przechowującą elementy dowolnego typu.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
 * Wykorzystanie typów generycznych 
 * @author kodatnik.blogspot.com
 */
class Pudelko &amp;lt;T&amp;gt; {
 // referencja do obiektu typu T
 private T element; 

 // konstruktor klasy
 public Pudelko(T element) {
  this.element = element;
 } 

 // metoda zwraca referencję do przechowywanego elementu
 public T pobierzElement() {
  return element;
 }
}
&lt;/pre&gt;
Tworząc obiekt klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Pudelko&lt;/span&gt; musimy określić jakiego typu dane będą w nim przechowywane. Przykładowe wykorzystanie klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Pudelko&lt;/span&gt;.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class TestPudelka {
 public static void main(String args[]) {
    
  // tworzymy trzy pudełka dla różnych typów danych (String, Integer oraz Double)
  Pudelko&amp;lt;String&amp;gt;  p1 = new Pudelko&amp;lt;String&amp;gt;(&quot;Ala ma kota&quot;);
  Pudelko&amp;lt;Integer&amp;gt; p2 = new Pudelko&amp;lt;Integer&amp;gt;(12);     
  Pudelko&amp;lt;Double&amp;gt;  p3 = new Pudelko&amp;lt;Double&amp;gt;(24.76);   
  
  // sprawdzamy zawartość każdego pudełka
  System.out.println (p1.pobierzElement());
  
  int wartosc = p2.pobierzElement() + 3;
  System.out.println (wartosc);
  
  System.out.println (p3.pobierzElement());    
 }
}
&lt;/pre&gt;
Wynik działania aplikacji (pudełko pierwsze przechowuje łańcuchy tekstowe, drugie liczby całkowite, a trzecie liczby rzeczywiste).&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Ala ma kota
15
24.76
&lt;/pre&gt;
Większość klas dostarczanych z Javą wykorzystuje typy generyczne. Są to zazwyczaj klasy będące &quot;pojemnikami&quot; dla innych obiektów (tzw. kolekcje). Na przykład klasy &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;LinkedList&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Array&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Stack&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Vector&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;TreeMap&lt;/span&gt; itp.&lt;br /&gt;
&lt;div class=&quot;tip&quot;&gt;
Typy generyczne przeznaczone są tylko do typów obiektowych, nie można ich użyć do typów prymitywnych.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/8343102674251706440/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/12/typy-generyczne.html#comment-form' title='Komentarze (13)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8343102674251706440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/8343102674251706440'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/12/typy-generyczne.html' title='Typy generyczne'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-1186795635339824870</id><published>2009-11-26T16:38:00.003+01:00</published><updated>2009-11-26T16:55:58.493+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blogger"/><category scheme="http://www.blogger.com/atom/ns#" term="Gadżety"/><title type='text'>Piszemy gadżet do Bloggera - część 1</title><content type='html'>Gadżety rozszerzają funkcjonalność naszych blogów. Dla platformy &lt;a href=&quot;http://blogger.com/&quot;&gt;Blogger&lt;/a&gt; istnieje już kilkaset gotowych rozwiązań. Nic nie stoi na przeszkodzie, aby napisać samodzielnie taki gadżet. W kilku postach postaram się przybliżyć tematykę pisania gadżetów. Co będzie nam potrzebne:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;edytor tekstu (z możliwością zapisu w formacie UTF-8, np. Windowsowy notatnik, &lt;a href=&quot;http://notepad-plus.sourceforge.net/&quot; target=&quot;_blank&quot;&gt;Notepad++&lt;/a&gt;, czy &lt;a href=&quot;http://www.pspad.com/&quot; target=&quot;_blank&quot;&gt;PSPad&lt;/a&gt;),&lt;/li&gt;
&lt;li&gt;serwer na którym zamieścimy nasz gadżet (np. &lt;a href=&quot;http://sites.google.com/&quot; target=&quot;_blank&quot;&gt;Witryny Google&lt;/a&gt;, lub inny dowolny serwer z możliwością wgrywania plików),&lt;/li&gt;
&lt;li&gt;podstawową znajomość HTML&#39;a i JavaScriptu.&lt;/li&gt;
&lt;/ul&gt;&lt;div style=&quot;font-family: Verdana,sans-serif;&quot;&gt;&lt;b&gt;Struktura gadżetu&lt;/b&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
Gadżety do Bloggera tak samo jak pozostałe gadżety Googli składają się z plików XML (kod gadżetu, pliki językowe itd.). Podstawowa struktura gadżetu została przedstawiona poniżej.&lt;br /&gt;
&lt;pre class=&quot;brush: xml; gutter: false;&quot;&gt;&amp;lt;module&amp;gt;
 &amp;lt;moduleprefs title=&quot;Przykładowy gadżet&quot;&amp;gt; 
  // pozostałe ustawienia
 &amp;lt;content type=&quot;html&quot;&amp;gt;
  &amp;lt;![CDATA[ 
   // zawartość HTML, JavaScript
  ]]&amp;gt;
 &amp;lt;/content&amp;gt;
 &amp;lt;/moduleprefs&amp;gt;
&amp;lt;/module&amp;gt;&lt;/pre&gt;Pierwsza linia jest obowiązkowa i informuje o rozpoczęciu pliku w formacie XML. Pozostałe to tagi związane z gadżetami i tak:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;tag &lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;&lt;/b&gt; to oznaczenie, że plik będzie zawierał dane gadżetu,&lt;/li&gt;
&lt;li&gt;tag &lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;moduleprefs&amp;gt;&lt;/span&gt;&lt;/b&gt; zawiera dodatkowe informacje o gadżecie (autor, tytuł, lokalizacje, używane rozszerzenia itp.)&lt;/li&gt;
&lt;li&gt;tag &lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;content type=&quot;html&quot;&amp;gt;&lt;/span&gt;&lt;/b&gt; informuje, że zawartością gadżetu będą polecenia HTML&#39;a,&lt;/li&gt;
&lt;li&gt;sekcja &lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;![CDATA[&lt;/span&gt;&lt;/b&gt;  rozpoczyna właściwy kod HTML&#39;a (czy JavaScript&#39;u), który będzie wyświetlany przez gadżet,&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;]]&amp;gt;&lt;/span&gt;&lt;/b&gt; zamknięcie sekcji &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;CDATA&lt;/span&gt;,&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;/content&amp;gt;&lt;/span&gt;&lt;/b&gt; - tag zamykający,&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;&lt;/b&gt; - tag zamykający.&lt;/li&gt;
&lt;/ul&gt;Utwórzmy prosty gadżet wyświetlający napis &quot;Nasz pierwszy gadżet!&quot;. Dodatkowo w sekcji &lt;b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;moduleprefs&amp;gt;&lt;/span&gt;&lt;/b&gt; zamieścimy informacje o autorze. Po wpisaniu kodu do edytora zapiszmy go pod nazwą &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;PierwszyGadzet.xml&lt;/span&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: xml; gutter: false;&quot;&gt;&amp;lt;module&amp;gt;
 &amp;lt;moduleprefs author=&quot;Devon&quot; title=&quot;Przykładowy gadżet&quot;&amp;gt; 
 &amp;lt;content type=&quot;html&quot;&amp;gt;
  &amp;lt;![CDATA[ 
   Nasz pierwszy gadżet!
  ]]&amp;gt;
 &amp;lt;/content&amp;gt;
 &amp;lt;/moduleprefs&amp;gt;
&amp;lt;/module&amp;gt;&lt;/pre&gt;Pozostaje opublikowanie go w sieci. Możemy wykorzystać do tego celu &lt;a href=&quot;http://sites.google.com/&quot; target=&quot;_blank&quot;&gt;Witryny Googli&lt;/a&gt; (więcej informacji o zakładaniu witryny znajdziesz &lt;a href=&quot;http://poradnikwebmastera.blox.pl/2009/11/Jak-szybko-zalozyc-witryne.html&quot; target=&quot;_blank&quot;&gt;tutaj&lt;/a&gt;). Po opublikowaniu (adres mojego gadżetu to:  &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;http://sites.google.com/site/kodatnikfiles/xml/PierwszyGadzet.xml&lt;/span&gt;), możemy sprawdzić jego działanie. Logujemy się do &lt;b&gt;Bloggera&lt;/b&gt;, przechodzimy na &lt;b&gt;Układ/Elementy strony&lt;/b&gt;, klikamy &lt;b&gt;Dodaj gadżet&lt;/b&gt;, wybieramy &lt;b&gt;Dodaj swoje własne&lt;/b&gt; i wpisujemy adres URL naszego gadżetu.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhDfAUlofn0ij8z0NLBlHdyXEdLh2jEtcDz7A-Lli0QseLd7qpxoiZGfzWo5MOSv2A0CLLAixh_EqlXauUxMnoK3lLbU8lCWiryVsXzGqvJXeJA2lc8nOa44Z0w9v9wzdhUQ-p8Tqno28/s1600/dodajemy.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;187&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhDfAUlofn0ij8z0NLBlHdyXEdLh2jEtcDz7A-Lli0QseLd7qpxoiZGfzWo5MOSv2A0CLLAixh_EqlXauUxMnoK3lLbU8lCWiryVsXzGqvJXeJA2lc8nOa44Z0w9v9wzdhUQ-p8Tqno28/s320/dodajemy.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
Klikamy &lt;b&gt;Dodaj wg adresów URL&lt;/b&gt; i jeśli wszystko przebiegło poprawnie powinniśmy otrzymać takie okienko:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEileJfNIkkDq4J1y6B762WFkAmXiCi362UspGH-tpACDm6SfWrsYZt7hS4hHGAKtIBJYy_T8vD4YlTOPG3p2Sf1FC_krGOr4ap_OM7c2pfbMqR83X0JwTbtfm29_iU87778j9KH8Vkpo2s/s1600/konfiguracja.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;312&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEileJfNIkkDq4J1y6B762WFkAmXiCi362UspGH-tpACDm6SfWrsYZt7hS4hHGAKtIBJYy_T8vD4YlTOPG3p2Sf1FC_krGOr4ap_OM7c2pfbMqR83X0JwTbtfm29_iU87778j9KH8Vkpo2s/s320/konfiguracja.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
Dajemy &lt;b&gt;Zapisz&lt;/b&gt; i nasz gadżet pojawi się na blogu.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgMtnDiDlg_NXVaknm8rW47RU02hRF8onMj8J9FpGy21d3wR94-v3M2XeVrXJb6wxE7g57snvbJc8rh3Cnw023BOyOBgQLaV0OOacQ7LFI374r5CxoEobd26rSc02yHjJwakl7C8qCCiQ/s1600/pierwszy.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgMtnDiDlg_NXVaknm8rW47RU02hRF8onMj8J9FpGy21d3wR94-v3M2XeVrXJb6wxE7g57snvbJc8rh3Cnw023BOyOBgQLaV0OOacQ7LFI374r5CxoEobd26rSc02yHjJwakl7C8qCCiQ/s1600/pierwszy.jpg&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
W następnych odcinkach pokaże jak skorzystać z dodatkowych opcji, zmienić kolory gadżetu (zgodnie z szablonem bloga), dostać się do danych bloga oraz utworzyć lokalizacje językowe.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;tip&quot;&gt;Wszystkie gadżety, które utworzymy i dodamy do Bloggera są &quot;cache&#39;owane&quot;. Oznacza to, że zmiany które wprowadzimy w kodzie nie będą widoczne od razu w gadżecie (Google &quot;trzyma&quot; wersję zbuforowaną mniej więcej 2 godziny). Jeżeli chcemy sprawdzić od razu zmiany to możemy, albo wyłączyć buforowanie (trochę pracy - modyfikacja szablonu), albo zapisać gadżet pod inną nazwą na serwerze (np. &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;DrugiGadzet.xml&lt;/span&gt;) i dodać go od nowa do naszego bloga.&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/1186795635339824870/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/11/piszemy-gadzet-do-bloggera-czesc-1.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/1186795635339824870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/1186795635339824870'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/11/piszemy-gadzet-do-bloggera-czesc-1.html' title='Piszemy gadżet do Bloggera - część 1'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhDfAUlofn0ij8z0NLBlHdyXEdLh2jEtcDz7A-Lli0QseLd7qpxoiZGfzWo5MOSv2A0CLLAixh_EqlXauUxMnoK3lLbU8lCWiryVsXzGqvJXeJA2lc8nOa44Z0w9v9wzdhUQ-p8Tqno28/s72-c/dodajemy.jpg" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-9112982009325709164</id><published>2009-11-26T01:02:00.001+01:00</published><updated>2009-12-05T01:05:42.280+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Struktury Danych"/><title type='text'>Lista powiązana - własna implementacja</title><content type='html'>Lista powiązana (&lt;i&gt;ang. linked list&lt;/i&gt;) to struktura dynamiczna, której każdy element tak zwany węzeł (&lt;i&gt;ang. node&lt;/i&gt;) posiada określoną wartość (lub wartości) oraz referencję do kolejnego węzła. Chcemy napisać prostą listę przechowującą wartości typu &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;String &lt;/span&gt;(łańcuchy tekstowe). Pierwszą czynnością jest napisanie odpowiedniej klasy, na podstawie której będziemy tworzyć węzły. &lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
 * Węzeł - element listy 
 * @author kodatnik.blogspot.com
 */
class Wezel {
 // łańcuch tekstowy
 private String napis;
 // referencja do kolejnego elementu/węzła
 private Wezel nastepny;
 
 // konstruktor domyślny, &quot;zerujemy&quot; pola
 public Wezel() {
  this(null, null);
 }
 
 // konstruktor dwuparametrowy
 public Wezel(String napis, Wezel nastepny) {
  // przypisujemy polu napis wartość parametru
  this.napis = napis;
  // przypisujemy polu nastepny wartość parametru  
  this.nastepny = nastepny;
 }
 
 // metoda zwraca pole nastepny (dostępowa)
 public Wezel pobierzNastepny() {
  return nastepny;
 }
 
 // metoda ustawia pole nastepny (modyfikująca)
 public void ustawNastepny(Wezel nastepny) {
  this.nastepny = nastepny;
 }
 
 // metoda zwraca pole napis (dostępowa)
 public String pobierzNapis() {
  return napis;
 }

 // metoda ustawia pole napis (modyfikująca)
 public void ustawNapis(String napis) {
  this.napis = napis;
 } 
  
 // zwraca &quot;węzeł&quot; w formie łańucha tekstowego (pole napis)
 public String toString() {
  return napis;
 }
}
&lt;/pre&gt;Mając gotową klasę dla węzłów, tworzymy klasę odpowiedzialną za prawidłowe funkcjonowanie listy. Nasza lista będzie listą jednostronną (dostęp możliwy tylko z jednego miejsca - początku listy).&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
 * Lista powiązana 
 * Przykład listy jednostronnej, jednokierunkowej, 
 * przechowującej łańcuchy tekstowe 
 * @author kodatnik.blogspot.com
 */
public class ListaPowiazana {

 // początek listy
 private Wezel poczatek;
 // liczba elementów
 private int rozmiar;
 
 // konstruktor domyślny, &quot;zerujemy&quot; pola
 public ListaPowiazana () {
  poczatek = null;
  rozmiar = 0;
 }
 
 // metoda wstawia na początek listy nowy węzeł z wartością przekazaną jako parametr
 public void wstawNaPoczatek(String napis) {
  // tworzymy nowy węzeł oraz zmieniamy referencję początku listy
  poczatek = new Wezel(napis, poczatek);
  // zwiększamy rozmiar listy (liczbę elementów)
  rozmiar++;
 }
 
 // metoda usuwa i zwraca węzeł znajdujący się na początku listy
 public Wezel usunZPoczatku() {
  // jeśli lista jest pusta zwracamy null
  if(czyPusta()) return null;

  // zapamiętujemy referencję początku listy
  Wezel temp = poczatek;
  // zmieniamy referencję początku listy na następny węzeł
  poczatek = poczatek.pobierzNastepny();
  // zmniejszamy rozmiar listy
  rozmiar--;
  // zwracamy zapamiętany początek listy (usunięty węzeł)
  return temp; 
 }
 
 // metoda sprawdza czy lista jest pusta
 public boolean czyPusta() {
  // zwracamy prawdę lub fałsz
  return (poczatek == null);
 }
 
 // metoda czyści listę &quot;zerując&quot; pola
 public void wyczysc() {
  poczatek = null;
  rozmiar = 0;
 }
 
 // metoda zwraca rozmiar listy (liczbę jej elementów)
 public int pobierzRozmiar() {
  return rozmiar;
 }
 
 // metoda wyświetla zawartość listy
 public void wyswietl() {
  //zapamiętujemy początek listy
  Wezel temp = poczatek;
  // wyświetlamy komunikat
  System.out.print (&quot;Początek -&amp;gt; &quot;);
  // dopóki referencja jest różna od null
  while( temp != null ) {
   // wyświetlamy węzeł (zadziała metoda toString() z klasy Wezel)
   System.out.print (temp + &quot; -&amp;gt; &quot;);
   // przechodzimy do następnego węzła
   temp = temp.pobierzNastepny();
  }
  // wyświetlamy null (dla oznaczenia końca listy)
  System.out.println(temp);
 }
 
 // metoda zwraca listę w formie łańcucha tekstowego
 // inny sposób wyświetlenia listy
 public String toString() {
  // tworzymy zmienną przechowującą łańcuch wyjściowy
  String wyjscie = &quot;&quot;;
  //zapamiętujemy początek listy
  Wezel temp = poczatek;
  // dopóki referencja jest różna od null  
  while( temp != null ) {
   // dodajemy zawartość węzła (zadziała metoda toString() z klasy Wezel) do zmiennej
   wyjscie +=  temp + &quot; &quot;;
   // przechodzimy do następnego węzła
   temp = temp.pobierzNastepny();
  }
  // zwracamy łańcuch tekstowy
  return wyjscie;
 }
}
&lt;/pre&gt;Sprawdźmy działanie listy dodając do niej przykładowe elementy.&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class TestListyPowiazanej {
 public static void main(String args[]) {
    
  // tworzymy listę powiązaną
  ListaPowiazana lista = new ListaPowiazana();
 
  // dodajemy elementy do listy
  lista.wstawNaPoczatek(&quot;Kasia&quot;);
  lista.wstawNaPoczatek(&quot;Marek&quot;);  
  lista.wstawNaPoczatek(&quot;Dorota&quot;);   
  lista.wstawNaPoczatek(&quot;Olga&quot;);   
  // wyświetlamy listę
  lista.wyswietl();
  // wyświetlamy rozmiar listy
  System.out.println (&quot;Liczba elementów listy: &quot; + lista.pobierzRozmiar());
  // usuwamy jeden element
  System.out.println (&quot;Usuwamy element: &quot; + lista.usunZPoczatku());
  // wyświetlamy listę  
  lista.wyswietl();  
 }
}
&lt;/pre&gt;Uruchomiona aplikacja:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Początek -&amp;gt; Olga -&amp;gt; Dorota -&amp;gt; Marek -&amp;gt; Kasia -&amp;gt; null
Liczba elementów listy: 4
Usuwamy element: Olga
Początek -&amp;gt; Dorota -&amp;gt; Marek -&amp;gt; Kasia -&amp;gt; null
&lt;/pre&gt;Powyższą klasę możemy z powodzeniem wykorzystać do implementacji w pełni dynamicznego stosu. Rozwiązane z wykorzystaniem tablic przedstawiłem w poście: &lt;a href=&quot;http://kodatnik.blogspot.com/2009/11/stos-implementacja-tablicowa.html&quot;&gt;Stos - implementacja tablicowa&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/9112982009325709164/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/11/lista-powiazana-wasna-implementacja.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/9112982009325709164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/9112982009325709164'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/11/lista-powiazana-wasna-implementacja.html' title='Lista powiązana - własna implementacja'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-7118856916260596956</id><published>2009-11-25T23:30:00.000+01:00</published><updated>2009-11-25T23:30:13.199+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Wieże Hanoi</title><content type='html'>Wieże Hanoi to problem polegający na przełożeniu z jednego słupka, na drugi, dysków o różnej średnicy. Przy przekładaniu można posługiwać się dodatkowym słupkiem stanowiącym bufor. Nie można kłaść dysku o większej średnicy na dysk o mniejszej średnicy, ani przekładać więcej niż jednego dysku jednocześnie. Chcemy napisać aplikację, która zasymuluje nam kolejne kroki potrzebne do przełożenia dysków. Zastosujemy algorytm rekurencyjny. &lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;// wykorzystujemy klasę Scanner z pakietu java.util
import java.util.*;

/**
 * Wieże Hanoi - rozwiązanie rekurencyjne
 * @author kodatnik.blogspot.com
 */
public class WiezeHanoi {
 
 // Rekurencyjna metoda przekładająca dyski o parametrach
 // dyski - liczba dysków
 // skad - oznaczenie słupka początkowego
 // dokad - oznaczenie słupka docelowego
 // bufor - oznaczenie słupka pomocniczego
 public static void hanoi(int dyski, char skad, char dokad, char bufor) {
  // jeśli są dyski
  if (dyski &gt; 0 ) {
   // przenieś (rekurencyjnie) n-1 dysków ze słupka A na słupek B posługując się słupkiem C
   hanoi(dyski - 1, skad, bufor, dokad);
   // wyświetl przeniesienie dysku
   System.out.println(skad + &quot; &gt; &quot; + dokad);
   // przenieś (rekurencyjnie) n-1 dysków ze słupka B na słupek C posługując się słupkiem A
   hanoi(dyski - 1, bufor, dokad, skad);
  }
 } 

 public static void main(String args[]) {
  
  Scanner sc = new Scanner(System.in);
  System.out.print (&quot;Ile dysków chcesz przełożyć: &quot; );

  // pobieramy od użytkownika liczbę dysków
  int n = sc.nextInt();     
     
  // wywołujemy metodę wyświetlającą kolejne przełożenia dysków
  // ze słupka A na słupek C korzystając ze słupka B
  hanoi(n , &#39;A&#39;, &#39;C&#39;, &#39;B&#39;);     
 }
}
&lt;/pre&gt;Uruchomiona aplikacja:&lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;Ile dysków chcesz przełożyć: 4
A &gt; B
A &gt; C
B &gt; C
A &gt; B
C &gt; A
C &gt; B
A &gt; B
A &gt; C
B &gt; C
B &gt; A
C &gt; A
B &gt; C
A &gt; B
A &gt; C
B &gt; C
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/7118856916260596956/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/11/wieze-hanoi.html#comment-form' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/7118856916260596956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/7118856916260596956'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/11/wieze-hanoi.html' title='Wieże Hanoi'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5790332872166558665.post-1415412264830415912</id><published>2009-11-20T23:13:00.004+01:00</published><updated>2009-11-20T23:24:26.566+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorytmy"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><title type='text'>Problem Józefa Flawiusza</title><content type='html'>Józef Flawiusz podczas wojny żydowsko-rzymskiej wraz 40 towarzyszami został otoczony przez Rzymian. Nie chcąc się poddać postanowili popełnić samobójstwo. Ustawili się w kręgu i co trzecia osoba odbierała sobie życie. Na końcu pozostał przy życiu przyjaciel Flawiusza oraz on sam. Oddali się w ręce wroga. Chcemy napisać aplikację, która zasymuluje nam, w jakiej kolejności ginęli żołnierze oraz, na której pozycji w kręgu ustawił się Flawiusz wraz ze swoim przyjacielem. Do rozwiązania tego problemu wykorzystamy przedstawioną wcześniej klasę &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Kolejka &lt;/span&gt;(&lt;a href=&quot;http://kodatnik.blogspot.com/2009/11/kolejka-implementacja-tablicowa.html&quot; target=&quot;_blank&quot;&gt;Kolejka - implementacja tablicowa&lt;/a&gt;).&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;/**
 * Problem Józefa Flawiusza
 * @author kodatnik.blogspot.com
 */
public class JozefFlawiusz {
    
 public static void main(String[] args) {
  // zmienna przechowuje liczbę żołnierzy (Flawiusz + 40)
  int zolnierze = 41;
  // zmienna określa co który będzie ginął
  int coKtory = 3;

  // tworzymy kolejkę o rozmiarze równych liczbie żołnierzy
  Kolejka k = new Kolejka(zolnierze);
  
  // dodajemy żołnierzy do kolejki (od 1 do 41)
  for (int i = 1; i &amp;lt;= zolnierze; i++)
   k.dodaj(i);
            
  // w pętli dopóki kolejka nie jest pusta
  while ( !k.czyPusta() ) {
   // przestawiamy dwóch żołnierzy z początku na koniec kolejki
   for (int i = 0; i &amp;lt; coKtory - 1; i++)
    k.dodaj(k.usun());

   // eliminujemy trzeciego (usuwamy go z kolejki)
   // i wyświetlamy jego numer ekranie
   System.out.print(k.usun() + &quot; &quot;);
  } 
  System.out.println();
 }
}
&lt;/pre&gt;Uruchomiona aplikacja: &lt;br /&gt;
&lt;pre class=&quot;console&quot;&gt;3 6 9 12 15 18 21 24 27 30 33 36 39 1 5 10 14 19 23 28 32 37 41
7 13 20 26 34 40 8 17 29 38 11 25 2 22 4 35 16 31
&lt;/pre&gt;Jak widać na wynikach generowanych przez program, Józef Flawiusz wraz z przyjacielem ustawili się na pozycji 16 i 31.</content><link rel='replies' type='application/atom+xml' href='http://kodatnik.blogspot.com/feeds/1415412264830415912/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://kodatnik.blogspot.com/2009/11/problem-jozefa-flawiusza.html#comment-form' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/1415412264830415912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5790332872166558665/posts/default/1415412264830415912'/><link rel='alternate' type='text/html' href='http://kodatnik.blogspot.com/2009/11/problem-jozefa-flawiusza.html' title='Problem Józefa Flawiusza'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>