Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Przejście ze zwykłych wskaźników na wskaźniki inteligentne.

Ostatnio zmodyfikowano 2016-12-17 21:45
Autor Wiadomość
pepe450
Temat założony przez niniejszego użytkownika
Przejście ze zwykłych wskaźników na wskaźniki inteligentne.
» 2016-12-17 20:21:57
Witam mam za zadanie przerobić program drzewa binarnego tak aby zamiast działań na zwykłych wskaźnikach korzystał z wskaźników inteligentnych.
Proszę o pomoc w zrozumieniu wskaźników inteligentnych jak ich użyć abym korzystał z nich prawidłowo.
Ponieważ nie wydaję mi się aby jedyna różnica polegała na tym żebym zamiast
        ElementDrzewa* lewy;
ElementDrzewa* prawy;
ElementDrzewa* rodzic;
użyję:
        std::unique_ptr<ElementDrzewa> lewy;
std::unique_ptr<ElementDrzewa> prawy;
std::unique_ptr<ElementDrzewa> rodzic;

Do czego służą funkcje takie jak:
std::make_unique<ElementDrzewa>(nullptr)
std::move(korzen)

Oto mój kod na zwykłych wskaźnikach:
main.cpp
C/C++
#include<iostream>
#include"BSTree.h"
using namespace std;
int main()
{
    BSTree bst;
    cout <<( bst.isEmpty() ? "Drzewo jest puste"
        : "Drzewo nie jest puste" ) << endl;
    bst.insert( 5 );
    bst.insert( 3 );
    bst.insert( 7 );
    bst.insert( 4 );
    bst.insert( 2 );
    cout <<( bst.isEmpty() ? "Drzewo jest puste"
        : "Drzewo nie jest puste" ) << endl;
    cout << "Drzewo zawiera element o wartosc 3: " << bst.contains( 3 ) << endl;
    cout << "Drzewo zawiera element o wartosc 9: " << bst.contains( 9 ) << endl;
    bst.printInOrder();
    cout << endl;
    bst.clear();
    cout <<( bst.isEmpty() ? "Drzewo jest puste"
        : "Drzewo nie jest puste" ) << endl;
    system( "pause" );
    return 0;
}
ElementDrzewa.h
C/C++
#pragma once
#include<iostream>
using namespace std;
class ElementDrzewa
{
    ElementDrzewa * lewy;
    ElementDrzewa * prawy;
    ElementDrzewa * rodzic;
    int wartosc;
public:
    friend class BSTree;
    ElementDrzewa();
    ElementDrzewa( ElementDrzewa * r = NULL, ElementDrzewa * l = NULL, ElementDrzewa * p = NULL, int w = 0 );
    ~ElementDrzewa();
};
ElementDrzewa.cpp
C/C++
#include "ElementDrzewa.h"
#include<iostream>
using namespace std;
ElementDrzewa::ElementDrzewa()
{
    rodzic = lewy = prawy = NULL;
    wartosc = 0;
}
ElementDrzewa::ElementDrzewa( ElementDrzewa * r, ElementDrzewa * l, ElementDrzewa * p, int w )
    : rodzic( r )
     , lewy( l )
     , prawy( p )
     , wartosc( w )
{
   
}
ElementDrzewa::~ElementDrzewa()
{
   
}
BSTree.h
C/C++
#pragma once
#include"ElementDrzewa.h"
#include<iostream>
using namespace std;
class BSTree
{
    ElementDrzewa * korzen;
    void inorder( ElementDrzewa * pom ) const;
    void deleteAll( ElementDrzewa * pom );
public:
    BSTree();
    ~BSTree();
    bool isEmpty();
    void insert( int liczba );
    void printInOrder();
    bool contains( int szukana ) const;
    void clear();
};
BSTree.cpp
C/C++
#include "BSTree.h"
#include<iostream>
using namespace std;
void BSTree::inorder( ElementDrzewa * pom ) const
{
    if( pom->lewy != NULL )
         inorder( pom->lewy );
   
    cout << pom->wartosc << endl;
    if( pom->prawy != NULL )
         inorder( pom->prawy );
   
}
void BSTree::deleteAll( ElementDrzewa * pom )
{
    if( pom->lewy ) deleteAll( pom->lewy );
   
    if( pom->prawy ) deleteAll( pom->prawy );
   
    delete pom;
    pom = NULL;
}

void BSTree::clear()
{
    if( korzen ) deleteAll( korzen );
   
    korzen = NULL;
}
BSTree::BSTree()
{
    korzen = NULL;
}
BSTree::~BSTree()
{
    if( korzen ) deleteAll( korzen );
   
    korzen = NULL;
}
bool BSTree::isEmpty()
{
    if( korzen == NULL )
         return true;
    else
         return false;
   
}
void BSTree::insert( int liczba )
{
    if( korzen == NULL )
    {
        korzen = new ElementDrzewa( korzen, NULL, NULL, liczba );
        return;
    }
    ElementDrzewa * p = korzen;
    while( p )
    {
        if( p->wartosc >= liczba )
        {
            if( p->lewy == NULL )
            {
                p->lewy = new ElementDrzewa( p, NULL, NULL, liczba );
                return;
            }
            if( p->lewy )
                 p = p->lewy;
           
        }
        else
        {
            if( p->prawy == NULL )
            {
                p->prawy = new ElementDrzewa( p, NULL, NULL, liczba );
                return;
            }
            if( p->prawy )
                 p = p->prawy;
           
        }
    }
}
void BSTree::printInOrder()
{
    if( korzen == NULL )
    {
        cout << "Drzewo jest puste" << endl;
    }
    else
    {
        ElementDrzewa * p = korzen;
        inorder( p );
    }
   
}
bool BSTree::contains( int szukana ) const
{
    ElementDrzewa * pom = korzen;
    while( pom )
    {
        if( pom->wartosc == szukana )
        {
            return true;
        }
        if( pom->wartosc <= szukana )
             pom = pom->prawy;
        else pom = pom->lewy;
       
    }
    return false;
}
P-155098
carlosmay
» 2016-12-17 21:00:48
Na początek spróbuj z trochę wolniejszym ale łatwiejszym w ogarnięciu std::shared_ptr<>.
Nie będziesz musiał martwić się o przesuwaniu prawa wyłączności.
P-155103
michal11
» 2016-12-17 21:45:40
Ja bym zrobił tak
C/C++
class ElementDrzewa
{
    std::unique_ptr < ElementDrzewa > lewy;
    std::unique_ptr < ElementDrzewa > prawy;
    ElementDrzewa * rodzic; // defacto weak ptr, skoro istnieje to musze miec rodzica
    int wartosc; //template
   
public:
   
    ElementDrzewa() = delete;
    ElementDrzewa( const ElementDrzewa & parent, int wart )
    {
        rodzic = & parent;
        wartosc = wart;
    }
    ElementDrzewa( const ElementDrzewa & copy ) = delete;
    ElementDrzewa & operator =( const ElementDrzewa & assign ) = delete;
    ElementDrzewa( const ElementDrzewa && move ) = default;
    ElementDrzewa & operator =( const ElementDrzewa & assign ) = default;
    ~ElementDrzewa() = default;

trzeba jeszcze oczywiście dodać jakies funkcje na odpowiednie tworzenie i przenoszenie nodów na lewo i prawy ale to już dość prosta sprawa.

Po co ci było zafriendowane BTTree w ElementDrzewa?

BTTTree też powinno miec unique_ptr jako root.

jeszcze jedna mała rzecz
C/C++
bool BSTree::isEmpty()
{
    if( korzen == NULL )
         return true;
    else
         return false;
   
}

można zapisać jako
C/C++
bool BSTree::isEmpty()
{
    return korzen == NULL;
}

generalnie polecam talk Herba Suttera o smart pointerach z ostatniego cppconu, powinno ci pomóc
https://www.youtube.com/watch​?v=JfmTagWcqoE
P-155105
« 1 »
  Strona 1 z 1