dimanche 2 février 2020

Unhandled exception thrown: read access violation, this->spazio was 0xE0150076

So i'm trying to run a class with static functions that can find if a binary tree has only 0 and 1 values. in particular, root must be equal to 0, every node equal to 0 must have 1 as left and right children, and every node equal to 1 must have 0 as left and right children.

I tried to create a new class, and compiler doesn't give me any error. This is Binary Tree class code:

#ifndef _Bin_treecC_H_
#define _Bin_treecC_H_

#include "Bin_tree.h"
#include "exceptions.h"


template <class T>
class Bin_treec : public Bin_tree<T, int> {
    static const int NIL = -1;

public:

    typedef typename Bin_tree<T, int>::value_type value_type;
    typedef typename Bin_tree<T, int>::Nodo Nodo;

    struct _cella {
        Nodo genitore;
        Nodo sinistro;
        Nodo destro;
        value_type valore;
    };

    typedef struct _cella Cella;

    // costruttori e distruttori
    Bin_treec();
    Bin_treec(int);
    ~Bin_treec();

    // operatori
    void create();
    bool empty() const;

    Nodo root() const;
    Nodo parent(Nodo) const;
    Nodo sx(Nodo) const;
    Nodo dx(Nodo) const;
    bool sx_empty(Nodo) const;
    bool dx_empty(Nodo) const;

    //void costr(Bin_treec<T>);
    void erase(Nodo);

    T read(Nodo) const;
    void write(Nodo, value_type);

    void ins_root();
    void ins_sx(Nodo);
    void ins_dx(Nodo);

private:
    int MAXLUNG;
    Cella* spazio;
    int nNodi;
    Nodo inizio;
    Nodo libera;
};

template <class T>
Bin_treec<T>::Bin_treec()
{
    MAXLUNG = 100;
    spazio = new Cella[MAXLUNG];
    create();
}

template <class T>
Bin_treec<T>::Bin_treec(int nNodi) : MAXLUNG(nNodi)
{
    spazio = new Cella[nNodi];
    create();
}


template <class T>
Bin_treec<T>::~Bin_treec()
{
    erase(inizio);
    delete[] spazio;
}

template <class T>
void Bin_treec<T>::create()
{
    inizio = NIL;
    for (int i = 0; i < MAXLUNG; i++)
    {
        spazio[i].sinistro = (i + 1) % MAXLUNG;
    }

    libera = 0;
    nNodi = 0;
}

template <class T>
bool Bin_treec<T>::empty() const
{
    return(nNodi == 0);
}

template <class T>
typename Bin_treec<T>::Nodo Bin_treec<T>::root() const
{
    return(inizio);
}

template <class T>
typename Bin_treec<T>::Nodo Bin_treec<T>::parent(Nodo n) const
{
    if (n != inizio)
        return (spazio[n].genitore);
    else
        return(n);
}

template <class T>
typename     Bin_treec<T>::Nodo Bin_treec<T>::sx(Nodo n) const
{
    if (!sx_empty(n))
        return (spazio[n].sinistro);
    else
        return(n);
};

template <class T>
typename     Bin_treec<T>::Nodo Bin_treec<T>::dx(Nodo n) const
{
    if (!dx_empty(n))
        return (spazio[n].destro);
    else
        return(n);
}

template <class T>
bool Bin_treec<T>::sx_empty(Bin_treec<T>::Nodo n) const
{
    return (spazio[n].sinistro == NIL); \\HERE VISUAL SAYS THERE IS AN ERROR.
}

template <class T>
bool Bin_treec<T>::dx_empty(Bin_treec<T>::Nodo n) const
{
    return (spazio[n].destro == NIL);
}

template <class T>
void Bin_treec<T>::ins_root()
{
    if (inizio == NIL)
    {   

        inizio = libera;
        libera = spazio[libera].sinistro;
        spazio[inizio].sinistro = NIL;
        spazio[inizio].destro = NIL;
        nNodi++;
    }
    else
        throw RootExists();
}


template <class T>
void Bin_treec<T>::ins_sx(Nodo n)
{
    if (inizio == NIL)
        throw EmptyTree();
    if (n == NIL)
        throw NullNode();
    if (spazio[n].sinistro != NIL)
        throw NodeExists();
    if (nNodi >= MAXLUNG)
        throw FullSize();
    else
    {
        Nodo q = libera;
        libera = spazio[libera].sinistro;
        spazio[n].sinistro = q;
        spazio[q].sinistro = NIL;
        spazio[q].genitore = n;
        spazio[q].destro = NIL;
        nNodi++;
    }
}

template <class T>
void Bin_treec<T>::ins_dx(Nodo n)
{
    if (inizio == NIL)
        throw EmptyTree();
    if (n == NIL)
        throw NullNode();
    if (spazio[n].destro != NIL)
        throw NodeExists();
    if (nNodi >= MAXLUNG)
        throw FullSize();
    else
    {
        Nodo q = libera;
        libera = spazio[libera].sinistro;
        spazio[n].destro = q;
        spazio[q].genitore = n;
        spazio[q].sinistro = NIL;
        spazio[q].destro = NIL;
        nNodi++;
    }
}

template <class T>
void Bin_treec<T>::erase(Nodo n)
{
    if (n != NIL) {
        if (!sx_empty(n))
            erase(spazio[n].sinistro);
        if (!dx_empty(n))
            erase(spazio[n].destro);
        if (n != inizio) {
            Nodo p = parent(n);
            if (spazio[p].sinistro == n)
                spazio[p].sinistro = NIL;
            else
                spazio[p].destro = NIL;
        }
        else
            inizio = NIL;
        nNodi--;
        spazio[n].sinistro = libera;
        libera = n;
    }
    else
        throw NullNode();
}

template <class T>
T Bin_treec<T>::read(Nodo n) const
{
    if (n != NIL)
        return (spazio[n].valore);
    else
        throw NullNode();
}

template <class T>
void Bin_treec<T>::write(Nodo n, value_type a)
{
    if (n != NIL)
        spazio[n].valore = a;
    else
        throw NullNode();
}
#endif /* _Bin_treecC_H_ */

this is the class which controls if rules are respected:

#ifndef _ZERO_ONE_BINARY_TREE_H_
#define _ZERO_ONE_BINARY_TREE_H_

#include "bin_treec.h"
using namespace std;

template <class T>
class zero_one_binary_tree 
{

public:
    static bool is_zero_one(const Bin_treec <T>& B)
    {

        Bin_treec<T> S = B;

        if (!S.empty() && S.root() == 0)
            checkzeroone(S.root(),S);

        if (checkzeroone(S.root(),S) == false)
            return false;
        else
            return true;
    }

    static bool checkzeroone(int n, const Bin_treec <T>& H)
    {
        Bin_treec<T> J = H;

        if (n == 0)
        {
            if (!J.sx_empty(n) && !J.dx_empty(n)) {
                if (J.sx(n) == 1 && J.dx(n) == 1)
                {
                    checkzeroone(J.sx(n), J);
                    checkzeroone(J.dx(n), J);
                }
                else if (J.sx(n) != 1 || J.dx(n) != 1) {
                    if ((J.sx_empty(n) && J.dx_empty(n))) {
                        cout << "nodo foglia, tutto corretto!" << endl;
                        return true;
                    }
                    else{
                        return false;
                    }
                }
            }
        }
        if (n == 1)
        {
            if (!J.sx_empty(n) && !J.dx_empty(n)) {
                if (J.sx(n) == 0 && J.dx(n) == 0)
                {
                    checkzeroone(J.sx(n), J);
                    checkzeroone(J.dx(n), J);
                }
                else if (J.sx(n) != 0 || J.dx(n) != 0) {
                    if ((J.sx_empty(n) && J.dx_empty(n))) {
                        cout << "nodo foglia, tutto corretto!" << endl;
                        return true;
                    }
                    else {
                        return false;
                    }
                }


            }
        }


    }
};

#endif

This is the main:

#include "zero_one_binary_tree.h"
#include <iostream>

using namespace std;


int main() {
    Bin_treec<int> T;
    typename Bin_treec<int>::Nodo n1 = 0, n2 = 0;

    T.ins_root();
    T.write(T.root(), 0);
    n1 = T.root();
    T.ins_sx(n1);
    T.ins_dx(n1);
    T.write(T.sx(n1), 2);
    n1 = T.dx(n1);
    T.write(n1, 3);
    T.ins_dx(n1);
    T.write(T.dx(n1), 4);
    T.print();
    cout << T;
    zero_one_binary_tree<int>::is_zero_one(T);

}

When i try to run the exe, it suddently stops and says that:

Unhandled exception thrown: read access violation.
this->**spazio** was 0xE019E256. occurred

The error reports me to the row i reported inside the code (line 139) and I don't know how to solve it. In my opinion there is a problem with how i'm passing node children but actually I can't solve this. It's not the first time it happens with my code so any help would be appreciated!

Aucun commentaire:

Enregistrer un commentaire