Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Algorytm usuwania gałęzi drzewa - Nowe podejscie
Forum PHP.pl > Forum > PHP
Black-Berry
Ostatnio siedziałem sporo nad utworzeniem struktury kategorii na stronie. Istnieje fajna metoda opisana tutaj - klik. Osobiście ma dla mnie to taką wadę, że nie mamy swobody przy przenoszeniu lub zamienianiu dowolnych gałęzi w drzewie. W mojej metodzie wykorzystuję uproszczoną strukturę bazy.

  1. +--------+--------+
  2. | id | parent |
  3. +--------+--------+

Ma to spore zalety. Najtrudniejsze jest jednak np. Usuwanie całej gałęzi. Moze się komuś przyda. Proszę też o jakieś komentarze. Dzięki kolejce FIFO pozbyłem się rekurencji. Ograniczyłem też ilość zapytań do bazy do liczby węzłów zawierających dzieci. Tak więc jeśli mamy np kategorie które zawierają dużą ilość artykułów ( Zazwyczaj tak jest, że mamy o wiele mniej kategorii niż artykułów ) to jest to całkiem wydajna metoda. Udało mi się zaimplementować taki algorytm: (Testowałem i działa) smile.gif

  1. <?php
  2. $node_id = 5; //wybieramy jakiś węzeł
  3. $parents= new numeric_fifo_queue; //nowa kolejka FIFO
  4. $parents->push( $node_id ); //wpisujemy id wezla który chcemy usunąć
  5. while( !$parents->is_empty() )
  6. {
  7. while ($row = mysql_fetch_array("SELECT * FROM tree WHERE parent=".$parents->pop(), MYSQL_ASSOC))
  8. {
  9. $parents->push( $row["id"] );
  10. mysql_query ( "DELETE FROM tree WHERE id = ".$row["id"] );
  11. }
  12. }
  13. //na koniec usuwamy węzeł o id = $node_id;
  14. mysql_query ( "DELETE FROM tree WHERE id = ".$node_id );
  15. ?>

Można to jeszcze udoskonalić tak aby pozbyć się końcówki. Wystarczy w zapytaniu do bazy wstawić jedno 'or'. Nie będzie wtedy trzeba pamiętać o 2 różnych miejscach usuwania wpisu:

  1. zapytanie:
  2. "SELECT * FROM tree WHERE parent=".$parents->pop()
  3. zamieniamy na:
  4. "SELECT * FROM tree WHERE parent=".$parents->pop()." OR id=".$node_id
  5. i już możemy usunąć ostatnie 'DELETE' query;
cinekz
Może byś pokazał te klasę najpierw? biggrin.gif A tak ogólnie to ekstra.
Black-Berry
Nie mam klasy do drzewa. To tylko kod który można sobie dostosować. Jeśli jednak chodzi o klasę kolejki FIFO to standard dlatego nie zamieszczałem jej tutaj. Ale skoro prosisz to proszę:
  1. <?php
  2. class numeric_fifo_queue
  3. {
  4. var
  5. $arrQueue,  // Array of queue items
  6. $intBegin,  // Begin of queue - head
  7. $intEnd,  // End of queue - tail
  8. $intArraySize,  // Size of array
  9. $intCurrentSize; // Current size of array
  10.  
  11. function numeric_fifo_queue( $intSize = 99999 )
  12. {
  13. $this->arrQueue  = Array();
  14. $this->intArraySize = $intSize;
  15. $this->arrCurrentSize = 0;
  16. $this->intBegin = 0;
  17. $this->intEnd = $this->intArraySize - 1;
  18. }
  19.  
  20. function push( $objQueueItem )
  21. {
  22. if ( $this->intCurrentSize >= $this->intArraySize ) return false;
  23. if ( $this->intEnd == $this->intArraySize - 1 ){
  24. $this->intEnd = 0;
  25. }else{
  26. $this->intEnd++;
  27. }
  28. $this->arrQueue[ $this->intEnd ] = $objQueueItem;
  29. $this->intCurrentSize++;
  30. return true;
  31. }
  32.  
  33. function pop()
  34. {
  35. if ( $this->is_empty() ) return false;
  36. $objItem = $this->arrQueue[$this->intBegin];
  37. if ( $this->intBegin == $this->intArraySize - 1 ){
  38. $this->intBegin = 0;
  39. }else{
  40. $this->intBegin++;
  41. }
  42. $this->intCurrentSize--;
  43. return $objItem;
  44. }
  45.  
  46. function is_empty()
  47. {
  48. return ( $this->intCurrentSize == 0 ? true : false );
  49. }
  50. }
  51. ?>
Nie ukrywam, że klasy tej nie pisałem sam ale ściągnąłem z neta. W przyszłości postaram się jeszcze zamieścić moje metody do tworzenia rozwijanego menu z tego drzewa ale to już bajka bo usuwanie gałęzi jest najtrudniejsze jeśli nie stosujemy w bazie pól lft, right (patrz artykuł z 1 postu). Usuwanie węzła przy takiej strukturze bazy to kwestia usunięcia rekordu, a dodawanie polega na podaniu 'parenta' więc nie ma sensu o tym pisać. Pozdrawiam i czekam na dalsze opinie.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.