/algorithms/avl_insert.tex
http://github.com/fmela/libdict · LaTeX · 151 lines · 122 code · 26 blank · 3 comment · 0 complexity · 68bdd282f5069847d2389611f0080404 MD5 · raw file
- % avl_insert.tex
- % 11-19-2001
- \nopagenumbers
- \parskip=2pt
- \parindent=0pt
- {\sl An Iterative Algorithm for AVL Tree Insertion
- \hfill \rm Farooq Mela $<$farooq.mela@gmail.com$>$}
- \medskip
- \noindent {\bf Algorithm A} ({\it AVL Tree Insertion}).
- Given a set of nodes which form an AVL tree {\tt T}, and a key to insert
- {\tt K}, this algorithm will insert the node into the tree while maintaining
- the tree's balance properties. Each node is assumed to contain {\tt KEY},
- {\tt BAL}, {\tt LLINK}, {\tt RLINK}, and {\tt PARENT} fields. For any given
- node {\tt N}, {\tt KEY(N)} gives the key field of {\tt N}, {\tt BAL(N)} gives
- the balance field of {\tt N}, {\tt LLINK(N)} and {\tt RLINK(N)} are pointers to
- {\tt N}'s left and right subtrees, respectively, and {\tt PARENT(N)} is a
- pointer to the node of which {\tt N} is a subtree. Any or all of these three
- link fields may be $\Lambda$, which for {\tt LLINK(N)} and {\tt RLINK(N)}
- indicates that {\tt N} has no left or right subtree, respectively, and for
- {\tt PARENT(N)} indicates that {\tt N} is the root of the tree. The {\tt BAL}
- field must be able to represent an integer on the range $[-2, +2]$. The tree
- has a field {\tt ROOT} which is a pointer to the root node of the tree.
- \medskip
- You can find an implementation of this algorithm, as well as many others, in
- {\bf libdict}, which is available on the web at
- {\tt http://github.com/fmela/libdict}.
- \medskip
- \parindent=36pt
- \item{\bf A1.} [Initialize.]
- Set ${\tt N} \gets {\tt ROOT(T)}$, ${\tt P} \gets {\tt Q}\gets \Lambda$.
- \item{\bf A2.} [Find insertion point.]
- If ${\tt N} = \Lambda$, go to step A3.
- If ${\tt K} = {\tt KEY(N)}$,
- the key is already in the tree and the algorithm terminates with an error.
- Set ${\tt P} \gets {\tt N}$;
- if ${\tt BAL(P)} \neq 0$, set ${\tt Q} \gets {\tt P}$.
- If ${\tt K} < {\tt KEY(N)}$,
- then set ${\tt N} \gets {\tt LLINK(N)}$,
- otherwise set ${\tt N} \gets {\tt RLINK(N)}$. Repeat this step.
- \item{\bf A3.} [Insert.]
- Set ${\tt N} \gets {\tt AVAIL}$.
- If ${\tt N} = \Lambda$, the algorithm terminates with an out of memory error.
- Set ${\tt KEY(N)} \gets {\tt K}$,
- ${\tt LLINK(N)} \gets {\tt RLINK(N)} \gets \Lambda$,
- ${\tt PARENT(N)} \gets {\tt P}$, and
- ${\tt BAL(N)} \gets 0$.
- If ${\tt P} = \Lambda$, set ${\tt ROOT(T)} \gets {\tt N}$, and go to step A8.
- If ${\tt K} < {\tt KEY(P)}$,
- set ${\tt LLINK(P)} \gets {\tt N}$; otherwise,
- set ${\tt RLINK(P)} \gets {\tt N}$.
- \item{\bf A4.} [Adjust balance factors.]
- If ${\tt P} = {\tt Q}$, go to step A5.
- If ${\tt LLINK(P)} = {\tt N}$,
- set ${\tt BAL(P)} \gets -1$; otherwise,
- set ${\tt BAL(P)} \gets +1$.
- Then set ${\tt N} \gets {\tt P}$, and ${\tt P} \gets {\tt PARENT(P)}$,
- and repeat this step.
- \item{\bf A5.} [Check for imbalance.] If ${\tt Q} = \Lambda$, go to step A8.
- Otherwise:
- \itemitem{i.} If ${\tt LLINK(Q)} = {\tt N}$,
- set ${\tt BAL(Q)} \gets {\tt BAL(Q)} - 1$.
- If ${\tt BAL(Q)} = -2$, go to step A6, otherwise, go to step A8.
- \itemitem{ii.} If ${\tt RLINK(Q)} = {\tt N}$,
- set ${\tt BAL(Q)} \gets {\tt BAL(Q)} + 1$.
- If ${\tt BAL(Q)} = +2$, go to step A7, otherwise, go to step A8.
- \item{\bf A6.} [Left imbalance.]
- If ${\tt BAL(LLINK(Q))} > 0$, rotate {\tt LLINK(Q)} left. Rotate {\tt Q} right.
- Go to step A8.
- \item{\bf A7.} [Right imbalance.]
- If ${\tt BAL(RLINK(Q))} < 0$, rotate {\tt RLINK(Q)} right. Rotate {\tt Q} left.
- Go to step A8.
- \item{\bf A8.} [All done.] The algorithm terminates successfully.
- \medskip
- \parindent=0pt
- {\bf Rotations in AVL Trees}
- \noindent {\bf Algorithm R} ({\it Right Rotation}).
- Given a tree {\tt T} and a node in the tree {\tt N}, this routine will rotate
- {\tt N} right.
- \parindent=36pt
- \item{\bf R1.} [Do the rotation.]
- Set
- ${\tt L} \gets {\tt LLINK(N)}$ and
- ${\tt LLINK(N)} \gets {\tt RLINK(L)}$.
- If ${\tt RLINK(L)} \neq \Lambda$,
- then set ${\tt PARENT(RLINK(L))} \gets {\tt N}$.
- Set ${\tt P} \gets {\tt PARENT(N)}$, ${\tt PARENT(L)} \gets {\tt P}$.
- If ${\tt P} = \Lambda$, then set ${\tt ROOT(T)} \gets {\tt L}$;
- if ${\tt P} \neq \Lambda$ and ${\tt LLINK(P)} = {\tt N}$,
- set ${\tt LLINK(P)} \gets {\tt L}$, otherwise
- set ${\tt RLINK(P)} \gets {\tt L}$.
- Finally, set ${\tt RLINK(L)} \gets {\tt N}$,
- and ${\tt PARENT(N)} \gets {\tt L}$.
- \item{\bf R2.} [Recompute balance factors.]
- Set
- ${\tt BAL(N)} \gets {\tt BAL(N)} + (1 - {\tt MIN(BAL(L), 0)})$,
- ${\tt BAL(L)} \gets {\tt BAL(L)} + (1 + {\tt MAX(BAL(N), 0)})$.
- \parindent=0pt
- \medskip
- The code for a left rotation is symmetric. At the risk of being repetitive, it
- appears below.
- \medskip
- \noindent {\bf Algorithm L} ({\it Left Rotation}).
- Given a tree {\tt T} and a node in the tree {\tt N}, this routine will rotate
- {\tt N} left.
- \parindent=36pt
- \item{\bf L1.} [Do the rotation.]
- Set
- ${\tt R} \gets {\tt RLINK(N)}$ and
- ${\tt RLINK(N)} \gets {\tt LLINK(R)}$.
- If ${\tt LLINK(R)} \neq \Lambda$,
- then set ${\tt PARENT(LLINK(R))} \gets {\tt N}$.
- Set ${\tt P} \gets {\tt PARENT(N)}$, ${\tt PARENT(R)} \gets {\tt P}$.
- If ${\tt P} = \Lambda$, then set ${\tt ROOT(T)} \gets {\tt R}$;
- if ${\tt P} \neq \Lambda$ and ${\tt LLINK(P)} = {\tt N}$,
- set ${\tt LLINK(P)} \gets {\tt R}$, otherwise
- set ${\tt RLINK(P)} \gets {\tt R}$.
- Finally, set ${\tt LLINK(R)} \gets {\tt N}$,
- and ${\tt PARENT(N)} \gets {\tt R}$.
- \item{\bf L2.} [Recompute balance factors.]
- Set
- ${\tt BAL(N)} \gets {\tt BAL(N)} - (1 + {\tt MAX(BAL(R), 0)})$,
- ${\tt BAL(R)} \gets {\tt BAL(R)} - (1 - {\tt MIN(BAL(N), 0)})$.
- \parindent=0pt
- \bye
- % EOF