\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{Enqueue}{$ queue, x $}
\STATE {$ queue[queue.tail] \gets x $}
\IF {$ queue.tail = queue.length - 1 $}
\STATE {$ queue.tail \gets 0 $}
\ELSE
\STATE {$ queue.tail \gets queue.tail + 1 $}
\ENDIF
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\FUNCTION{Dequeue}{$ queue $}
\STATE {$ x \gets queue[queue.head] $}
\IF {$ queue.head = queue.length - 1 $}
\STATE {$ queue.head \gets 0 $}
\ELSE
\STATE {$ queue.head \gets queue.head + 1 $}
\ENDIF
\RETURN {$ x $}
\ENDFUNCTION
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\FUNCTION{IsEmpty}{$ queue $}
\IF {$ queue.head = queue.tail $}
\RETURN \TRUE
\ENDIF
\RETURN \FALSE
\ENDFUNCTION
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{Push}{$ stack, x $}
\STATE {$ stack[stack.top] \gets x $}
\STATE {$ stack.top \gets stack.top + 1 $}
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\FUNCTION{Pop}{$ stack $}
\STATE {$ stack.top \gets stack.top - 1 $}
\RETURN {$ stack[stack.top] $}
\ENDFUNCTION
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\FUNCTION{IsEmpty}{$ stack $}
\IF {$ stack.top = 0 $}
\RETURN \TRUE
\ENDIF
\RETURN \FALSE
\ENDFUNCTION
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\FUNCTION{ListSearch}{$ list, key $}
\STATE {$ x \gets list.head $}
\WHILE {$ x \neq $ \textsc{null} \AND $ x.key \neq key $}
\STATE {$ x \gets x.next $}
\ENDWHILE
\RETURN {$ x $}
\ENDFUNCTION
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{ListInsert}{$ list, key $}
\STATE {$ node \gets $ new \CALL{ListNode}{$ prev=$ \textsc{null} $, next=list.head, key=key $}}
\IF {$ list.head \neq $ \textsc{null}}
\STATE {$ list.head.prev \gets node $}
\ENDIF
\STATE {$ list.head \gets node $}
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{ListDelete}{$ list, node $}
\IF {$ node.prev \neq $ \textsc{null}}
\STATE {$ node.prev.next \gets node.next $}
\ELSE
\STATE {$ list.head \gets node.next $}
\ENDIF
\IF {$ node.next \neq $ \textsc{null}}
\STATE {$ node.next.prev \gets node.prev $}
\ENDIF
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\FUNCTION{TreeSearch}{$ tree, key $}
\STATE {$ node \gets tree.root $}
\WHILE {$ node \neq $ \textsc{null} \AND $ node.key \neq key $}
\IF {$ key < node.key $}
\STATE {$ node \gets node.left $}
\ELSE
\STATE {$ node \gets node.right $}
\ENDIF
\ENDWHILE
\RETURN {$ node $}
\ENDFUNCTION
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{TreeInsert}{$ tree, key $}
\STATE {$ node \gets $ new \CALL{TreeNode}{$ parent = $ \textsc{null} $, left = $ \textsc{null} $, right = $ \textsc{null} $, key= key $}}
\STATE {}
\STATE {$ parent \gets $ \textsc{null}}
\STATE {$ current \gets tree.root $}
\WHILE {$ current \neq $ \textsc{null} \AND $ current.key \neq key $}
\STATE {$ parent \gets current $}
\IF {$ key < current.key $}
\STATE {$ current \gets current.left $}
\ELSE
\STATE {$ current \gets current.right $}
\ENDIF
\ENDWHILE
\STATE {}
\STATE {$ node.parent \gets parent $}
\IF {$ parent = $ \textsc{null}}
\STATE {$ tree.root \gets node $}
\ELSIF {$ key < parent.key $}
\STATE {$ parent.left \gets node $}
\ELSE
\STATE {$ parent.right \gets node $}
\ENDIF
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\FUNCTION{TreeMinimum}{$ node $}
\WHILE {$ node.left \neq $ \textsc{null}}
\STATE {$ node \gets node.left $}
\ENDWHILE
\RETURN {$ node $}
\ENDFUNCTION
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{TreeDelete}{$ tree, node $}
\IF {$ tree.root = $ \textsc{null} \OR $ node = $ \textsc{null}}
\RETURN
\ENDIF
\STATE {}
\IF {$ node.left = $ \textsc{null} \AND $ node.right = $ \textsc{null}}
\IF {$ node.parent = $ \textsc{null}}
\STATE {$ tree.root \gets $ \textsc{null}}
\ELSIF {$ node.parent.left = node $}
\STATE {$ node.parent.left \gets $ \textsc{null}}
\ELSE
\STATE {$ node.parent.right \gets $ \textsc{null}}
\ENDIF
\RETURN
\ENDIF
\STATE {}
\IF {$ node.left = $ \textsc{null}}
\IF {$ node.parent = $ \textsc{null}}
\STATE {$ tree.root \gets node.right $}
\ELSIF {$ node.parent.left = node $}
\STATE {$ node.parent.left \gets node.right $}
\ELSE
\STATE {$ node.parent.right \gets node.right $}
\ENDIF
\STATE {$ node.right.parent \gets node.parent $}
\RETURN
\ENDIF
\STATE {}
\IF {$ node.right = $ \textsc{null}}
\IF {$ node.parent = $ \textsc{null}}
\STATE {$ tree.root \gets node.left $}
\ELSIF {$ node.parent.left = node $}
\STATE {$ node.parent.left \gets node.left $}
\ELSE
\STATE {$ node.parent.right \gets node.left $}
\ENDIF
\STATE {$ node.left.parent \gets node.parent $}
\RETURN
\ENDIF
\STATE {}
\STATE {$ succesor \gets $ \CALL{TreeMinimum}{$ node.right $}}
\STATE {$ node.key \gets successor.key $}
\STATE \CALL{TreeDelete}{$ tree, successor $}
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{TreeInsertBiject}{$ tree, array, p, r $}
\IF {$ p = r $}
\STATE \CALL{TreeInsert}{$ tree, array[p] $}
\ELSIF {$ r - p = 1 $}
\STATE \CALL{TreeInsert}{$ tree, array[p] $}
\STATE \CALL{TreeInsert}{$ tree, array[r] $}
\ELSE
\STATE {$ q \gets p + \frac{r - p}{2} $}
\STATE \CALL{TreeInsert}{$ tree, array[q] $}
\STATE \CALL{TreeInsertBiject}{$ tree, array, p, q - 1 $}
\STATE \CALL{TreeInsertBiject}{$ tree, array, q + 1, r $}
\ENDIF
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{BalancedTreeCreate}{$ tree, array, n $}
\STATE \CALL{Sort}{$ array, n $}
\STATE \CALL{TreeInsertBiject}{$ tree, array, 0, n-1 $}
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}
Istnieją trzy sposoby przechodzenia drzewa binarnego:
Podane trzy akcje oznaczają:
Zmierz czas działania operacji ListSearch dla różnych wartości n i przedstaw wyniki na wykresie (na ocenę 3.5):
Ważne! W powyższym chodzi o to, żeby zmierzyć łączny czas wyszukiwania wszystkich elementów i następnie go podzielić przez liczbę elementów. Mierzenie czasu działania dla jednego elementu jest nieprawidłowe!
Wykonaj eksperyment w dwóch wariantach dla zmieniającego się n:
Wartość m określa ile będzie powtórzeń “szukania każdej wartości” i służy temu by zmierzyć czas, który potencjalnie jest bardzo niski (bliski zera)
Wartość m należy dobrać eksperymentalnie, żeby żadne pomiary czasowe nie wynosiły zero (np. można zacząć od m=1 i podwajać dopóki którykolwiek z pomiarów czasowych wynosi zero)
Uwaga! Odpowiednia wartość m może być różna w zależności od typu danych (rosnące / losowe) oraz typu struktury danych (listy / drzewa), więc dobór odpowiedniej wartości należy powtórzyć przy każdym eksperymencie
Zmierz czas działania operacji TreeSearch analogicznie jak poprzednio (na ocenę 4.0)
Zmierz czas działania operacji TreeSearch dla drzew zrównoważonych analogicznie jak poprzednio (na ocenę 4.5)
\begin{algorithm}
\begin{algorithmic}
\PROCEDURE{Shuffle}{$ array, n $}
\FOR {$ i \gets n-1 $ \DOWNTO $ 2 $}
\STATE {$ j \gets $} \CALL{Random}{$ 0, i-1 $}
\STATE \CALL{Swap}{$ array, i, j$}
\ENDFOR
\ENDPROCEDURE
\end{algorithmic}
\end{algorithm}