Przejście ze zwykłych wskaźników na wskaźniki inteligentne.
Ostatnio zmodyfikowano 2016-12-17 21:45
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 #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 #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 #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 #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 #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; } |
|
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. |
|
michal11 |
» 2016-12-17 21:45:40 Ja bym zrobił tak class ElementDrzewa { std::unique_ptr < ElementDrzewa > lewy; std::unique_ptr < ElementDrzewa > prawy; ElementDrzewa * rodzic; int wartosc; 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 bool BSTree::isEmpty() { if( korzen == NULL ) return true; else return false; }
można zapisać jako 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 |
|
« 1 » |