Drzewo binarne

Drzewo binarne

Projekt: przedstawiający strukturę drzewa binarnego.

Wymagania programu:
– plik wejściowy input.txt posiada:

  • w linii 1 – ciąg liczb oddzielonych średnikami,
  • w linii 2 – liczbę wyszukiwaną,

– plik wyjściowy output.txt posiada:

  • w linii 1 – ilość szukaną,
  • w linii 2 – czas wyszukania,
  • w linii 3 – rodzica (jeśli liczba istnieje w drzewie, jeśli nie wystosowany jest odpowiedni komunikat a sam plik się na tym kończy),
  • w linii 4 – lewe dziecko (lub jego brak – NULL),
  • w linii 5 – prawe dziecko (lub jego brak – NULL),
  • w linii 6 – ścieżkę do liczby wyszukanej oddzielaną myślnikami.

Zasada działania:
Użytkownik po wystartowaniu programu posiada dwie możliwości:
1. Wygenerować nowy plik input po podaniu ilości linii drzew (tworzone są w taki sposób aby zapełnić całe drzewo np. dla 3 linii losowanych jest 7 liczb),
2. Wykorzystać własny plik input (w przypadku jego braku zostanie wygenerowany nowy),
po czym podaje liczbę do wyszukania, tworzony jest plik wyjściowy z zapisanymi danymi.

Dodatkowo wyświetlane jest czytelne drzewo binarne oraz krótkie w razie konieczności komunikaty.

Wykorzystane dane wejściowe…

-593;-389;-506;744;-6;381;-655;-50;357;-60;-817;-647;449;488;-446
-6

Dane wyjściowe…

Liczba do wyszukania: -6
Czas wykonania (w milisekundach): 0
Rodzic to: -389
Lewo: 744
Prawo: 381
Ścieżka: (-6)-(-389)-(-593)

Galeria:

Kod programu:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.StringTokenizer;

import javax.swing.JOptionPane;
public class glowna
	public static void main(String[] args) throws IOException {	
		
		//Program posiada 2 możliwosci: 
		//	A)użytkownik posiada swój własny plik input.txt
		//	B)program generuje wlasny, użytkownik ustala ilość linii drzewa oraz wyszukiwany element
		
		File pliko = new File("output.txt");	//Tworzy plik output.txt
		pliko.createNewFile();
		
		int ilosc_liczb = 0;	//Zmienna potrzebna do obliczenia ilosci liczb w zaleznosci od linii drzew (opcja B)
                                          //lub odczytania ilosci liczb z pliku (opcja A)
		int czyIstnieje = 0;	//Switch wybierający pomiedzy opcją A lub B
        String linia;	//Do wykorzystania string tokenizera
		int ile_liczb=3;	//Ilość fragmentów w linii (liczba lub zbiór spacjii)
        double ilosc_spacji=20;	// Ustala odstępy pomiędzy liczbami podczas rysowania drzewa w programie (im więcej 
                                   //linii tym większe odstępy
		int m=1;	//Dodatkowa zmienna
		String liczba;	//Tymczasowa zmienna wykorzystana przy odczytywaniu zmiennych z pliku
	    int ilosc_lin = 100;	//Startowa zmienna (później modyfikowana)
	    int n=0;	//Liczba wyszukiwana (później modyfikowana)
	    int sw=0;	//Zmienna wykorzystywana w switchu
	    
	    try{	//Zabezpieczenie gdy zostanie podana np. litera lub nieprzyjmowana wartość plik będzie wygenerowany
		sw = Integer.parseInt(JOptionPane.showInputDialog("1.Mam swoj plik input \n2.Wygeneruj\n\nWybierz 1 lub 2!"));
	    }catch(Exception e){
            System.out.print("BŁĄD ");}   

	    switch (sw){
	         case 1 : {
	        	 File plikz = new File("input.txt");
	        	 if(plikz.exists() == true)
	        	 {
	        	 czyIstnieje=1;	//Na podstawie tej zmiennej uruchamiane są niektóre fragmenty kodu
	        	 FileReader plik=new FileReader("input.txt");
	     		 BufferedReader bufor=new BufferedReader(plik);
	     		 linia = bufor.readLine();
	    		 StringTokenizer token=new StringTokenizer(linia,";");
	    		 ilosc_liczb=token.countTokens(); //Zliczenie ilości liczb w przypadku własnego pliku
	     		 bufor.close();
	        	 }
	        	 else
	        	 {
	        		 System.out.print("Plik nie istnieje zostanie więc wygenerowany\n");
	        		 czyIstnieje=0;
	        	 }
	           break;
	         }
	         case 2 : {
	        	 czyIstnieje=0;
	            break;
	         }
	         default : {
	        	 System.out.print("Podano złą daną. Plik zostanie wygenerowany\n");
	        	 czyIstnieje=0;
	         }
	    }        

	    if(czyIstnieje==0)	//Generowanie pliku
	    {
			File pliki = new File("input.txt");
			pliki.createNewFile();
			
			//Zapis losowych liczb do pliku z przedziału ((-1000)-1000)////////////////////////////////////
	        ilosc_lin=Integer.parseInt(JOptionPane.showInputDialog("Ile linii drzewa chcesz utworzyć?"));
	        int liczb_w_lini=1;	//Wymagane do obliczenia ilości liczb
	        
	        for(int s=1;s<ilosc_lin;s++)	//Oblicza odstępy w zależności od ilości lini (im więcej tym większe)
	        	ilosc_spacji=ilosc_spacji*2;
	        
	        for (int z=1;z<=ilosc_lin;z++)	//Pętla obliczająca ilość liczb
			{
				ilosc_liczb=ilosc_liczb+liczb_w_lini;
				liczb_w_lini=liczb_w_lini*2;
			}
	    }
        
        int tab[] = new int[ilosc_liczb+1];	//Tablica o rozmiarze ilości wszystkich liczb
        int ile;	//Zmienna dbająca o unikatowość losowanych liczb
          
        if(czyIstnieje==0)
        {
		FileWriter plik2 = new FileWriter("input.txt");
        BufferedWriter buforWy = new BufferedWriter(plik2);
		for (int y=1;y<tab.length-1;y++)	//Pętla losująca liczby i odrazu zapisująca wartości do tablicy a potem do pliku
		{
			do{
			ile=0;	
			tab[y]=(int) (Math.random()*2000-1000);
			for(int il=0;il<tab.length-1;il++)
			{
				if(tab[il]==tab[y])
					ile++;
			}
			}while(ile!=1);
			buforWy.write(Integer.toString(tab[y]));
			buforWy.write(";");
		}
		
		do{
		ile=0;	
		tab[ilosc_liczb-1]=(int) (Math.random()*2000-1000);	//Ostatnia liczba zapisywana do pliku aby nie tworzyć 
                                                                          //zbędnego średnika w pliku (na końcu)
		for(int il=0;il<tab.length-1;il++)
		{
			if(tab[il]==tab[ilosc_liczb-1])
				ile++;
		}
		}while(ile!=1);
		buforWy.write(Integer.toString(tab[ilosc_liczb-1]));
        buforWy.close();

        //"Narysowanie" drzewa w programie (opcja B)///////////////////////////////////////
        
		FileReader plik=new FileReader("input.txt");
		BufferedReader bufor=new BufferedReader(plik);


		while((linia = bufor.readLine())!=null)
		{
			StringTokenizer token=new StringTokenizer(linia,";");	
			for(int i=0;i<ilosc_lin;i++)
			{
				ilosc_spacji=ilosc_spacji/2;	//Obliczanie odstępów pomiędzy liczbami
				
				for(int j=ile_liczb;j>0;j--)
				{
					if((j-1) % 3==1)	//Program sprawdza czy wypisać liczbę czy utworzyć odstęp
					{
							liczba=token.nextToken();	//Pobieranie elementu z pliku
							System.out.print(liczba);	//Wypisanie elementów w programie
							tab[m]=Integer.parseInt(liczba);	//Zapisanie elementu ponownie w tablicy
							m++;	//Przejscie do następnego elementu tablicy
					}
					else
					{
						for(double k=0;k<ilosc_spacji-1.75;k++)	
						{
							System.out.print(" ");	//Tworzenie odstępu
						}
					}	
				}
				System.out.print("\n");
				ile_liczb=ile_liczb*2;
			}	
		}
		bufor.close();	
		
		FileWriter plik4 = new FileWriter("input.txt");
        BufferedWriter buforDod = new BufferedWriter(plik4);		
		
		for (int y=1;y<tab.length-1;y++)	
		{
			buforDod.write(Integer.toString(tab[y]));
			buforDod.write(";");
		}
		buforDod.write(Integer.toString(tab[ilosc_liczb]));
		
		n=Integer.parseInt(JOptionPane.showInputDialog("Co chcesz wyszukac?"));
		buforDod.newLine();
		buforDod.write(Integer.toString(n));
		buforDod.close();
        } 
        else
        {
       	 		FileReader plik=new FileReader("input.txt");
       	 		BufferedReader bufor=new BufferedReader(plik);
       	 		linia = bufor.readLine();
       	 		StringTokenizer token=new StringTokenizer(linia,";");
       	 		for(int z=1;z<tab.length;z++)
       	 		{
       	 			liczba=token.nextToken();
       	 			tab[z]=Integer.parseInt(liczba);
       	 		}
       	 		n=Integer.parseInt(bufor.readLine());
       	 		bufor.close();   
       	 		
       	 		//"Narysowanie" drzewa w programie (opcja A)///////////////////////////////////////
       	 		ilosc_lin=0;
       			for (double y=tab.length;y>1;y=y/2)	
       			{
       				ilosc_lin++;
       			}
       	 	
       			for(int s=1;s<ilosc_lin;s++)	//Oblicza odstępy w zależności od ilości lini (im więcej tym większe)
    	        	ilosc_spacji=ilosc_spacji*2;
       			
       			int il=1;
    			for(int i=0;i<ilosc_lin;i++)
    			{
    				ilosc_spacji=ilosc_spacji/2;	//Obliczanie odstępów pomiędzy liczbami
    				
    				for(int j=ile_liczb;j>0;j--)
    				{
    					if((j-1) % 3==1)	//Program sprawdza czy wypisać liczbę czy utworzyć odstęp
    					{
    						if(il<ilosc_liczb+1)
    						{
    							System.out.print(tab[il]);	//Wypisanie elementów w programie
    							il++;	//Przejscie do następnego elementu tablicy
    						}
    					}
    					else
    					{
    						for(double k=0;k<ilosc_spacji-1.75;k++)	
    						{
    							System.out.print(" ");	//Tworzenie odstępu
    						}
    					}	
    				}
    				System.out.print("\n");
    				ile_liczb=ile_liczb*2;
    			}   	 		   	 		
        }
        
        long start=System.nanoTime();	//Obliczanie czasu
        
		//Zapisanie wyników w pliku output///////////////////////////////////////////////////
			
        FileWriter plik3 = new FileWriter("output.txt");
        BufferedWriter buforWy2 = new BufferedWriter(plik3);
		buforWy2.write("Liczba do wyszukania: "+Integer.toString(n));
		buforWy2.newLine();
		int miejsce=0;	//Pierwsze położenie wyszukiwanego elementu
		for (int y=1;y<tab.length;y++)	//Wyszukiwanie wymaganego elementu w tablicy
		{
			if(tab[y]==n)
				miejsce=y;
		}
		
		long stop=System.nanoTime();	//Koniec obliczania czasu
		buforWy2.write("\nCzas wykonania (w milisekundach): "+(stop-start)/1000000);
		buforWy2.newLine();
		
		if(miejsce==0)
			buforWy2.write("BRAK WYSZUKIWANEJ LICZBY!");
		else
		{
		if(miejsce==1)	//Wyjątek dla pierwszego elementu
		{
			buforWy2.write("NULL!!");
			buforWy2.newLine();
			if(ilosc_liczb==1)
			{
			buforWy2.write("NULL!!");
			buforWy2.newLine();
			}
			else
			{
			buforWy2.write("NULL!!");
			buforWy2.newLine();
			buforWy2.write("Prawo: "+tab[miejsce+1]);
			buforWy2.newLine();
			}
		}
		else if(miejsce % 2==1)	//Wyszukiwanie rodzica, prawego jak i lewego sąsiada
		{
			buforWy2.write("Rodzic to: "+tab[(miejsce-1)/2]);
			buforWy2.newLine();
			buforWy2.write("Lewo: "+tab[miejsce-1]);
			buforWy2.newLine();
			if(miejsce==ilosc_liczb)
				buforWy2.write("Prawo: NULL!!");
			else
				buforWy2.write("Prawo: "+tab[miejsce+1]);
			buforWy2.newLine();
		}
		else
		{
			buforWy2.write("Rodzic to: "+tab[miejsce/2]);
			buforWy2.newLine();
			buforWy2.write("Lewo: "+tab[miejsce-1]);
			buforWy2.newLine();
			
			if(miejsce==ilosc_liczb)
				buforWy2.write("Prawo: NULL!!");
			else
				buforWy2.write("Prawo: "+tab[miejsce+1]);
			buforWy2.newLine();
		}
		if(miejsce==1)	//Ścieżka dla pierwszego elementu
		{
			if(tab[1]<0)
				buforWy2.write("Ścieżka: ("+tab[1]+")");
			else
				buforWy2.write("Ścieżka: "+tab[1]);
			buforWy2.newLine();
		}
		else	//Ścieżka dla reszty
		{
			if(tab[miejsce]<0)
				buforWy2.write("Ścieżka: ("+tab[miejsce]+")");
			else
				buforWy2.write("Ścieżka: "+tab[miejsce]);
			for(int x=1;x<ilosc_lin;x++)
			{
				if(miejsce % 2==1)
				{
					if(miejsce!=1)
					{
						if(tab[(miejsce-1)/2]<0)
							buforWy2.write("-("+tab[(miejsce-1)/2]+")");
						else
							buforWy2.write("-"+tab[(miejsce-1)/2]);
					miejsce=(miejsce-1)/2;
					}
				}
				else
				{
					if(miejsce!=1)
					{
						if(tab[miejsce]/2<0)
							buforWy2.write("-("+tab[(miejsce)/2]+")");
						else
							buforWy2.write("-"+tab[(miejsce)/2]);
					miejsce=(miejsce)/2;
					}
				}
			}
		}
		}
		buforWy2.close();	
	}
}

Słowniczek pojęć:

W informatyce drzewo binarne to jeden z rodzajów drzewa (struktury danych), w którym liczba synów każdego wierzchołka wynosi nie więcej niż dwa. Wyróżnia się wtedy lewego syna i prawego syna danego wierzchołka.