<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>avl-tree &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/avl-tree/</link>
	<description>Feed of posts on WordPress.com tagged "avl-tree"</description>
	<pubDate>Wed, 23 Dec 2009 13:00:32 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Data Structure: Balanced Search Trees]]></title>
<link>http://abhitak.wordpress.com/2009/11/23/data-structure-balanced-search-trees/</link>
<pubDate>Sun, 22 Nov 2009 19:47:07 +0000</pubDate>
<dc:creator>Abhishek</dc:creator>
<guid>http://abhitak.wordpress.com/2009/11/23/data-structure-balanced-search-trees/</guid>
<description><![CDATA[Tomorrow i have Exam on Data Structures. For preparing for that i found the following study material]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Tomorrow i have Exam on Data Structures. For preparing for that i found the following study materials to be very useful:<br />
1. <a href="http://en.wikipedia.org/wiki/AVL_tree">AVL Trees &#8211; Wikipedia</a><br />
2. <a href="http://en.wikipedia.org/wiki/Red-black_tree">Red-Black Trees &#8211; Wikipedia</a><br />
3. (i)<a href="http://lcm.csa.iisc.ernet.in/dsa/node118.html"> 2-3 Trees</a>. Insertion &#38; deletion links are given in this page.<br />
   (ii) There is one more paper whose ideology of 2-3 tree is little different from the one mentioned above. <a href="https://abhitak.wordpress.com/wp-admin/media.php?action=edit&#38;attachment_id=285">Here</a> it is. I would like to mention that the 3.(ii) ideology is taught generally. But we(IIT Kharagpur &#38; IISc Bangalore) were taught the 3.(i) one.</p>
<p>There is one very good Java Applet where you can insert, delete, search etc. an element in different kinds of trees STEP-BY-STEP. Here&#8217;s the link:<br />
<a href="http://people.ksp.sk/~kuko/bak/index.html">Search Tree Java Applet</a><br />
Enable Java in your browser to view it.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Cargo Cult Programming (part 1)]]></title>
<link>http://hbfs.wordpress.com/2009/10/13/cargo-cult-programming-part-1/</link>
<pubDate>Tue, 13 Oct 2009 10:47:54 +0000</pubDate>
<dc:creator>Steven Pigeon</dc:creator>
<guid>http://hbfs.wordpress.com/2009/10/13/cargo-cult-programming-part-1/</guid>
<description><![CDATA[Programmers aren&#8217;t always the very rational beings they please themselves to believe. Very oft]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Programmers aren&#8217;t always the very rational beings they please themselves to believe. Very often, we close our eyes and take decisions based on what we <em>think</em> we know, and based on what have been told by more or less reliable sources. Such as, for example, taking <a href="http://en.wikipedia.org/wiki/Red-black_tree" target="_blank">red-black</a> trees rather than <a href="http://en.wikipedia.org/wiki/AVL_tree" target="_blank">AVL</a> trees because they are faster, while not being able to quite justify in the details why it must be so. Programming using this kind of decision I call <em>cargo cult programming</em>.</p>
<p><a href="http://en.wikipedia.org/wiki/File:CMA_CGM_Balzac.jpg"><img src="http://hbfs.wordpress.com/files/2009/08/cargo.jpg?w=300" alt="cargo" title="cargo" width="400" height="179" class="aligncenter size-medium wp-image-1539" /></a></p>
<p>Originally, I wanted to talk about red-black <em>vs.</em> AVL trees and how they compare, but I&#8217;ll rather talk about the STL <tt>std::map</tt> that is implemented using red-black trees with G++ 4.2, and <tt>std::unordered_map</tt>, a <a href="http://en.wikipedia.org/wiki/Hash_table" target="_blank">hash-table</a> based container introduced in <a href="http://en.wikipedia.org/wiki/C%2B%2B_Technical_Report_1" target="_blank">TR1</a>.</p>
<p><!--more--></p>
<p>TR1 <tt>std::unordered_map</tt> is a map that does not maintain any particular order between the keys of the data it contains. It is therefore implemented as a <a href="http://en.wikipedia.org/wiki/Hash_table" target="_blank">hash table</a>. The <tt>std::map</tt> is implemented, at least in G++ 4.2, as a <a href="http://en.wikipedia.org/wiki/Red-black_tree" target="_blank">red-black tree</a>. Self-balancing trees change their shape with each insertion in order to maintain most leaves at an equal depth, ensuring an <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access time. The difference between an AVL tree and a red-black tree is the way the tree is rebalanced, and the red-black tree does about half as much operations as an AVL tree on insertion, making somewhat faster&#8212;how much faster remains to be quantified.</p>
<p>So I ran a few simple experiments to compare <tt>std::unordered_map</tt> and <tt>std::map</tt>. First, I got hold of the Zingarelli word list, containing some 585,000 Italian words (I can&#8217;t find a working URL, but I got the list a few years ago on a <a href="http://en.wikipedia.org/wiki/Scrabble" target="_blank">Scrabble</a>-related page). I ran three tests: insertion, successful search, and failed search. The list is broken into two parts, one containing 90% of the words, to be inserted, and 10% of the words where kept for the unsuccessful search test.</p>
<p>The insertion test consisted into inserting all of Zingarelli&#8217;s list into both data structures, in the most simplistic way: scanning the list sequentially and inserting items one by one.</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.75s</td>
<td>~699000</td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.76s</td>
<td>~690000</td>
</tr>
</table>
<p>Insertion times are about the same; so we cannot conclude anything special here except maybe that the insertion time is largely dominated by memory allocation and copy. For the successful search (10,000 tries in each case):</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.047s</td>
<td>~209000</td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.006s</td>
<td>~1.6&#215;10<sup>6</sup></td>
</tr>
</table>
<p>Map look-up is <em>immensely</em> faster with <tt>std::unordered_map</tt>, a ratio of about 8:1! Failed searches exhibit the same behavior. For ~60,000 failed searches:</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.263s</td>
<td>~37700</td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.037s</td>
<td>~268000</sup></td>
</tr>
</table>
<p>We see the same kind of differences here again, but the failed searches are much slower than the successful searches.</p>
<p>When we repeat the experiment with integers (with the same kind of numbers; 500,000 integers of which 10% are randomly chosen for the failed searches), we get essentially the same picture but a massive speedup as strings are rather costly to copy. Indeed, for the insertion:</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.19s</td>
<td>2.3&#215;10<sup>6</sup></td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.10s</td>
<td>4.5&#215;10<sup>6</sup></td>
</tr>
</table>
<p>Now, we see the algorithmic difference between the two algorithms as the time spent allocating and copying strings is eliminated. For successful and failed searches, we get (again for 10,000 look-ups):</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.015s</td>
<td>0.7&#215;10<sup>6</sup></td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.005s</td>
<td>2.0&#215;10<sup>6</sup></td>
</tr>
</table>
<p>and:</p>
<table align="center" border="1">
<tr>
<td></td>
<td>wall time</td>
<td>op/s</td>
</tr>
<tr>
<td><tt>std::map</tt></td>
<td>0.082s</td>
<td>0.1&#215;10<sup>6</sup></td>
</tr>
<tr>
<td><tt>std::unordered_map</tt></td>
<td>0.009s</td>
<td>1.1&#215;10<sup>6</sup></td>
</tr>
</table>
<p>The <tt>std::unordered_map</tt> therefore seems to be much faster than <tt>std::map</tt>. What have we lost in order to gain this speed? First, a lot of memory as hash table must retain a certain sparseness to sport their average constant-time look-ups; and the ordering of keys. Listing the items sorted in a hash map won&#8217;t produce an ordered list, but rather a randomized version of the list. <tt>std::map</tt> on the other hand, allow lexicographic enumeration of its contents.</p>
<p align="center">*<br />*&#8195;*</p>
<p>So you&#8217;re reading this and are thinking, <em>mmppfh, of course, it&#8217;s a hash table, you nitwit</em>. Well, yes. Maybe so.</p>
<p>But here&#8217;s what prompted me to do the test. Red-black trees offer <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access. But that&#8217;s assuming (and quite wrongly) that comparing keys can be performed in constant time. This may be true for simple keys, such as machine-size integers (known in C and C++ as <tt>int</tt>) but not so for more complex data, like strings and other structures. For string, for example, comparison may still be very fast because the cost of comparing two string only depends on the longest common prefix; if two long strings have differences in the first few characters, comparison terminates rapidly and the cost is moderate. If, on the other hand, the string share a very long prefix, then the comparison algorithm must scan both strings until the end is reached or a difference is found; this can be very long. So, lets <img src='http://l.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' /> be the average common prefix length. The expected search time is now <img src='http://l.wordpress.com/latex.php?latex=O%28p+%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(p \lg n)' title='O(p \lg n)' class='latex' /> which can grow large if <img src='http://l.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' /> is large.</p>
<p>For a hash table look-up, you must first compute the hash key which can be at best done in linear time in the average key length. In our first case, this length is the average string length. Let this average length be <img src='http://l.wordpress.com/latex.php?latex=h&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='h' title='h' class='latex' />. The number of probe is <img src='http://l.wordpress.com/latex.php?latex=c_n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c_n' title='c_n' class='latex' /> a small constant that depends on the sparseness of the table and the number of items, <img src='http://l.wordpress.com/latex.php?latex=n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='n' title='n' class='latex' />, it contains. For each of those <img src='http://l.wordpress.com/latex.php?latex=c_n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c_n' title='c_n' class='latex' /> probes, a string comparison is performed, leading to an expected complexity of <img src='http://l.wordpress.com/latex.php?latex=O%28c_n+h+p%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(c_n h p)' title='O(c_n h p)' class='latex' />.</p>
<p>Now, it is not clear when <img src='http://l.wordpress.com/latex.php?latex=p+%5Clg+n+%5Cgeqslant+c_n+h+p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \lg n \geqslant c_n h p' title='p \lg n \geqslant c_n h p' class='latex' />. Both <img src='http://l.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' /> cancel, which boils down to <img src='http://l.wordpress.com/latex.php?latex=%5Clg+n+%5Cgeqslant+c_n+h&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\lg n \geqslant c_n h' title='\lg n \geqslant c_n h' class='latex' />. So, in <em>some</em> conditions, it may be possible to make the tree appear faster than the hash table.</p>
<p>On the average, however, the hash map should win becase we expect <img src='http://l.wordpress.com/latex.php?latex=c_n+%26%2360%3B%26%2360%3B+%5Clg+n&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c_n &lt;&lt; \lg n' title='c_n &lt;&lt; \lg n' class='latex' />.</p>
<p align="center">*<br />*&#8195;*</p>
<p>A <a href="http://en.wikipedia.org/wiki/Cargo_cult" target="_blank">cargo cult</a> is described as:</p>
<blockquote><p>
A cargo cult is a type of religious practice that may appear in primitive tribal societies in the wake of interaction with technologically advanced, non-native cultures. The cults are focused on obtaining the material wealth of the advanced culture through magical thinking, religious rituals and practices, believing that the wealth was intended for them by their deities and ancestors.
</p></blockquote>
<p></p>
<p>Except from the part with ancestor spirits but especially when considering <a href="http://en.wikipedia.org/wiki/Magical_thinking" target="_blank">magical thinking</a>, cargo culting applies very often to how programmers write code and take decisions about data structures and algorithms. Choosing a red-black tree over an AVL, or over a <a href="http://en.wikipedia.org/wiki/Splay_tree" target="_blank">splay</a> tree, because we think that it is somehow always better&#8212;sometimes because Ancestor X (a more or less reliable source or authority, such as a more experience programmer, a teacher, or some Internet <a href="http://en.wikipedia.org/wiki/Dude" target="_blank">dude</a>) said so&#8212;is a form of cargo cult where the programmer does not use rationality to its full extent to make a decision.</p>
<p>When choosing data structures, one must be fully aware of the dual cost of data structures. The first cost is the run-time cost. Theoretical complexity and actual implementation-dependant run-times may be quite different. The second cost is memory usage. Memory is large on modern systems but not infinite. A particularly wasteful method that offers constant-time access to the data may use as much as, say, ten times the memory used by a method that gives you <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access. If for small data set this 10&#215; memory usage pose no particular problem, it may be quite different with a largish data set. It&#8217;s all a very delicate balancing act between run-time performance and scalability.</p>
<p>It&#8217;s very hard to trust one&#8217;s gut feelings about a data structure and the data put in. Combined with the access patterns, the data structure may yield a very counter-intuitive performance. Rather than giving into magic thinking cargo cult programming, you should <em>always</em> take a little time to validate our assumptions and hypotheses about the data, the data structure, and the access patterns, as data structure behavior is clearly <em>not</em> independent from the data and the access patterns.</p>
<p>Consider this very simple example. We have a simple binary tree and a list of strings. Binary trees offer <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> insertion and access times, so it is, <i>a priori</i>, a good choice. Now, the list of string is composed of words, but it so happens it&#8217;s already sorted. If we insert the strings in the order they are in the list, we get a degenerate binary-tree that&#8217;s in fact a list! Indeed so: insertions are always performed at the far right of the tree, causing the tree to degenerate into something we could call a <em>vine</em> and then all operations degenerate to linear time. If we randomize the list and insert the words into the tree in that randomized order, we get a ragged tree, but about equally deep everywhere, leading to the expected <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access and insertion time.</p>
<p>The sorted list / binary tree example is an over-simplistic one, I admit, but it gets to the point: the programmer used a data structure cargo-culted to offer <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clg+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\lg n)' title='O(\lg n)' class='latex' /> access time, but due to his incomplete comprehension of the data (the <em>sorted</em> list) and of the access pattern (inserting items sequentially from the list), the result was disastrous.</p>
<p>But the thing is, we <em>all</em> do that to a certain extent!</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Alberi AVL]]></title>
<link>http://fripp.wordpress.com/2008/02/19/alberi-avl/</link>
<pubDate>Tue, 19 Feb 2008 10:39:25 +0000</pubDate>
<dc:creator>fripp</dc:creator>
<guid>http://fripp.wordpress.com/2008/02/19/alberi-avl/</guid>
<description><![CDATA[Gli alberi AVL sono degli alberi binari bilanciati in altezza. Un albero binario si dice bilanciato ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Gli alberi AVL sono degli alberi binari bilanciati in altezza. Un albero binario si dice bilanciato in altezza se, per ciascun nodo dell&#8217;albero, l&#8217;altezza del sottoalbero sinistro differisce dall&#8217;altezza del sottoalbero destro al più di una unità.</p>
<p>Per gli alberi AVL si parla anche di <i>fattore di sbilanciamento</i> di un nodo e lo si definisce come la differenza tra l&#8217;altezza del sottoalbero sinistro e l&#8217;altezza del sottoalbero destro.  Banalmente, in un albero AVL il fattore di sbilanciamento  di ciascun nodo è, in valore assoluto, <img src='http://l.wordpress.com/latex.php?latex=+%5Cleq+1&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' \leq 1' title=' \leq 1' class='latex' />.</p>
<p>A differenza di un albero binario &#8220;tradizionale&#8221;, un albero AVL mantiene la proprietà di bilanciamento in qualsiasi circostanza, sia dopo un inserimento di un nuovo valore che dopo la cancellazione.</p>
<p>Si può dimostrare che l&#8217;altezza di un albero AVL di n nodi è sempre <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clog+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\log n)' title='O(\log n)' class='latex' /> e quindi tutte le operazioni di gestione dell&#8217;albero (ricerca, inserimento e cancellazione) hanno costo <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clog+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\log n)' title='O(\log n)' class='latex' />.<br />
<!--more--><br />
Per mantenere il bilanciamento dell&#8217;albero in seguito a inserimenti o cancellazioni si devono effettuare delle particolari rotazioni, semplici o composte, che permettono di riequilibrare l&#8217;albero.</p>
<p>Abbiamo 4 tipi principali di rotazioni, che vengono applicate in base alla tipologia di sbilanciamento che si vuole corregere. Supponiamo di chiamare v il <i>nodo critico, </i>ovvero il nodo più profondo dell&#8217;albero che ha un fattore di sbilanciamento in modulo uguale a 2;  possiamo trovarci in 4 casi distinti, che necessitano di rotazioni differenti:</p>
<ul>
<li>Rotazione SS: si verifica quando a determinare lo sbilanciamento è il figlio sinistro del sottoalbero sinistro del nodo v</li>
<li>Rotazione DD: si verifica quando a determinare lo sbilanciamento è il figlio destro del sottoalbero destro del nodo v</li>
<li>Rotazione SD: si verifica quando a determianre lo sbilanciamento è il figlio destro del sottoalbero sinistro del nodo v</li>
<li>Rotazione DS: si verifica quando a determianre lo sbilanciamento è il figlio sinistro del sottoalbero destro del nodo v</li>
</ul>
<p>I 4 casi sono simmetrici a coppie (SS con DD, SD con DS).</p>
<p>Nel caso sia necessaria una rotazione SS, per ribilanciare il nodo v occorrerà applicare una rotazione semplice verso destra su v.</p>
<p>Nel caso sia necessaria una rotazione SD, per ribilanciare il nodo v occorrerà una doppia rotazione: sia z il figlio sinistro di v; l&#8217;abero T che sbilancia v è il sottoalbero destro di z, radicato in w. La rotazione SD consiste in una rotazione semplice verso sinistra con perno in z seguita da una rotazione di base verso destra con perno in v.</p>
<p><a href="http://fripp.wordpress.com/files/2008/02/ss.png" title="ss.png"></a></p>
<div style="text-align:center;" align="left"><a href="http://fripp.wordpress.com/files/2008/02/ss.png" title="ss.png"><img src="http://fripp.wordpress.com/files/2008/02/ss.png" alt="ss.png" align="middle" height="147" width="371" /></a></div>
<div style="text-align:center;" align="left"></div>
<p>La precedente immagine mostra un&#8217;esempio di rotazione semplice verso destra, imperniata sul nodo di etichetta b; la rotazione verso sinistra è perfettamente simmetrica.</p>
<p>Di seguito troverete il codice C per eseguire le 4 rotazioni.</p>
<pre class="brush: cpp;">

struct node{
    void *data;
    size_t data_size;
    //h è l'ltezza del nodo
    int h;
    struct node *left;
    struct node *right;
    struct node *father;
};

static struct node* ss( struct node* root ){
    printf(&quot;Rotazione ss\n&quot;);
    struct node* x;

    //effettuiamo la rotazione
    x = root-&gt;left;
    root-&gt;left = x-&gt;right;
    x-&gt;right = root;

    //aggiorniamo le altezze dei nodi coinvolti
    root-&gt;h = MAX( HEIGHT( root-&gt;left ), HEIGHT( root-&gt;right ) ) + 1;
    x-&gt;h = MAX( HEIGHT( x-&gt;left ), x-&gt;h ) + 1;

    x-&gt;father=x-&gt;right-&gt;father;
    if(x-&gt;father){
        if(x-&gt;right-&gt;father-&gt;left==x-&gt;right)
            x-&gt;right-&gt;father-&gt;left=x;
        else if(x-&gt;right-&gt;father-&gt;right==x-&gt;right)
            x-&gt;right-&gt;father-&gt;right=x;
    }

    x-&gt;right-&gt;father=x;
    if(x-&gt;right-&gt;left)
        x-&gt;right-&gt;left-&gt;father=x-&gt;right;

    return x;
}

/*
 * La funzione dd effettua una rotazione semplice verso sinistra.
 * La funzione prende in ingresso il nodo perno
 */

static struct node* dd( struct node* root ){
    printf(&quot;Rotazione dd\n&quot;);
    struct node* x;

    //effettuiamo la rotazione
    x = root-&gt;right;
    root-&gt;right = x-&gt;left;
    x-&gt;left = root;

    //aggiorniamo le altezze dei nodi coinvolti
    root-&gt;h = MAX( HEIGHT( root-&gt;left ), HEIGHT( root-&gt;right ) ) + 1;
    x-&gt;h = MAX( HEIGHT( x-&gt;right ), root-&gt;h ) + 1;

    x-&gt;father=x-&gt;left-&gt;father;
    if(x-&gt;father){
        if(x-&gt;left-&gt;father-&gt;left==x-&gt;left)
            x-&gt;left-&gt;father-&gt;left=x;
        else if(x-&gt;left-&gt;father-&gt;right==x-&gt;left)
            x-&gt;left-&gt;father-&gt;right=x;
    }
    x-&gt;left-&gt;father=x;
    if(x-&gt;left-&gt;right)
        x-&gt;left-&gt;right-&gt;father=x-&gt;left;

    return x;
}

/*
 * La funzione sd effettua una rotazione composta, prima verso sinistra con perno nel figlio sinistro del nodo crtico,
 * poi verso destra con perno nel nodo critico stesso.
 * La funzione prende in ingresso il nodo critico
 */

static struct node* sd( struct node* root ){
    printf(&quot;Rotazione sd\n&quot;);

    root-&gt;left = dd( root-&gt;left );

    return ss( root );
}

static struct node* ds( struct node* root ){
    printf(&quot;Rotazione sd\n&quot;);

    root-&gt;right = ss( root-&gt;right );

    return dd( root );
}
</pre>
<p>Le 4 funzioni prendono in ingresso il &#8220;nodo critico&#8221;, ovvero il più profondo nodo con fattore di sbilanciamento in modulo uguale a 2. Le funzioni mantengono pure i &#8220;rapporti di paternità&#8221; tra i nodi e aggiornano l&#8217;altezza dei nodi coivolti nella rotazione.La funzione di inserimento è semplice da implementare. Il criterio su cui si basa è lo stesso su cui si basa la funzione di inserimento ricorsivo per un normale albero binario; l&#8217;unica aggiunta sta nel controllo dello sbilanciamento dopo l&#8217;inserimento.Ecco il codice:</p>
<pre class="brush: cpp;">

inline struct node* avl_insert(struct node* root, void *data, size_t s,compare_function compare){

    if(!root){

        root=node_alloc(data,s);
        root-&gt;father=0;

    }else if(compare(data,root-&gt;data)&lt;0){
        root-&gt;left=avl_insert(root-&gt;left,data,s,compare);
        root-&gt;left-&gt;father=root;

        /*
         * Dopo l'inserimento del nuovo nodo controlliamo se si verifica uno sbilanciamento.
         * Se si, controlliamo le caratteristiche dello sbilanciamento per decidere che tipo di rotazione effettuare
         */
        if((HEIGHT(root-&gt;left) - HEIGHT(root-&gt;right)) == 2){

            if(compare(data,root-&gt;left-&gt;data)&lt;0){

                //effettuaiamo una rotazione ss
                root=ss(root);

            }else{
                //rotazione sd
                root=sd(root);

            }
        }
    }else if(compare(data,root-&gt;data)&gt;0){
        root-&gt;right=avl_insert(root-&gt;right,data,s,compare);
        root-&gt;right-&gt;father=root;

        //Stesse considerazioni fatte sopra
        if((HEIGHT(root-&gt;right) - HEIGHT(root-&gt;left))==2){

            if(compare(data,root-&gt;right-&gt;data)&gt;0){
                root=dd(root);

            }else{
                root=ds(root);

            }
        }
    }

    //Aggiorniamo l'altezza del nodo dopo l'inserimento
    root-&gt;h=MAX(HEIGHT(root-&gt;left),HEIGHT(root-&gt;right))+1;

    return root;
}
</pre>
<p>Ho implementato pure la funzione di cancellazione. Il codice di quest&#8217;ultima funzione e di tutte le altre lo potrete scaricare dal mio repository a <a href="http://www.mediafire.com/?3mew1mbu2xx" target="_blank">questo</a> link.Occorre sottolineare che, mentre nel caso degli inserimenti al più si effettua una sola rotazione, nel caso della cancellazione di un nodo si posson fare <img src='http://l.wordpress.com/latex.php?latex=O%28%5Clog+n%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='O(\log n)' title='O(\log n)' class='latex' /> rotazioni consecutive.Per approfondimenti, cliccate <a href="http://en.wikipedia.org/wiki/AVL_tree" target="_blank">qui</a>.</p>
</div>]]></content:encoded>
</item>

</channel>
</rss>
