Oppure

Loading
04/02/12 11:17
flavio89
Ragazzi ho un problema.
Sto lavorando ad un progetto di un dizionario che implementi gli alberi red-black.

Alla compilazione (senza errori) mi viene mostrato il messaggio di Errore Segmentazione.
Uso Code::blocks come IDE.

Allego anche il rar del progetto, che penso sia più chiaro rispetto a quello che posto su questo thread.
Progetto.rar -> tinyurl.com/…

Header:
#include <string>
#include <list>
#include <iostream>


using namespace std;
typedef list<string> ELENCO;


// crea la lista di elementi
ELENCO crea();



Class Header:
#include "header.h"
#include <list>

class word  {
     protected:
          string parola;                                  // chiave

          word () {};                                     // costruttore
          ~word ();                                       // distruttore

    public:
        string get_parola () {return parola;};            // restituisce la chiave del nodo
};

enum color {red,black};                                   // definisco un nuovo tipo di variabile

class RedBlack : public word{
     private:
          color colore;                                   // RED = 0      BLACK = 1
          RedBlack* left, *right;                         // puntatore a nodo sx e dx
          RedBlack* parent;                               // puntatore al nodo padre

          RedBlack () {};                                 // costruttore
          ~RedBlack ();                                   // distruttore

     public:
          RedBlack* build () ;                            // inizializza un albero vuoto
          color get_col () {return colore;};              // torna il colore del nod
          void erase ();
          RedBlack* insert  (RedBlack*&, RedBlack*&, string);         // inserisce nodi all' interno dell' albero
          RedBlack* balance (RedBlack*&, RedBlack*&, string);
          RedBlack* left_rotate (RedBlack*&, RedBlack*&);
          void write (RedBlack*,int);                     // output formattatato dell' albero
};

typedef RedBlack* RB;
typedef list <RB> PILA;



Class functions
#include  "class_header.h"

PILA padre;     // stack globale per trovare nodo padre

// inizializza albero vuoto
RB RedBlack::build () {
          RB tree = new RedBlack;
          tree = NULL;
          return tree;
};

// pulisco lo stack ed inserisco una sentinella
void RedBlack::erase () {
        padre.clear();
        padre.push_back (NULL);
}


RB RedBlack::balance (RB &tree,RB &nodo,string chiave) {
    tree = insert (tree,nodo,chiave);
    RB root = tree;

    // se è radice, colore è nero.
    if (nodo == root) {
        nodo->parent = NULL;
        nodo->colore = black;
        }

    else nodo->colore = red;

    // ripristina lo stack per trovare il padre
    erase ();

    RB y;

    while ((nodo->parent->colore == red) && (nodo->parent != NULL))  {     // e se il colore del padre è ROSSO
            if (nodo->parent == nodo->parent->parent->left) {
             y = nodo->parent->parent->right;

            if (y->colore == red) {
                nodo->parent->colore = black;
                y->colore = black;
                nodo->parent->parent->colore = red;
                nodo = nodo->parent->parent;
                }   // fine IF

            else if (nodo == nodo->parent->right) {
                nodo = nodo->parent;
              left_rotate (nodo,root);    // albero nodo
                nodo->parent->colore = black;
                nodo->parent->parent->colore = red;
                //right_rotate;   // albero padre padre nodo
                } // fine ELSE IF
        } // if IF GENERALE
    // -------------------------------------------------------
            else  {
            y = nodo->parent->parent->left;

            if (nodo == nodo->parent->left) {
                nodo = nodo->parent;
                left_rotate (nodo,root);    // albero nodo
                nodo->parent->colore = black;
                nodo->parent->parent->colore = red;
               // right_rotate;   // albero padre padre nodo
                } // fine IF


            } // fine ELSE
        }   // fine WHILE

        return tree;
}

// inserisco il termine all' interno dell' albero
RB RedBlack::insert(RB &tree, RB &nodo, string chiave)  {

    // inserisci il termine
    if (tree == NULL) {
    nodo = new RedBlack;

    nodo->parola = chiave;
    nodo->left = NULL;
    nodo->right = NULL;
    nodo->parent = padre.back();                        // il padre è l' ultimo nodo esaminato
//    tree = nodo;
    return nodo;
    }

    // determina la posizione del nodo
    else if (chiave < tree->parola) {
       padre.push_back (tree);                         // salva il nodo appena esaminato per trovare il padre
        return insert (tree->left,nodo,chiave);
    }

    else if (chiave > tree->parola) {
         padre.push_back (tree);
            return insert (tree->right,nodo,chiave);
    }
}


RB RedBlack::left_rotate (RB &nodo,RB& root) {
    RB y;
    y = nodo->right;
    nodo->right = y->left;

    if (y->left != NULL) {
        y->left->parent = nodo;
        y->parent = nodo->parent;

        if (nodo->parent == NULL) root = y;
        else if (nodo == nodo->parent->left) nodo->parent->left = y;
        else nodo->parent->right = y;

    y->left = nodo;
    nodo->parent = y;
    } // fine IF

    return nodo;
}

// stampa l' albero
void RedBlack::write (RB tree,int i) {
    if (tree != NULL) {
        write (tree->right,i+1);
        for (int j = 1; j <= i; j++) cout << "   ";

        cout << tree->parola << endl;
        write (tree->left,i+1);
    }
}


Main:
#include "header.h"
#include "class_header.h"


int main () {

    // carica la lista dei termini
    ELENCO termini  = crea();

    // inizializza un albero vuoto
    RB tree = tree->build();

    // scorri la lista di termini caricata precedentemente
    ELENCO::iterator it;
    it = termini.begin();

    RB nodo;
    for (it = termini.begin(); it != termini.end(); it++) tree->balance (tree,nodo,*(it));
    //tree->insert (tree,nodo,*(it));


    cout << endl;
    // stampa l' albero formattato
    tree->write (tree,1);

    return 0;
    }


Functions:
#include "header.h"

// carica termini in memoria mediante una lista
ELENCO crea () {
    ELENCO lista;

    lista.push_back ("Casa");
    lista.push_back ("Tavolo");
    lista.push_back ("Macchina");
    lista.push_back ("Abaco");
    lista.push_back ("Abete");
    lista.push_back ("Computer");
    lista.push_back ("Armadio");
    lista.push_back ("Sedia");
    lista.push_back ("Televisore");
    lista.push_back ("Cane");
    lista.push_back ("Fotografia");
    lista.push_back ("Modem");
    lista.push_back ("Cellulare");
    lista.push_back ("Penna");
    lista.push_back ("Gomma");
    lista.push_back ("Ruota");
    lista.push_back ("Mano");
    lista.push_back ("Piede");
    lista.push_back ("Cd");
    lista.push_back ("Disco");
    lista.push_back ("Calamita");
    lista.push_back ("Pioggia");
    lista.push_back ("Sogno");
    lista.push_back ("Segreto");
    lista.push_back ("Schermo");
    lista.push_back ("Mouse");
    lista.push_back ("Chitarra");
    lista.push_back ("Batteria");
    lista.push_back ("Pinza");
    lista.push_back ("Napoli");
    lista.push_back ("Roma");
    lista.push_back ("Milano");

    return lista;
}


Aggiungo che secondo il debug, c'è un errore nel file class_function, alla riga 36 (while) nella funzione ::balance.
Ultima modifica effettuata da flavio89 04/02/12 11:59
aaa
04/02/12 12:47
nessuno
Questa

RB tree = tree->build();

non ha senso.

Come fai a chiamare un metodo di un oggetto che ancora non esiste?
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
05/02/12 10:12
flavio89
E come dovrei inizializzare l' albero?
Comunque quella parte funziona senza problemi, non voglio contraddirti ma penso l' intoppo ci sia non
appena chiamo la funzione 'balance' (come si segnala anche il debug), più precisamente la parte del bilanciamento ("tradotta" da uno pseudocodice fornito dal professore) ma sinceramente proprio non riesco a risolvere.
aaa
05/02/12 10:43
nessuno
Io non voglio neanche contraddire il Visual C++ ma ho questo (logico) errore

Run-Time Check Failure #3 - The variable 'tree' is being used without being initialized.
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
05/02/12 10:45
flavio89
quindi come dovrei inizializzare la variabile 'tree'?
aaa
05/02/12 11:07
nessuno
Attraverso il costruttore della sua classe.

Se tree deve essere un oggetto di classe RedBlack, devi usare il costruttore della classe RedBlack. E noto che il costruttore è privato ... ma perché?

P.S. Non ho ancora letto il resto del codice ... mi sono solo soffermato su questo primo problema ...
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
05/02/12 11:12
flavio89
Perdonami, quindi una cosa di questo tipo?

Nel MAIN:
RB tree; // inizializzo variabile
tree = RedBlack (tree);

Costruttore con parametri
RB::RedBlack (tree) { tree = new RedBlack; tree->left = NULL; tree->right = NULL; return tree;}

aaa
05/02/12 11:22
nessuno
Non hai molta confidenza con le basi dell'OOP ...

Il costruttore lo dichiari public e scrivi

RedBlack::RedBlack()
{
left=right=parent = NULL;
colore = red;
};

(anche il colore deve essere inizializzato)

e quando crei l'oggetto scrivi semplicemente

RB tree = new RedBlack();
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.