Program działający na zbiorach

0

Witam,

Mam do napisania program działający na zbiorach. Treść zadanie jest następująca:

Stworzyć klasę modelującą zbiory elementów np. 
A = { 1, 12, 4, 5, 7, 3} 
B = { 1, 4, 13, 7, 6, 9} 
Daj klasie możliwości wykonania na obiektach klasy operacji następujących: 
1. suma zbiorów A + B = { 1, 12, 4, 5, 7, 3, 13, 6, 9} 
2. część wspólna A * B = { 1, 4, 7 } 
3. różnica A – B = {12, 5, 3} 
4. różnica B – A = {13, 6, 9} 
5. różnica symetryczna = {12, 5, 3, 13, 6, 9} 
Dodaj przynajmniej operacje czytania i drukowania zbiorów, dodawania i usuwania elementów zbioru. Zadbaj o najniższą z możliwych złożoność obliczeniową operacji. 

Program jest napisany. Sęk w tym że nie działa poprawnie. Jedyne co działa to wyświetlanie liczb. Gdy chcę np. obliczyć sumę, to na wyjściu wyrzuca mi "kosmiczne" liczby. Nie wiem czym to może być spowodowane.

Sam fakt że się kompiluje uznaje za duży sukces. Program jest dość długi. Oto on:


#include <iostream>

using namespace std;

class Set{
public:
	int	number;
	int	* elems;
    
	Set(int tab[], int n)
	{
	    number = n;
		elems = new int[n];
		for(int i = 0; i < n; i++) elems[i] = tab[i];
    }
	
	Set(Set &obj)
	{
        number = obj.number;
		elems = new int[number];
		for(int i = 0; i < number; i++) elems[i] = obj.elems[i];
    }
    
	~Set()
    {
		delete [] elems;
    }
    
    void swap(int &a, int &b)
    {
         int temp = a;
         a = b;
         b = temp;
    }
    
    void bubblesort(int tab[], int n)
    {
         int p;
         for (int i=n-1; i>0; i--) 
         { 
         p=1; 
         for (int j=0; j<i; j++) 
           if (tab[j] > tab[j+1]) 
           { 
               swap(tab[j], tab[j+1]); 
               p=0; 
           } 
       if (p) break; 
       } 
    } 
    
    void rdup(int * tab, int n)
    {
         int *current;
         int *end = tab + n - 1;

          for ( current = tab + 1; tab < end; tab++, current = tab + 1 )
          {
              while ( current < end )
               {
            if ( *current == *tab )
            {
                *current = *end--;
            }
            else
            {
                current++;
            }
        }
    }
}    
         
	
	void sum(Set &a)
	{
		int	n = number;
		int * tab = new int[n + a.number];
		bool czy;
		
		for(int i = 0; i < n; i++) tab[i] = elems[i];
		
		for(int i = 0; i < a.number; i++){
  	    czy = false;
			for(int j = 0; j < n; j++){
				if(elems[j] == a.elems[i]) czy = true;
				else czy = czy | false;}
			
			if(!czy){
				tab[n] = a.elems[i];
				n++;}}
		
        bubblesort(tab, a.number);
        rdup(tab, a.number);		
		system("cls");
        cout << "Suma zbiorow to: ";		
		for (int i = 0; i < n; i++)
        cout << tab[n] << " "; 
        
        delete [] tab;
        cout << endl;
        system("PAUSE");
    }
    
    void relative_complement(Set &a)
    {
         int n = 0;
         int * tab = new int[number];
         bool czy;
         
         for (int i = 0; i < number; i++){
             czy = false;
             for (int j = 0; j < a.number; j++){
                 if(elems[i] == a.elems[j]) czy = true;
                 else czy = czy | false;}
    
             if(!czy){
                 tab[n] = elems[i];
                 n++;}}
             
        bubblesort(tab, number);
        rdup(tab, number);         
        system("cls");
        cout << "Roznica zbiorow to: ";		
        for (int i = 0; i < n; i++)
        cout << tab[n] << " "; 
        cout << endl;        
        delete [] tab;
        system("PAUSE");      
                 
    }
    
    void symmetric_diff(Set &a)
    {
         int n = 0;
         int m = 0;
         int * tab = new int[number];
         int * tab2 = new int[a.number];
         int * mer = new int[number + a.number]; 
         bool czy;
         
         for (int i = 0; i < number; i++){
             czy = false;
             for (int j = 0; j < number; j++){
                 if (elems[i] == a.elems[j]) czy = true;
                 else czy = czy | false;}
         
         if(!czy){
                 tab[n] = elems[i];
                 n++;}}
                 
         for (int k = 0; k < a.number; k++){
             czy = false;
             for (int l = 0; l < number; l++){
                 if (a.elems[k] == elems[l]) czy = true;
                 else czy = czy | false;}
                 
         if (!czy){
                   tab2[m] = a.elems[k];
                   m++;}}
         
         for (int o = 0; o < number; o++)
             mer[o] = tab[o];
         
         for (int p = number; p < number + a.number; p++)
             mer[p] = tab[p-number];
                  
         bubblesort(mer, number + a.number);
         rdup(mer, number + a.number);
         cout << "Roznica symetryczna to: ";         
         for (int q = 0; q < number + a.number; q++)
         cout << mer[q] << " ";    
         
         system("PAUSE");
    }        
  
	void intersection (Set &a)
	{
		int	n = 0;
	    int * tab = new int[(number > a.number) ? number : a.number];
		bool czy;
		
		for(int i = 0; i < a.number; i++){
			czy = false;
			for(int j = 0; j < number; j++){
				if(elems[j] == a.elems[i]) czy = true;
				else czy = czy | false;}
			
			if(czy){
				tab[n] = a.elems[i];
				n++;}}
		
		bubblesort(tab, a.number);
		rdup(tab, a.number);
        system("cls");
        cout << "Czesc wspolna zbiorow to: ";		
        for (int i = 0; i < n; i++)
        cout << tab[n] << " "; 

        delete [] tab;
        cout << endl;        
        system("PAUSE");
    }
    
    void dodaj(int n)
    {
         int * temp = new int[number];
         for (int i = 0; i < number; i++)
         temp[i] = elems[i];
         delete [] elems;
         elems = new int[number + 1];
         for (int i = 0; i < number; i++)
         elems[i] = temp[i];
         delete [] temp;
         elems[number] = n;
    }
    
    void usun(int n)
    {
         int usun = n;
         int * temp = new int[number];
         for (int i = 0; i < number; i++)
         temp[i] = elems[i];
         delete [] elems;
         number = number - 1;
         elems = new int[number];
         for (int i = 0; i < usun; i++)
         elems[i] = temp[i];
         for (int i = usun; i = number; i++)
         elems[i-1] = temp[i];
         delete [] temp; 
    }
	
	Set create(Set &a)
	{
		number = a.number;
		delete elems;
		elems = new int[number];
		for(int i = 0; i < number; i++) elems[i] = a.elems[i];
    }
    
    void show()
	{
		for(int i = 0; i < number; i++) cout << elems[i] << " ";
		cout << endl;
		system("PAUSE");
    }
};

int main()
{
    int wybor;
    int ktory_zbior;
    int ktory_powieksz, jaki_powieksz;
    int ktory_usun, jaki_usun;
    int ktora_roznica;
    
	cout << "Podaj licznosc pierwszego zbioru" << endl;
	int dl_a;
	cin >> dl_a;
	
	cout << "\nPodaj licznosc drugiego zbioru" << endl;
	int dl_b;
	cin >>dl_b;
	
	int * pierwszy = new int[dl_a];
	int * drugi = new int[dl_b];
	
	cin.get();
	system("cls");
	
	cout << "Tworzymy pierwszy zbior" << endl;
	for (int i = 0; i < dl_a; i++){
        cout << "\nPodaj " << i+1 << " element zbioru ";
        cin >> pierwszy[i];
        }
 
    cin.get();
    system("cls");
    
    cout << "Tworzymy drugi zbior" << endl;
    for (int j = 0; j < dl_b; j++){
        cout << "\nPodaj " << j+1 << " element zbioru ";
        cin >> drugi[j];
        }
    
    cin.get();
    system("cls");
    
    Set a(pierwszy, dl_a);
    Set b(drugi, dl_b);
    
    do {
    system("cls");
    cout << "Mamy już dane dwa zbiory, co chcesz teraz zrobic?" << endl;
	cout << "1. Wyswietlic zbior?" << endl;
	cout << "2. Wyswietlic sume zbiorow?" << endl;
	cout << "3. Wyswietlic czesc wspolna zbiorow?" << endl;
	cout << "4. Wyswietlic roznice zbiorow?" << endl;
	cout << "5. Dodac element do zbioru?" << endl;
	cout << "6. Usunac element ze zbioru?" << endl;
    cout << "7. Zakonczyc dzialanie programu?" << endl;
	cin >> wybor;
    
    switch (wybor) { 
           case 1:
                {
                     cout << endl;
                     cout << "Ktory zbior?" << endl;
                     cin >> ktory_zbior;
                     cout << endl;
                     if (ktory_zbior == 1)
                        a.show();
                        else
                        b.show();
                     break;
                }
           case 2:
                {
                        a.sum(b);
                        break;
                }     
           case 3:
                {
                      a.intersection(b);
                      break;
                }
                
           case 4:
                {
                      cout << endl;
                      cout << "1. A-B" << endl;
                      cout << "2. B-A" << endl;
                      cout << "3. Roznica Symetryczna" << endl;
                      cin >> ktora_roznica;
                      
                      switch (ktora_roznica){
                             case 1:
                                  {
                                             a.relative_complement(b);
                                             break;
                                  }
                             case 2:
                                  {
                                             b.relative_complement(a);
                                             break;
                                  }
                             case 3:         
                                  {
                                             a.symmetric_diff(b);
                                             break;           
                                  }
                      }
                      break;
                }
           case 5:
                {
                      cout << "Ktory zbior ma zostac powiekszony? ";
                      cin >> ktory_powieksz;
                      cout << "\nO jaki element? ";
                      cin >> jaki_powieksz;
                      
                      if (ktory_powieksz == 1)
                      a.dodaj(jaki_powieksz);
                      else
                      b.dodaj(jaki_powieksz);
                      break;
                }                   
            case 6:
                 {
                      cout << "Ktory zbior ma zostac zmniejszony? ";
                      cin >> ktory_usun;
                      cout << "\nO ktory element, liczac od lewej strony? ";
                      cin >> jaki_usun;
                      if (ktory_usun == 1)
                      a.usun(jaki_usun);
                      else
                      b.usun(jaki_usun);
                      break;
                 }              
           }    
    }
	while (wybor != 7);
	
    system("PAUSE");
}

Będę bardzo wdzięczny za wskazanie błędów.

Pozdrawiam,
Wojciech

0

Funkcja sortowania jest raczej źle, w sortowaniu bombelkowym jest w pętli for pętla while i inne warunki sprawdzania.
Funkcji swap nie musisz definiować, jest ona bowiem w bibliotece iostream
Stworzyłeś klasę, ale jej nie używasz zaraz na początku, tworzysz tablice intów a przecież po to definiowałeś klasę.
Radziłbym na spokojnie zaprojektować program jeszcze raz, bo tu jest mnóstwo niepotrzebnych słów. Dużo tekstu, mało robi.

0

Ogólnie to po co sortować, i po co wymyślać koło na nowo? Weź rozszerz sobie funkcjonalność std::set lub std::unordered_set o wymagane parametry i zadziała.

0

Niestety to nie przejdzie. Celem jest stworzenie władnej klasy. Inna sprawa, nie przerabialiśmy czegoś takiego jak std::set, a moje marne umiejętności programistycznie nie pozwolą na nauczenie się tego w tym czasie który mi pozostał.

Sortowanie postaram się poprawić.

Czy ktoś ma może pomysł na to czemu przy głupiej sumie wychodzą takie kosmiczne liczby?

Pozdrawiam,

0

W sum(Set&) masz takiego potworka:

 else czy = czy | false; 

Tą linijkę można spokojnie skasować, gdyż nic nie wnosi. Tylko skąd Ci się tu wzięła alternatywa bitowa?

Niepoprawne wyświetlanie jest spowodowane trywialną literówką:

for (int i = 0; i < n; i++)
        cout << tab[n] << " ";

See now? ;)

Nadmienię tylko, że samo sumowanie specjalnie wydajne nie jest, i znacznie lepiej byłoby sortować zbiory w konstruktorach.

Ponadto sama idea klasy jest zachwiana. Takie funkcje same z siebie nie powinny nic wypisywać; klasy powinny udostępniać dedykowane funkcje/operator<< do tego celu.
W tym wypadku powinieneś zwracać nowy obiekt, "łapać" go, i dopiero wyświetlać.

Sama treść zadania przynajmniej mi sugeruje, że powinieneś tutaj przeładować operatory arytmetyczne.

0

Hej,

Bardzo dziękuję za wskazanie literówki. Poprawiłem i teraz przynajmniej wiem dokładnie co nie działa. Po poprawkach:

Nie działa:

  • sortowanie
  • różnica symetryczna
  • usuwanie duplikatów - to chyba wyrzucę z programu, nie jest potrzebne

Wiem że na przeładowanych operatorach wyglądałoby to znacznie lepiej. Jednak na razie dla mnie najważniejsze jest to by działało tak jak powinno. Potem, jeśli czas pozwoli, zastanowię się nad przerobieniem tego na przeładowane operatory. Zrobiłem to na razie w ten sposób, gdyż moje umiejętności tylko na tyle pozwalają.

0

Rzuciłem okiem na sortowanie i nie widzę w nim błędów, doświadczalnie też zwraca dobre wyniki.
Wnioskuję że wołasz sortowanie ze złym argumentem długości tablicy, jak na przykład w sumie.

W tejże funkcji też sprawdzasz czy przypadkiem nie występują duplikaty elementów z pierwszej tablicy w drugiej. Jeśli robisz tak we wszystkich innych funkcjach, to rzeczywiście usuwania duplikatów możesz się pozbyć.

Zarówno sortowanie jak i usuwanie duplikatów nie mają powodu być w klasie, mogą być równie dobrze globalne.

Nie musiałeś robić własnego swap'a. Jest gotowy wewnątrz <algorithm>.

0

Dzięki za odpowiedź.
Akurat sortowanie i usuwanie duplikatów mogę usunąć z innej przyczyny. Mam działać na zbiorach, a według teorii zbiorów zbiór [1,1,6,3,4,5,9] to jest ten sam zbiór co [1,3,4,5,6,9]. Zobaczymy co mi prowadzący powie.

Na dobrą sprawę została mi tylko różnica symetryczna. Mój tok myślenia, to scalić ze sobą dwie tablice, które ten program dobrze wylicza. Tylko z tym mam problem:/

Doszedłem do czegoś takiego:
Zbiór A = [1,2,3,4,5]
Zbiór B = [4,5,6,7,8]

Różnicę symetryczną mi wyświetla: [1 2 3 1702130553 1546793837 6 7 8 5581408 1935438711].

Więc kod coś próbuje i jest na dobrej drodze. Algorytm poniżej:

[code]
void symmetric_diff(Set &a)
{
int n = 0;
int m = 0;
int * tab = new int[number];
int * tab2 = new int[a.number];
int * mer = new int[number + a.number];
bool czy;

     for (int i = 0; i < number; i++){
         czy = false;
         for (int j = 0; j < number; j++){
             if (elems[i] == a.elems[j]) czy = true;
             else czy = czy | false;}
     
     if(!czy){
             tab[n] = elems[i];
             n++;}}
             
     for (int k = 0; k < a.number; k++){
         czy = false;
         for (int l = 0; l < a.number; l++){
             if (a.elems[k] == elems[l]) czy = true;
             else czy = czy | false;}
             
     if (!czy){
               tab2[m] = a.elems[k];
               m++;}}

     int i,j;          
     
     for (i = 0; i < number; i++)
         mer[i] = tab[i];
     for (i = number, j = 0; i < number + a.number; i++, j++)
         mer[i] = tab2[j];                  

     cout << "Roznica symetryczna to: ";         
     for (int q = 0; q < number + a.number; q++)
     cout << mer[q] << " ";    
     
     system("PAUSE");
}        

[/code]

EDIT:

Dobra, dziękuję za pomoc. Udało mi się zrobić tak, żeby było dobrze. Wszystko działa jak należy. Teraz zobaczymy czy prowadzący zajęcia przyjmie mi to, czy będzie chciał żebym poprawił. Ale mam nadzieję, że na 3.0 się zgodzi:)

Pozdrawiam,

0
wrozansk napisał(a)

Inna sprawa, nie przerabialiśmy czegoś takiego jak std::set

i to jest twój problem. bo wtedy wiedziałbyś jak to porządnie napisać.

przejrzyj chociaż przykładowe kody podstawowych metod: http://www.cplusplus.com/reference/stl/set/

1 użytkowników online, w tym zalogowanych: 0, gości: 1