Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Algorytm usuwania gałęzi drzewa - Nowe podejscie, na kolejce FIFO
Black-Berry
post 8.02.2008, 21:54:25
Post #1





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


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;


Ten post edytował Black-Berry 9.02.2008, 12:07:00


--------------------
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 2)
cinekz
post 9.02.2008, 11:18:01
Post #2





Grupa: Zarejestrowani
Postów: 50
Pomógł: 6
Dołączył: 15.06.2006

Ostrzeżenie: (0%)
-----


Może byś pokazał te klasę najpierw? biggrin.gif A tak ogólnie to ekstra.
Go to the top of the page
+Quote Post
Black-Berry
post 9.02.2008, 12:00:00
Post #3





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


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.


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 31.07.2025 - 09:22