Sortowanie szybkie - QuickSort

Sortowanie szybkie działa na zasadzie podziału tablicy na dwie części. Jedna z nich zawiera elementy o wartościach mniejszych, a druga elementy o wartościach większych od wartości elementu dzielącego (ang. pivot). Jako element dzielący można wybrać element środkowy, element pierwszy lub element ostatni. Każda z części tak podzielonej tablicy jest poddawana od nowa algorytmowi sortowania szybkiego.
/**
 * Sortowanie szybkie - QuickSort
 * @author kodatnik.blogspot.com 
 */ 
public class SortowanieSzybkie {
 // metoda zamienia miejscami elementy o indeksach i oraz j
 // w tablicy przekazanej jako parametr
 private static void zamien(int[] wejscie, int i, int j) {
  int temp = wejscie[i];
  wejscie[i] = wejscie[j];
  wejscie[j] = temp;
 }  
 
 // metoda dzieli tablicę (od indeksu p do indeksu k) na dwie części
 // - elementy mniejsze od wybranego elementu
 // - elementy większe od wybranego elementu
 private static int podzial(int[] wejscie, int p, int k) {
 
  // wybieramy element wg którego będziemy dzielić
  // np. element ostatni
  int element = wejscie[k];
  
  // ustalamy zakres na którym będziemy operować
  int i = p; 
  int j = k - 1;
  
  // pętla wyszukuje kolejne elementy większe i mniejsze od 
  // elementu dzielącego (zmienna element)
  while(i <= j) {
   while (wejscie[i] <= element && i < k) i++;
   while (wejscie[j] > element && j > p) j--;
   
   // jeśli elementy są na niewłaściwych pozycjach zamieniamy je
   if (i < j) zamien(wejscie, i, j);
   // jeśli indeksy się zrównają kończymy pętlę
   if (i == j) break;
  }
   
  // na końcu wstawiamy element dzielący na właściwą pozycję
  zamien(wejscie, i, k);
    
  // i zwracamy tę pozycję
  return i;
 } 
 
 // metoda sortuje elementy tablicy przekazanej jako parametr
 // dodatkowo w jej wywołaniu podajemy indeks pierwszego i ostatniego elementu
 public static void sortowanieSzybkie(int[] wejscie, int i, int j) {

  // jeśli indeksy są równe lub niepoprawne zakończ działanie
  if ( j <= i ) return;

  // dzielimy tablicę na części, indeks miejsca podziału zapisujemy w zmiennej os (oś)
  int os = podzial(wejscie, i, j);
  
  // rekurencyjnie dokonujemy posortowania lewej i prawej części naszej tablicy
  sortowanieSzybkie(wejscie, i, os-1);
  sortowanieSzybkie(wejscie, os+1, j);  
 }   
 
 // metoda wyświetla zawartość tablicy przekazanej jako parametr na ekranie
 public static void pokazTablice(int[] wejscie) {
  // każdy element znajdujący się w tablicy wyświetlamy na ekranie
  for(int x : wejscie) System.out.print (x + " ");
  System.out.println ();
 }

 public static void main(String[] args) {
  // tworzymy tablicę wypełniając ją od razu danymi
  int[] tablica = {4, 6, 1, 2, 3, 8, 7, 9, 5};
  
  // wyświetlamy tablicę na ekranie
  pokazTablice(tablica);
  // sortujemy tablicę
  sortowanieSzybkie(tablica, 0, tablica.length-1);
  // wyświetlamy posortowaną tablicę na ekranie
  pokazTablice(tablica);  
 }
}
Optymalizacja algorytmu polega na właściwym doborze elementu dzielącego. Najczęściej dokonuje się tego poprzez jego losowy wybór, bądź też wyznaczenie mediany z rozpatrywanych elementów.
Uruchomiona aplikacja:
4 6 1 2 3 8 7 9 5 
1 2 3 4 5 6 7 8 9 

Suma cyfr w liczbie rekurencyjnie

W jednym z wcześniejszych postów liczyliśmy sumę cyfr w liczbie za pomocą iteracji. Poniżej rozwiązanie tego zadania z wykorzystaniem rekurencji.
// wykorzystujemy klasę Scanner z pakietu java.util
import java.util.*;

/**
 * Suma cyfr w liczbie rekurencyjnie
 * @author kodatnik.blogspot.com 
 */ 
public class SumaCyfr {
 
 // metoda sumaCyfr zwraca sumę cyfr liczby 
 // przekazanej jako parametr jej wywołania
 public static int sumaCyfr(int liczba) {

  // jesli liczba mniejsza od 10 zwróć ją (warunek kończący wywołania rekurencyjne)
  if (liczba < 10)
   return liczba;

  // w przeciwnym razie bierzemy ostatnią cyfrę (modulo 10) plus rekurencyjne
  // wywołanie naszej metody z parametrem będącym liczbą bez ostatniej cyfry
  return (liczba % 10) + sumaCyfr(liczba / 10);
 }
 
 public static void main(String[] args){
  
  Scanner sc = new Scanner(System.in);
  System.out.print ("Podaj liczbę: " );
  
  // pobieramy od użytkownika liczbę
  int liczba = sc.nextInt();
  
  // wyświetlamy na ekranie sumę cyfr w liczbie
  System.out.println("Suma liczb: " + sumaCyfr(liczba));

 }
}
Uruchomiona aplikacja:
Podaj liczbę: 12345
Suma liczb: 15

Ciąg Fibonacciego rekurencyjnie i iteracyjnie

Ciąg Fibonacciego to ciąg liczb naturalnych określony wzorem f(n)=f(n-1)+f(n-2) dla danych f(0)=0 i f(1)=1. Chcemy napisać metodę obliczającą n-ty wyraz tego ciągu. Zastosujemy rozwiązanie rekurencyjne (metoda fibR()) oraz iteracyjne (metoda fibI()).
// wykorzystujemy klasę Scanner z pakietu java.util
import java.util.*;

/**
 * N-ty element ciągu Fibonacciego rekurencyjnie i iteracyjnie
 * @author kodatnik.blogspot.com 
 */ 
public class CiagFibonacciego {
 
 // metoda zwraca n-ty element ciągu Fibonacciego
 // wersja rekurencyjna 
 public static int fibR(int n) {
  
  if (n < 2) return n; // jeśli n<2 zwracamy n (dla zera 0 dla jedynki 1)
  
  return fibR(n-1) + fibR(n-2); // jeśli nie to zwracamy sumę elementu poprzedniego i jeszcze wcześniejszego
 }
 
 // metoda zwraca n-ty element ciągu Fibonacciego
 // wersja iteracyjna  
 public static int fibI(int n) {
  int elementA = 0; // zmienne pomocnicze symbolizujące
  int elementB = 1; // element poprzedni B i jeszcze wcześniejszy A
  
  int wynik = 0; // zmienna wynik, pod którą podstawimy obliczoną wartość
  
  if (n < 2) return n; // jeśli n<2 zwracamy n (dla zera 0 dla jedynki 1)
   
   // jeśli nie to liczymy n=ty element ciagu
   for(int i = 2; i <= n; i++){ 
    wynik = elementA + elementB; // pod wynik podstawiamy sumę poprzednich elementów
    elementA = elementB; // modyfikujemy zmienne przechowujące
    elementB = wynik;  // dwie ostatnie wartości
   }
  
  return wynik; // zwracamy wynik
 }
 
 public static void main(String[] args) {
  
  Scanner sc = new Scanner(System.in);
  System.out.print ("Który element ciągu Fibonacciego chcesz obliczyć: " );

  // pobieramy od użytkownika liczbę
  int n = sc.nextInt();

  // wyświetlamy na ekranie obliczony element
  System.out.println( n + "-ty element ciągu Fibonacciego (rekurencja) wynosi: " + fibR(n));
  System.out.println( n + "-ty element ciągu Fibonacciego (iteracja) wynosi: " + fibI(n));  
 
 }
}
Uruchomiona aplikacja:
Który element ciągu Fibonacciego chcesz obliczyć: 10
10-ty element ciągu Fibonacciego (rekurencja) wynosi: 55
10-ty element ciągu Fibonacciego (iteracja) wynosi: 55
Rozwiązanie rekurencyjne jest bardzo kosztowne. Sprawdź czas wykonania jednej i drugiej metody dla dużych n, bądź też liczbę rekurencyjnych wywołań potrzebnych do takich obliczeń.

Dodajemy Wykop do Bloggera

Wykop to serwis do którego możemy dodawać ciekawe strony. Każda dodana informacja jest oceniana i dyskutowana przez społeczność internautów. Od niej zależy czy dany wpis będzie popularny czy też nie. Jednym ze sposobów wzbogacenia Bloggera o możliwość dodawania wpisów do wykopu jest mój gadżet Podziel się. W tym poście przedstawię drugą możliwość. Na stronie wykopywarki mamy dostępne kilka kodów, które można umieścić bezpośrednio w szablonie naszej strony. Informacja o osobach, które również uznały nasz post za ciekawy (wykopały go) będzie na bieżąco aktualizowana. Pytanie tylko gdzie go wkleić. Możliwości jest kilka, albo na początku treści posta, albo w jego nagłówku, albo pod postem. Przyjrzyjmy zatem się standardowej wykopywarce (duża ikona z ilością wykopów). Zmodyfikujmy trochę kod tak, aby edytor Bloggera przyjął go bez zastrzeżeń.
<script language='javascript'>
var wykop_url=location.href;
var wykop_title=document.title; 
var wykop_desc=encodeURIComponent('Podaj opis');
var widget_bg='FFFFFF';
var widget_type='normal';
var widget_url='http://www.wykop.pl/widget.php?url='+(wykop_url)+'&amp;title='+(wykop_title)+'&amp;desc='+(wykop_desc)+'&amp;bg='+(widget_bg)+'&amp;type='+(widget_type);
document.write("<div style='float: right;'><iframe border='0' frameborder='0' scrolling='no' src='"+widget_url+"' style='border:none;width:72px;height:65px;overflow:hidden;margin:0;padding:0;'/></div>");
</script>
Dodałem dodatkowo umiejscowienie ikony (prawa strona - <div style='float: right;'>) oraz zamieniłem kilka znaków, które powodują błędy Bloggera. Mając już kod, spróbujmy go dodać do naszych postów, a dokładnie do tytułu posta. Logujemy się do Bloggera, wybieramy Układ/Edytuj kod HTML. Zaznaczamy Rozszerz szablony widżetów. W podglądzie źródła naszego szablonu szukamy (Ctrl+F) następującego fragmentu:
<b:includable id='post' var='post'>
  <div class='post hentry uncustomized-post-template'>
Wklejamy poniżej zmodyfikowany kod wykopu. Wszystko funkcjonuje prawidłowo przy wyświetlonych pojedynczych wpisach. Na stronie głównej naszego bloga ikonka wykopu będzie niestety starała się dodać adres bloga, a nie poszczególnych postów, więc....wykorzystamy wyrażenie warunkowe, które będzie dodawało wykopywarkę tylko na stronach postów, a nie na stronie głównej.
<b:if cond='data:blog.pageType != "index"'>
 Nasz zmodyfikowany kod wykopu
</b:if>
Efekt widoczny na moim blogu. Oczywiście możemy zmienić miejsce dodania ikony jak i również jej położenie (do prawej, do lewej, na środku itd.). Na przykład dodanie ikony do treści posta, to odnalezienie w szablonie następującego kodu:
<div class='post-body entry-content'>
...i wstawienie poniżej tego co poprzednio. Sposób ten umożliwia, w zależności od naszych preferencji, dodanie ikon/linków do dowolnych serwisów (zobacz np. serwis Wyczaj to)
Jeśli nie odpowiada nam duża ikona to możemy wybrać z wykopywarki kod obsługujący wersję compact.

Podziel się - gadżet do Bloggera

Często na blogach mamy możliwość dodania czytanego posta do serwisów społecznościowych takich jak Wykop czy Twitter. W Bloggerze jedyną normalną możliwością skorzystanie z tej formy promocji bloga jest pasek nawigacyjny (Navbar). Niestety nie jest on lubiany przez twórców blogów jak i również jego oferta serwisów jest minimalna (brak jakiegokolwiek rodzimego serwisu). Gdy nie ma tego czego potrzebujemy, musimy wziąć sprawy w swoje ręce. Napisałem prosty gadżet do Bloggera umożliwiający podzielenie się blogiem/postem w serwisach społecznościowych. Dodatek dostępny jest w ogólnodostępnym katalogu gadżetów Bloggera. Jak go dodać. Logujemy się do Bloggera, wybieramy Układ/Elementy strony. Na pokazanym widoku naszego bloga, klikamy Dodaj gadżet. Otworzy się okienko z możliwością wyboru i dodania gadżetu. Wybieramy Więcej gadżetów w pole wyszukiwania wpisujemy Podziel się (patrz obrazek). Po znalezieniu gadżetu możemy go dodać klikając ikonkę z plusem.



Dodatkowo możemy dokonać prostej konfiguracji wpisując inny tytuł, położenie ikonek oraz serwisy, które mają być obsługiwane (klikając aktualizacja, nasze ustawienia odświeżą się). Gadżet dostosuje do wybranych parametrów swoją wysokość.


Po dodaniu do bloga możemy umiejscowić go albo z boku (Sidebar) albo w dowolnym innym miejscu (wystarczy przeciągnąć prostokąt z gadżetem w inne miejsce układu strony). Wersja online gadżetu obok.
W zależności od tego czy jesteśmy na stronie głównej bloga czy też czytamy post, do serwisu społecznościowego trafi odpowiednio adres URL bloga, tytuł bloga, opis bloga lub też adres URL posta, tytuł posta.
Jeśli korzystasz z Bloggera w wersji angielskiej, to po kliknięciu Add a Gadget w pole wyszukiwania wpisz Sociable.

Aktualizacja: 15-02-2010
Dodana obsługa Google Buzz.

Aktualizacja: 01-04-2010
Poprawiona obsługa Wykopu.

Dodajemy Favicon do Bloggera

Standardowo Blogger udostępnia dla blogów pomarańczową ikonkę pojawiającą się przy pasku adresu naszej przeglądarki, Nic nie stoi na przeszkodzie, aby ją zmienić na własną bardziej oddającą treść naszego bloga. Plik ikony powinien mieć rozmiary 16x16 pikseli. Domyślny format to ICO (większość przeglądarek obsługuje również poprawnie pliki PNG i GIF). Do skonwertowania pliku graficznego do pliku ICO możemy wykorzystać darmowy program IrfanView, bądź też poszukać darmowych ikonek w sieci. Idealnie do tego nadaje się wyszukiwarka Google (wybieramy grafika/wyszukiwanie zaawansowane/określamy rozmiar 16x16). Wybrany obrazek musimy umieścić na serwerze i dokonać zmian w kodzie naszego szablonu (nadpisać domyślne ustawienia Bloggera). Logujemy się do Bloggera, wybieramy Układ/Edytuj kod HTML. W podglądzie źródła naszego szablonu szukamy (Ctrl+F) następującego fragmentu:
<b:include data='blog' name='all-head-content'/>
Jest to fragment odpowiedzialny za utworzenie zawartości nagłówka naszej strony. Poniżej powyższego kodu dopisujemy linijkę:
<link href='Adres URL pliku ikonki' rel='shortcut icon' 
type='image/vnd.microsoft.icon'/>
Gdzie Adres URL pliku ikonki to ścieżka dostępu do naszej ikonki (pliku z rozszerzeniem .ico). Efekt widoczny jest na moim blogu (zobacz w pasku tytułu przeglądarki).
Ikonki mogą być również animowane. Wykorzystywany jest do tego celu format GIF.
Rozmiar ikonki może być większy (np. 32x32 czy 48x48). Przeglądarka odpowiednio przeskaluje sobie nasz plik.

Zmieniamy tytuł strony w Bloggerze

Standardowo tytuł pojedynczego postu w Bloggerze jest umieszczany w kolejności (tytuł bloga + tytuł postu). Większość wyszukiwarek internetowych opiera swoje wyniki między innymi na tytule strony. Spróbujmy zatem zmienić kolejność elementów (najpierw tytuł posta, potem tytuł bloga). Logujemy się do Bloggera, wybieramy Układ/Edytuj kod HTML. W podglądzie źródła naszego szablonu szukamy (Ctrl+F) następującego fragmentu:
<title><data:blog.pageTitle/></title>
Jest to fragment odpowiedzialny za stworzenie tytułu strony. Zamieniamy go z następującym kodem:
<b:if cond='data:blog.url == data:blog.homepageUrl'>
<title><data:blog.pageTitle/></title>
<b:else/>
<title><data:blog.pageName/> | <data:blog.title/></title>
</b:if>
Dajemy Zapisz i gotowe. Powyższy fragment będzie tworzył tytuł strony w zależności od tego czy jesteśmy na stronie głównej (tytuł bloga) czy też na stronie konkretnego posta (tytuł posta | tytuł bloga). Oczywiście znak rozdzielający tytuły możemy wybrać dowolnie (w przykładzie jest to pionowa kreska). Efekt widoczny jest na moim blogu (zobacz w pasku tytułu przeglądarki).
Wszystkie tagi, z których możesz korzystać w swoim szablonie (np. <data:blog.title/> - tytuł bloga) znajdziesz tutaj (język ang.).

Popularne posty