• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed usuwanie elementów z drzewa binarnego (więcej w treści)

Object Storage Arubacloud
0 głosów
689 wizyt
pytanie zadane 24 sierpnia 2017 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
zamknięte 24 sierpnia 2017 przez Jakub 0

witam, mam dzisiaj proste pytanie .Ostatnio jakiś czas męczę drzewo binarne .Ostateczne udało mi się napisać działającą implementacje tej struktury .Myślę że zanim powiem co dokładnie mam na myśli to podam fragment którego pytanie dotyczy oraz cały kod dla pewności :

Funkcja delete:

void deleteTree(DataTrees *&element) { //usowanie drzewa , element w nagłówku to korzen drzewa 
		if(element)deleteTree(element->leftChild); //usuwamy dla lewego poddrzewa 
		if(element)deleteTree(element->rightChild); //usuwamy dla prawego poddrzewa 
		element = nullptr; //takie proto usuwanie elemntów (kiedy dam po ludzku delete to nie działa) 
}

Cały program:

#include "stdafx.h"

using namespace std;

struct DataTrees {
	int data;
	DataTrees *leftChild;
	DataTrees *rightChild;
};

void add(DataTrees *&parent, int value) { //wstawaianie elementu 
	if (!parent) { //jezeli jest tu puste mijsce
		parent = new DataTrees;
		parent->data = value;
		parent->leftChild = nullptr;
		parent->rightChild = nullptr;
	}
	else { //pezeszukiwanie 
		if (value >= parent->data) add(parent->rightChild, value);
		else add(parent->leftChild, value);
	}
}

void inOrder(DataTrees *parent) { //sosrtowaanioe
	if (parent) {
		inOrder(parent->leftChild);
		cout << parent->data << " ";
		inOrder(parent->rightChild);
	}
}

void find(DataTrees *parent, DataTrees *&element, int value) { //poszukiwanie danej wartosci i ustawianie wskaznika na odpowiedni obiekt 
	if (!parent) { //jezeli nie znaleziono i nie ma juzz wiecej elementow 
		cout << "error" << endl;
	}
	else if (parent->data == value) { //jezeli znaleziono
		element = parent;
		cout << "is good! " << endl;
	}
	else { //poszukiwanie binarne 
		if (value < parent->data) find(parent->leftChild,element,value);
		else find(parent->rightChild, element, value);
	}
}

void deleteTree(DataTrees *&element) { //usowanie drzewa , element w nagłówku to korzen drzewa 
		if(element)deleteTree(element->leftChild); //usuwamy dla lewego poddrzewa 
		if(element)deleteTree(element->rightChild); //usuwamy dla prawego poddrzewa 
		element = nullptr; //takie proto usuwanie elemntów (kiedy dam po ludzku delete to nie działa) 
}


int main()
{
	DataTrees *root = nullptr;
	DataTrees *element = nullptr;

	while (true) {
		cout << "---MENU---" << endl;
		cout << "1. add" << endl;
		cout << "2. inOrder" << endl;
		cout << "3. find" << endl;
		cout << "4. show find element" << endl;
		cout << "5. delete tree" << endl;
		cout << "----------" << endl;

		char z = _getch();

		switch (z) {
		case '1': {
			cout << "value: ";
			int v; cin >> v;
			add(root, v);
			break;
		}
		case '2': {
			if (root) {
				cout << "sort: ";
				if(root) inOrder(root);
				else cout << 0;
			}
			else cout << 0 << endl;

			_getch();
			break;
		}
		case '3': {
			cout << "value: ";
			int v; cin >> v;
			find(root, element, v);
			_getch();
			break;
		}
		case '4': {
			if (element) {
				cout << "value: " << element->data << endl;
			}
			else cout << 0 << endl;
			_getch();
			break;
		}
		case '5': {
			deleteTree(root);
			break;
		}
		}

		system("cls");
	}

    return 0;
}

Jak wspomniałem pytanie dotyczy funkcji deleteTree ,oczywiście działa jak najbardziej ok,tyle że gdyby wniknąć głębiej w pamięć komputera to nie usuwa drzewa :/ . Dzieje się tak dlatego że ustawiamy elementy drzewa na null a tak naprawdę nie usuwamy ich z pamięci ,co prawda w programie tego nie widać ale dla większych baz danych może powodować problemy .Jeżeli jednak zrobię tak :

void deleteTree(DataTrees *&element) { 
		if(element)deleteTree(element->leftChild); 
		if(element)deleteTree(element->rightChild); 
		delete element; //no... teraz nie zadaziała
}

Chociaż wydaje mi się że delete jest bardziej poprawnym rozwiązaniem to po jego użyciu program często się wysypuje ,zwłaszcza po ponownym dodaniu elementów do drzewa . W czym może być problem? A może tak naprawdę nullptr usuwa element i nie zostawia zbędnych rzeczy w pamięci RAM? Z góry dziękuje za pomoc i pozdrawiam :D

komentarz zamknięcia: już znam odpowiedź
komentarz 24 sierpnia 2017 przez TenGumis Gaduła (3,440 p.)
Podaj jakąś prostą listę kroków kiedy delete nie działa i wysypuje program.
komentarz 24 sierpnia 2017 przez Jakub 0 Pasjonat (23,120 p.)
po zastosowaniu kodu z odpowiedzi działa ok, ale nie wiem czemu tak trzeba było napisać ...

Generalnie program nie wysypywał  się od razu tylko zawsze po próbie dodanie następnego elementu i wyświetlenia zawartości drzewa funkcją inorder

2 odpowiedzi

+2 głosów
odpowiedź 24 sierpnia 2017 przez j23 Mędrzec (194,920 p.)
wybrane 24 sierpnia 2017 przez Jakub 0
 
Najlepsza
void deleteTree(DataTrees *&element) { 
        if(element)deleteTree(element->leftChild); 
        if(element)deleteTree(element->rightChild); 
        delete element;
        element = nullptr;
}

 

komentarz 24 sierpnia 2017 przez Jakub 0 Pasjonat (23,120 p.)
dzięki wielkie ,teraz działa . Ale czemu tak trzeba było napisać a nie zadziała samo delete ? No i jak to możliwe że ustawiamy na null coś co już nie istnieje ?
komentarz 24 sierpnia 2017 przez Jakub 0 Pasjonat (23,120 p.)
*na odwrót też działa ale nie mam pojęcia jakie znaczenie ma tu ustawienie wskaźnika na nullptr skoro i tak go usuwamy
1
komentarz 24 sierpnia 2017 przez j23 Mędrzec (194,920 p.)

Ale czemu tak trzeba było napisać

Problem polegał na tym, że po usunięciu całego drzewa wskaźnik root zawierał stary adres, przez co funkcja add próbowała dobierać się do pamięci, która została już zwolniona - stąd ten błąd.

*na odwrót też działa

Działa, bo zerujesz wskaźnik root, ale masz wyciek pamięci (bo niczego nie zwalniasz).

komentarz 24 sierpnia 2017 przez Jakub 0 Pasjonat (23,120 p.)

yesjeszcze raz dzięki i pozdrawiam serdecznie 

0 głosów
odpowiedź 24 sierpnia 2017 przez TenGumis Gaduła (3,440 p.)
void deleteTree(DataTrees *&element) według mnie nie potrzebnie jest tam '&' .

Rozwiązanie które podałeś z delete jest poprawne bo to ono tak naprawdę zwalnia pamięć.
Błąd może wynikać z tego że usuwasz puste drzewo. tj. root jest nullptrem
komentarz 24 sierpnia 2017 przez Jakub 0 Pasjonat (23,120 p.)
dzięki za odpowiedź ale znak '&' jest konieczny ponieważ pracujemy bezpośrednio na wskaźniku do korzenia ,to coś w rodzaju wskaźnik na wskaźnik ,gdybym dał tylko '*' to element tylko był by kopią adresu wskaźnika root . Więc zapis *&element jest równoznaczny z **element ,(wskaźnikiem drugiego stopnia) Ale nie muszę za każdym razem używać gwiazdki .Kiedy korzeń nie istnieje to też nie powinno być problemu bo mamy takiego if-a :

if(element) -więc jeżeli root==nullptr to nic się nie wykona

Podobne pytania

0 głosów
2 odpowiedzi 1,131 wizyt
pytanie zadane 17 stycznia 2018 w C i C++ przez k222 Nałogowiec (30,150 p.)
0 głosów
1 odpowiedź 242 wizyt

92,551 zapytań

141,393 odpowiedzi

319,523 komentarzy

61,936 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...