<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Population</title>
</head>

<body>



<p align="center"><font size="6" color="#FF0000"><span lang="en-ca"><b>AVLTree</b></span><b>(with 
remove)</b></font></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A. Second Edition</font></b></pre>
</div>
<div align="left">
  <pre><b>This is second<span lang="en-ca"> edition of my AVL Tree </span>and the reason I restart this project is that I was blamed for not finishing</b></pre>
</div>
<div align="left">
  <pre><b>remove function. So, let's finish it and it is so &quot;Ad-Hoc&quot;.</b></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.<span lang="en-ca"><a name="problem"></a>The problem</span></font></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>To write AVL tree on template basis and try to keep as much as possible of original BST frame work</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>because the code by Mr. Shaffer is very concise and compact! And efficiency is also a very important</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>issue here. As AVLTree has to store extra information than a BST, it is expected that we need to </b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>reduce as many &quot;balancing operations&quot; as possible. </b></font></span></pre>
</div>
<div align="left">
  <b><font color="#ff0000" size="5"><span lang="en-ca"><a name="explain"></a>C</span>.<span lang="en-ca">The
  </span></font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>idea of 
  program</b></font></span></div>
<div align="left">
  　</div>
<p><b>The main idea is similar to &quot;insert&quot; except that the trouble node is not 
always at same side as </b></p>
<p><b>the removed node, while for inserting, it is always the case. One more 
problem is that the son node </b></p>
<p><b>of the &quot;Axis&quot; node can have a balance factor of 0! What's worse, his 
brother may also has 0 as its</b></p>
<p><b>balance factor while their parent has a +/-2 as factor! What should we do 
about it? It seems there</b></p>
<p><b>is no algorithm about remove. Should I check &quot;data structure&quot; text book 
for confirmation? </b></p>
<div align="left">
  <pre><b><font color="#ff0000" size="5">D.<span lang="en-ca"><a name="Method"></a>The </span>major functions</font></b></pre>
</div>
<div align="left">
  <pre><b><font size="3"><span lang="en-ca">1. bool insert(const Elem&amp; e)</span></font></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>Do you expect that I might start from here? But no, I didn't change anything here. And it is only </b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>after I finished, I thought I can omit it even &quot;inserthelp&quot; is not virtual.</b></font></span></pre>
</div>
<div align="left">
  <pre><font size="3"><b>2. BinNode&lt;Elem&gt;* inserthelp(BinNode&lt;Elem&gt;*, const Elem&amp;);</b></font></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>This function is almost same as original BST except I try to update the height after each insertion</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>which will go up from the inserted new leaf along path. And before that insertion, I placed a road</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>sign &quot;inLeaf&quot; to indicate which side the path takes.</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>3. void updateHeight(BinNode&lt;Elem&gt;*&amp; subroot);</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>This is the key part of program where you update height first and then try to examine the balance</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>and try to keep it. It is the tricky part as I change the code many times. Finally I realized that</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>there are two big cases: a) The first root which is also the first node with factor 2/-2; b) The node</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>whose son node has factor of 2/-2; There are some extra conditions to examine the &quot;first&quot; in a) to </b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>make sure it is the &quot;first&quot;. </b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>4. int getTreeHeight(BinNode&lt;Elem&gt;* subroot);</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>I resist to use recursive method because the field &quot;height&quot; is a short-cut.</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>5. BinNode&lt;Elem&gt;* singleRotate(BinNode&lt;Elem&gt;* parent, bool isRoot, bool left2right);</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>Don't forget to adjust balance after rotating and the sequence is important as you have to do it from</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>bottom-up.</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>6. BinNode&lt;Elem&gt;* doubleRotate(BinNode&lt;Elem&gt;* parent, bool isRoot, bool left2right);</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>I made it look simple by adding the &quot;doDouble&quot; and quite satisfy with it.</b></font></span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">E</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Further improvement</b></font></span></pre>
</div>
<div align="left">
  <pre>　</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">F</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>File listing</b></font></span></pre>
</div>
<div align="left">
  <pre><b><font size="3"><span lang="en-ca">1. AVLTree.h</span></font></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>2. BinNode.h</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>3. BST.h</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>4. dictionary.h</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>5. Elem.h</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>6. AVLTree.cpp  (main)</b></font></span></pre>
</div>
<div align="left">
  <pre>　</pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: BinNode.h</b></font></span></pre>
</div>
<pre>// Binary tree node abstract class
template &lt;class Elem&gt; class BinNode {
public:
	// Return the node's element
	virtual Elem&amp; val() = 0;
	// Set the node's element
	virtual void setVal(const Elem&amp;) = 0;
	// Return the node's left child
	virtual BinNode* left() const = 0;
	// Set the node's left child
	virtual void setLeft(BinNode*) = 0;
	// Return the node's right child
	virtual BinNode* right() const = 0;
	// Set the node's right child
	virtual void setRight(BinNode*) = 0;
	// Return true iff the node is a leaf
	virtual bool isLeaf() = 0;
	//my personal preference
	virtual BinNode&lt;Elem&gt;* getSon(bool isLeft)const=0; 
	//my personal preference
	virtual void setSon(BinNode&lt;Elem&gt;* son, bool isLeft)=0;
};

// Binary tree node class
template &lt;class Elem&gt;
class BinNodePtr : public BinNode&lt;Elem&gt; {
private:
	Elem it;                     // The node's value
	BinNodePtr* lc;              // Pointer to left child
	BinNodePtr* rc;              // Pointer to right child
public:
	// Two constructors -- with and without initial values
	BinNodePtr() { lc = rc = NULL; }
	BinNodePtr(Elem e, BinNodePtr* l =NULL,
					 BinNodePtr* r =NULL)
	{ it = e; lc = l; rc = r; }
	~BinNodePtr() {}             // Destructor
	Elem&amp; val() { return it; }
	void setVal(const Elem&amp; e) { it = e; }
	inline BinNode&lt;Elem&gt;* left() const { return lc; }
	void setLeft(BinNode&lt;Elem&gt;* b) { lc = (BinNodePtr*)b; }
	inline BinNode&lt;Elem&gt;* right() const { return rc; }
	void setRight(BinNode&lt;Elem&gt;* b) { rc = (BinNodePtr*)b; }
	bool isLeaf() { return (lc == NULL) &amp;&amp; (rc == NULL); }
	BinNode&lt;Elem&gt;* getSon(bool isLeft)const {return isLeft?lc:rc;}
	void setSon(BinNode&lt;Elem&gt;* son, bool isLeft)
	{
		isLeft?setLeft(son):setRight(son);
	}
};


template &lt;class Elem&gt;
class AVLNodePtr : public BinNode&lt;Elem&gt; 
{
protected:
	Elem it;                     // The node's value
	AVLNodePtr* lc;              // Pointer to left child
	AVLNodePtr* rc;              // Pointer to right child
	int height;
	bool inLeft;
public:
 // Two constructors -- with and without initial values
	AVLNodePtr() { lc = rc = NULL; height=1; inLeft=true; }
	AVLNodePtr(Elem e, AVLNodePtr&lt;Elem&gt;* l =NULL,
					 AVLNodePtr&lt;Elem&gt;* r =NULL, int newHeight=1)
	{ it = e; lc = l; rc = r; height=newHeight; inLeft=true;}
	~AVLNodePtr() {}             // Destructor
	Elem&amp; val() { return it; }
	void setVal(const Elem&amp; e) { it = e; }
	BinNode&lt;Elem&gt;* left() const { return lc; }
	void setLeft(BinNode&lt;Elem&gt;* b) { lc = (AVLNodePtr*)b; }
	inline BinNode&lt;Elem&gt;* right() const { return rc; }
	void setRight(BinNode&lt;Elem&gt;* b) { rc = (AVLNodePtr*)b; }
	bool isLeaf() { return (lc == NULL) &amp;&amp; (rc == NULL); }
	void setHeight(int newHeight){height=newHeight;}
	int getHeight(){return height;}
	BinNode&lt;Elem&gt;* getSon(bool isLeft)const {return isLeft?lc:rc;}
	bool getSide() const {return inLeft;}
	void setSide(bool isLeft){ inLeft=isLeft;}
	void setSon(BinNode&lt;Elem&gt;* son, bool isLeft)
	{
		isLeft?setLeft(son):setRight(son);
	}

};</pre>
<pre>　</pre>
<pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: BST.h</b></font></span></pre>
<pre>// This file includes all of the pieces of the BST implementation

#include &quot;dictionary.h&quot;

#include &quot;binnode.h&quot;

// Binary Search Tree implementation for the Dictionary ADT
template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
class BST : public Dictionary&lt;Key, Elem, KEComp, EEComp&gt; {
protected:
  BinNode&lt;Elem&gt;* root;   // Root of the BST
  int nodecount;         // Number of nodes in the BST
  // Private &quot;helper&quot; functions
  void clearhelp(BinNode&lt;Elem&gt;*);
  BinNode&lt;Elem&gt;* inserthelp(BinNode&lt;Elem&gt;*, const Elem&amp;);
  BinNode&lt;Elem&gt;* deletemin(BinNode&lt;Elem&gt;*, BinNode&lt;Elem&gt;*&amp;);
  BinNode&lt;Elem&gt;* removehelp(BinNode&lt;Elem&gt;*, const Key&amp;,
                            BinNode&lt;Elem&gt;*&amp;);
  bool findhelp(BinNode&lt;Elem&gt;*, const Key&amp;, Elem&amp;) const;
  void printhelp(BinNode&lt;Elem&gt;*, int) const;
public:
  BST() { root = NULL; nodecount = 0; }  // Constructor
  ~BST() { clearhelp(root); }            // Destructor
  void clear()
    { clearhelp(root); root = NULL; nodecount = 0; }
  bool insert(const Elem&amp; e) {
    root = inserthelp(root, e);
    nodecount++;
    return true;
  }
  bool remove(const Key&amp; K, Elem&amp; e) {
    BinNode&lt;Elem&gt;* t = NULL;
    root = removehelp(root, K, t);
    if (t == NULL) return false;  // Nothing found
    e = t-&gt;val();
    nodecount--;
    delete t;
    return true;
  }
  bool removeAny(Elem&amp; e) { // Delete min value
    if (root == NULL) return false; // Empty tree
    BinNode&lt;Elem&gt;* t;
    root = deletemin(root, t);
    e = t-&gt;val();
    delete t;
    nodecount--;
    return true;
  }
  bool find(const Key&amp; K, Elem&amp; e) const
    { return findhelp(root, K, e); }
  int size() { return nodecount; }
  void print() const {
    if (root == NULL) cout &lt;&lt; &quot;The BST is empty.\n&quot;;
    else printhelp(root, 0);
  }
};

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
void BST&lt;Key, Elem, KEComp, EEComp&gt;::
clearhelp(BinNode&lt;Elem&gt;* subroot) {
  if (subroot == NULL) return;
  clearhelp(subroot-&gt;left());
  clearhelp(subroot-&gt;right());
  delete subroot;
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* BST&lt;Key, Elem, KEComp, EEComp&gt;::
inserthelp(BinNode&lt;Elem&gt;* subroot, const Elem&amp; val) {
  if (subroot == NULL)            // Empty tree: create node
    return (new BinNodePtr&lt;Elem&gt;(val, NULL, NULL));
  if (EEComp::lt(val, subroot-&gt;val())) // Insert on left
    subroot-&gt;setLeft(inserthelp(subroot-&gt;left(), val));
  else subroot-&gt;setRight(inserthelp(subroot-&gt;right(), val));
  return subroot;  // Return subtree with node inserted
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* BST&lt;Key, Elem, KEComp, EEComp&gt;::
deletemin(BinNode&lt;Elem&gt;* subroot, BinNode&lt;Elem&gt;*&amp; min) {
  if (subroot-&gt;left() == NULL) { // Found min
    min = subroot;
    return subroot-&gt;right();
  }
  else {                         // Continue left
    subroot-&gt;setLeft(deletemin(subroot-&gt;left(), min));
    return subroot;
  }
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* BST&lt;Key, Elem, KEComp, EEComp&gt;::
removehelp(BinNode&lt;Elem&gt;* subroot, const Key&amp; K,
           BinNode&lt;Elem&gt;*&amp; t) {
  if (subroot == NULL) return NULL; // Val is not in tree
  else if (KEComp::lt(K, subroot-&gt;val())) // Check left
    subroot-&gt;setLeft(removehelp(subroot-&gt;left(), K, t));
  else if (KEComp::gt(K, subroot-&gt;val())) // Check right
    subroot-&gt;setRight(removehelp(subroot-&gt;right(), K, t));
  else {                           // Found it: remove it
    BinNode&lt;Elem&gt;* temp;
    t = subroot;
    if (subroot-&gt;left() == NULL)       // Only a right child
      subroot = subroot-&gt;right();      //  so point to right
    else if (subroot-&gt;right() == NULL) // Only a left child
      subroot = subroot-&gt;left();       //  so point to left
    else {                    // Both children are non-empty
      subroot-&gt;setRight(deletemin(subroot-&gt;right(), temp));
      Elem te = subroot-&gt;val();
      subroot-&gt;setVal(temp-&gt;val());
      temp-&gt;setVal(te);
      t = temp;
    }
  }
  return subroot;
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
bool BST&lt;Key, Elem, KEComp, EEComp&gt;:: findhelp(
      BinNode&lt;Elem&gt;* subroot, const Key&amp; K, Elem&amp; e) const {
  if (subroot == NULL) return false;         // Empty tree
  else if (KEComp::lt(K, subroot-&gt;val()))    // Check left
    return findhelp(subroot-&gt;left(), K, e);
  else if (KEComp::gt(K, subroot-&gt;val()))    // Check right
    return findhelp(subroot-&gt;right(), K, e);
  else { e = subroot-&gt;val();  return true; } // Found it
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
void BST&lt;Key, Elem, KEComp, EEComp&gt;::
printhelp(BinNode&lt;Elem&gt;* subroot, int level) const {
  if (subroot == NULL) return;          // Empty tree
  printhelp(subroot-&gt;left(), level+1);  // Do left subtree
  for (int i=0; i&lt;level; i++)           // Indent to level
    cout &lt;&lt; &quot;  &quot;;
  cout &lt;&lt; subroot-&gt;val() &lt;&lt; &quot;\n&quot;;       // Print node value
  printhelp(subroot-&gt;right(), level+1); // Do right subtree
}
</pre>
<pre>　</pre>
<pre><font color="#FF0000"><span lang="en-ca">file name: <font size="3"><b>dictionary.h</b></font></span></font></pre>
<pre>　</pre>
<pre>// The Dictionary abstract class.  KEComp compares a key
// and an element. EEComp compares two elements.  
template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
class  Dictionary {
public:
  // Reinitialize dictionary
  virtual void clear() = 0;
  // Insert an element.  Return true if insert is
  // successful, false otherwise.
  virtual bool insert(const Elem&amp;) = 0;
  // Remove some element matching Key.  Return true if such
  // exists, false otherwise.  If multiple entries match
  // Key, an arbitrary one is removed.
  virtual bool remove(const Key&amp;, Elem&amp;) = 0;
  // Remove and return an arbitrary element from dictionary.
  // Return true if some element is found, false otherwise.
  virtual bool removeAny(Elem&amp;) = 0;
  // Return a copy of some Elem matching Key.  Return true
  // if such exists, false otherwise.  If multiple elements
  // match Key, return an arbitrary one.
  virtual bool find(const Key&amp;, Elem&amp;) const = 0;
  // Return the number of elements in the dictionary.
  virtual int size() = 0;
};
</pre>
<pre>　</pre>
<pre><font color="#FF0000"><span lang="en-ca">file name: <font size="3"><b>Elem.h</b></font></span></font></pre>
<pre>//This is the element of login system

class KEComp
{
public:
	static bool lt(int key, int elem) {return key&lt;elem;}
	static bool eq(int key, int elem) {return key==elem;}
	static bool gt(int key, int elem) {return key&gt;elem;}
};

class EEComp
{
public:
	static bool lt(int e1, int e2)
		{ return e1&lt;e2;}
	static bool eq(int e1, int e2)
		{ return e1==e2;}
	static bool gt(int e1, int e2)
		{ return e1&gt;e2;}
};</pre>
<pre>　</pre>
<pre><font color="#FF0000"><span lang="en-ca">file name:  </span><b><font size="3"><span lang="en-ca">AVLTree.h</span></font></b></font></pre>
<pre>#include &quot;BST.h&quot;

template&lt;class Elem&gt;
struct Descriptor
{
	BinNode&lt;Elem&gt;* parent;
	bool isRoot;
	bool isLeft;
	bool isSingle;
	bool left2right;
};


template&lt;class Key, class Elem, class KEComp, class EEComp&gt;
class AVL: public BST&lt;Key, Elem, KEComp, EEComp&gt;
{
protected:
//	BinNode&lt;Elem&gt;* startPtr;
	void clearhelp(BinNode&lt;Elem&gt;*);
	virtual BinNode&lt;Elem&gt;* inserthelp(BinNode&lt;Elem&gt;*, const Elem&amp;);	
	bool findhelp(BinNode&lt;Elem&gt;*, const Key&amp;, Elem&amp;) const;
	void printhelp(BinNode&lt;Elem&gt;*, int) const;
	void updateHeight(BinNode&lt;Elem&gt;*&amp; subroot);
	int  getFactor(BinNode&lt;Elem&gt;* subroot);
	void adjust(BinNode&lt;Elem&gt;*&amp; subroot, bool isRoot);
	int getTreeHeight(BinNode&lt;Elem&gt;* subroot);
	void adjustHeight(BinNode&lt;Elem&gt;* subroot);
	BinNode&lt;Elem&gt;* singleRotate(BinNode&lt;Elem&gt;* parent, bool isRoot, bool left2right);
	BinNode&lt;Elem&gt;* doubleRotate(BinNode&lt;Elem&gt;* parent, bool isRoot, bool left2right);
	void checkDir(BinNode&lt;Elem&gt;* subroot, bool&amp; isSingle, bool&amp; left2right);
	BinNode&lt;Elem&gt;* doDouble(BinNode&lt;Elem&gt;* oldRoot, bool left2right);
	virtual BinNode&lt;Elem&gt;* deletemin(BinNode&lt;Elem&gt;*, BinNode&lt;Elem&gt;*&amp;);
	virtual BinNode&lt;Elem&gt;* removehelp(BinNode&lt;Elem&gt;*, const Key&amp;, BinNode&lt;Elem&gt;*&amp;);
public:
	AVL() { root = NULL; nodecount = 0; }  // Constructor
	~AVL() { clearhelp(root); root=NULL; }            // Destructor
	/*
	bool insert(const Elem&amp; e)
	{		
		root = inserthelp(root, e);
		nodecount++;
		return true;
	}
	*/
};

//do not use recursive!!!!!
template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
int AVL&lt;Key, Elem, KEComp, EEComp&gt;::getTreeHeight(BinNode&lt;Elem&gt;* subroot)
{
	AVLNodePtr&lt;Elem&gt;* ptr, *l, *r;
	int newHeight, lHeight, rHeight;//, factor;//, sonFactor;

	if (subroot==NULL)
	{
		return 0;
	}
	
	ptr=(AVLNodePtr&lt;Elem&gt;*)subroot;
	l=(AVLNodePtr&lt;Elem&gt;*)ptr-&gt;left();
	r=(AVLNodePtr&lt;Elem&gt;*)ptr-&gt;right();	
	if (l==NULL)
	{
		lHeight=0;
	}
	else
	{
		lHeight=l-&gt;getHeight();
	}
	if (r==NULL)
	{
		rHeight=0;
	}
	else
	{
		rHeight=r-&gt;getHeight();
	}
	newHeight=1+(lHeight&gt;rHeight?lHeight:rHeight);
	return newHeight;
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
void AVL&lt;Key, Elem, KEComp, EEComp&gt;::adjustHeight(BinNode&lt;Elem&gt;* subroot)
{
	int height;
	if (subroot==NULL)
	{
		return;
	}
	height=getTreeHeight(subroot);
	((AVLNodePtr&lt;Elem&gt;*)(subroot))-&gt;setHeight(height);
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* AVL&lt;Key, Elem, KEComp, EEComp&gt;::doDouble(BinNode&lt;Elem&gt;* oldRoot, 
														bool left2right)
{
	BinNode&lt;Elem&gt; *small, *mid, *big,*t1,*t2,*t3,*t4;
	if (left2right)
	{
		big=oldRoot;//the root;
		small=oldRoot-&gt;left();
		mid=small-&gt;right();
		t1=small-&gt;left();
		t2=mid-&gt;left();
		t3=mid-&gt;right();
		t4=big-&gt;right();
	}
	else
	{
		small=oldRoot;
		big=small-&gt;right();
		mid=big-&gt;left();
		t1=small-&gt;left();
		t2=mid-&gt;left();
		t3=mid-&gt;right();
		t4=big-&gt;right();
	}
	mid-&gt;setLeft(small);
	mid-&gt;setRight(big);
	small-&gt;setLeft(t1);
	small-&gt;setRight(t2);
	big-&gt;setLeft(t3);
	big-&gt;setRight(t4);
	adjustHeight(small);
	adjustHeight(big);
	adjustHeight(mid);
	return mid;
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* AVL&lt;Key, Elem, KEComp, EEComp&gt;::doubleRotate(BinNode&lt;Elem&gt;* parent,
	bool isRoot, bool left2right)
{
	BinNode&lt;Elem&gt;* oldRoot;
	bool isLeft;
		
	if (isRoot)
	{
		oldRoot=parent;
		root=doDouble(oldRoot, left2right);
		
		return root;//because we need parent return as real root
	}
	else
	{
		isLeft=((AVLNodePtr&lt;Elem&gt;*)parent)-&gt;getSide();
		oldRoot=parent-&gt;getSon(isLeft);
		parent-&gt;setSon(doDouble(oldRoot, left2right), isLeft);
		adjustHeight(parent);
		return parent;
	}
}


//if isRoot, we don't need isLeft, it is useful when it is not root and 
//we need to know which son it is in
template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* AVL&lt;Key, Elem, KEComp, EEComp&gt;::singleRotate(BinNode&lt;Elem&gt;* parent,
	bool isRoot, bool left2right)
{
	BinNode&lt;Elem&gt;* oldRoot=parent, *son, *t1;
	bool isLeft=((AVLNodePtr&lt;Elem&gt;*)parent)-&gt;getSide();

	
	if (isRoot)
	{	
		son=parent-&gt;getSon(left2right);
		t1=son-&gt;getSon(!left2right);
		son-&gt;setSon(parent, !left2right);
		parent-&gt;setSon(t1, left2right);
		adjustHeight(parent);//sequence is VERY IMPORTANT!
		adjustHeight(son);//sequence is VERY IMPORTANT!
		
		root=son;
		return son;//because now, we need return son as parent;
		/*
		son=parent-&gt;getSon(isLeft);
		t1=son-&gt;getSon(!left2right);
		son-&gt;setSon(parent, !left2right);
		parent-&gt;setSon(t1, left2right);
		//because parent is at lower level now, we need adjust parent first!!!
		adjustHeight(parent);//sequence is VERY IMPORTANT!
		adjustHeight(son);//sequence is VERY IMPORTANT!
		
		root=son;
		return son;//because now, we need return son as parent;
		*/
	}
	else
	{
		//for non-root rotation, parent doesn't change!!!!!
		//it is now very concise!!
		oldRoot=parent-&gt;getSon(isLeft);
		son=oldRoot-&gt;getSon(left2right);//this is the trick!
		t1=son-&gt;getSon(!left2right);
		parent-&gt;setSon(son, isLeft);
		oldRoot-&gt;setSon(t1, left2right);
		son-&gt;setSon(oldRoot, !left2right);
		//sequence is very important!!!
		adjustHeight(oldRoot);
		adjustHeight(son);
		adjustHeight(parent);//adjust sequence: from low to high!!!
		return parent;
	}
	
}

//check the direction of rotation by returning value in reference
template&lt;class Key, class Elem, class KEComp, class EEComp&gt;
void AVL&lt;Key, Elem, KEComp, EEComp&gt;::checkDir(BinNode&lt;Elem&gt;* subroot, 
											  bool&amp; isSingle, bool&amp; left2right)
{
	BinNode&lt;Elem&gt;* son;
	int parentFactor, sonFactor;
	bool isLeft;
	isLeft=((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;getSide();
	son=subroot-&gt;getSon(isLeft);
	parentFactor=getFactor(subroot);
	//to do
	sonFactor=getFactor(son);
	if (sonFactor==0)
	{
		son=subroot-&gt;getSon(!isLeft);
		sonFactor=getFactor(son);
		if (sonFactor==0)
		{
			isSingle=true;
			left2right=parentFactor&gt;0;
			return;
		}
	}
	isSingle=parentFactor*sonFactor&gt;0;//same sign
	left2right=parentFactor&gt;0;
}

//if isroot, isLeft will be ignored.
template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
void AVL&lt;Key, Elem, KEComp, EEComp&gt;::adjust(BinNode&lt;Elem&gt;*&amp; subroot, bool isRoot)
{
	BinNode&lt;Elem&gt;* temp;
	bool isSingle, left2right, isLeft;
	if (isRoot)
	{
		temp=subroot;
	}
	else
	{
		//use its son to check
		isLeft=((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;getSide();		
		temp=subroot-&gt;getSon(isLeft);
		/*
		if (getFactor(temp)==0)
		{
			temp=subroot-&gt;getSon(!isLeft);
		}
		*/
	}

	checkDir(temp, isSingle, left2right);
	if (isSingle)
	{
		//it helps reading and for singleRotate isLeft is ignored when it is isRoot
		subroot=singleRotate(subroot, isRoot, left2right);
	}
	else
	{
		subroot=doubleRotate(subroot, isRoot, left2right);
	}
}


template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
int AVL&lt;Key, Elem, KEComp, EEComp&gt;::getFactor(BinNode&lt;Elem&gt;* subroot)
{
	int lHeight, rHeight;
	AVLNodePtr&lt;Elem&gt;* ptr, *l, *r;
	if (subroot==NULL)
	{
		return 0;
	}
	ptr=(AVLNodePtr&lt;Elem&gt;*)subroot;
	l=(AVLNodePtr&lt;Elem&gt;*)(ptr-&gt;left());
	r=(AVLNodePtr&lt;Elem&gt;*)(ptr-&gt;right());
	if (l==NULL)
	{
		lHeight=0;
	}
	else
	{
		lHeight= l-&gt;getHeight();
	}
	if (r==NULL)
	{
		rHeight=0;
	}
	else
	{
		rHeight=r-&gt;getHeight();
	}
	return lHeight-rHeight;
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
void AVL&lt;Key, Elem, KEComp, EEComp&gt;::updateHeight(BinNode&lt;Elem&gt;*&amp; subroot)
{
	int factor, sonFactor;
	bool isLeft;
	BinNode&lt;Elem&gt; *son;
	if (subroot==NULL)
	{
		return;
	}
	
	adjustHeight(subroot);

	factor=getFactor(subroot);

	isLeft=((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;getSide();
	son=subroot-&gt;getSon(isLeft);
	sonFactor=getFactor(son);
	//first situation: the first 2/-2 we meet from bottom-up
	if ((factor==2||factor==-2)&amp;&amp;subroot==root)
	{
		//a special case!!! as we search from bottom up
		//we may wait to adjust until we reach its father
		//the father happens to be root. But it is not a
		//root adjustment!!!
		if (sonFactor==1||sonFactor==-1||sonFactor==0)
		{
			adjust(subroot, true);
		}
		else
		{
			adjust(subroot, false);
		}				
	}
	else
	{
		if (sonFactor==2||sonFactor==-2)
		{
			adjust(subroot, false);
		}
	}
}




template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* AVL&lt;Key, Elem, KEComp, EEComp&gt;::inserthelp(BinNode&lt;Elem&gt;* subroot, 
														  const Elem&amp; val)
{
	if (subroot == NULL)            // Empty tree: create node
	{
		return (new AVLNodePtr&lt;Elem&gt;(val, NULL, NULL, 1));
	}
	if (EEComp::lt(val, subroot-&gt;val())) // Insert on left
	{
		((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;setSide(true);
		subroot-&gt;setLeft(inserthelp(subroot-&gt;left(), val));
		updateHeight(subroot);
	}
	else 
	{
		((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;setSide(false);
		subroot-&gt;setRight(inserthelp(subroot-&gt;right(), val));
		updateHeight(subroot);
	}
	return subroot;  // Return subtree with node inserted
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* AVL&lt;Key, Elem, KEComp, EEComp&gt;::
removehelp(BinNode&lt;Elem&gt;* subroot, const Key&amp; K, BinNode&lt;Elem&gt;*&amp; t) 
{
	if (subroot == NULL) 
	{
		return NULL; // Val is not in tree
	}
	else 
	{
		if (KEComp::lt(K, subroot-&gt;val())) // Check left
		{
			((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;setSide(true);
			subroot-&gt;setLeft(removehelp(subroot-&gt;left(), K, t));
			//updateHeight(subroot);
		}
		else
		{
			if (KEComp::gt(K, subroot-&gt;val())) // Check right
			{
				((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;setSide(false);
				subroot-&gt;setRight(removehelp(subroot-&gt;right(), K, t));
				//updateHeight(subroot);
			}
			else
			{                           // Found it: remove it
				BinNode&lt;Elem&gt;* temp;		
				t = subroot;

				if (subroot-&gt;left() == NULL)       // Only a right child
				{
					 subroot = subroot-&gt;right();      //  so point to right					 	
				}
				else 
				{
					if (subroot-&gt;right() == NULL) // Only a left child
					{						
						subroot = subroot-&gt;left();       //  so point to left
					}
					else
					{ 
					// Both children are non-empty
						subroot-&gt;setRight(deletemin(subroot-&gt;right(), temp));
						Elem te = subroot-&gt;val();
						subroot-&gt;setVal(temp-&gt;val());
						temp-&gt;setVal(te);
						t = temp;
						((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;setSide(false);
						//updateHeight(subroot);
					}
				}
			}
		}
	}
	updateHeight(subroot);
	return subroot;
}

template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
BinNode&lt;Elem&gt;* AVL&lt;Key, Elem, KEComp, EEComp&gt;::
deletemin(BinNode&lt;Elem&gt;* subroot, BinNode&lt;Elem&gt;*&amp; min)
{
	if (subroot-&gt;left() == NULL) 
	{ // Found min
		min = subroot;
		return subroot-&gt;right();
	}
	else
	{                         // Continue left
		((AVLNodePtr&lt;Elem&gt;*)subroot)-&gt;setSide(true);						
		subroot-&gt;setLeft(deletemin(subroot-&gt;left(), min));
		updateHeight(subroot);
		return subroot;
	}
}


template &lt;class Key, class Elem, class KEComp, class EEComp&gt;
void AVL&lt;Key, Elem, KEComp, EEComp&gt;::clearhelp(BinNode&lt;Elem&gt;* subroot) 
{
	if (subroot == NULL)
	{
		return;
	}
	clearhelp(subroot-&gt;left());
	clearhelp(subroot-&gt;right());
	delete subroot;	
}

</pre>
<pre><font color="#FF0000"><span lang="en-ca">file name: <font size="3"><b>AVLTree.cpp  (main)</b></font></span>
</font></pre>
<pre>#include &lt;iostream&gt;
#include &lt;time.h&gt;
#include &quot;AVLTree.h&quot;
#include &quot;Elem.h&quot;


using namespace std;

int main()
{
	int num;
	AVL&lt;int, int, KEComp, EEComp&gt; A;
	//srand(time(0));
	for (int i=0; i&lt;20; i++)
	{
		cout&lt;&lt;&quot;===================&quot;;
		num=rand()%100+12;
		cout&lt;&lt;&quot;insert number &quot;&lt;&lt;num&lt;&lt;endl;
		A.insert(num);
		A.print();
	}
	for (i=0; i&lt;20; i++)
	{
		int temp;
		cin&gt;&gt;num;
		A.remove(num, temp);
		cout&lt;&lt;&quot;\nnow remove number&quot;&lt;&lt;num&lt;&lt;endl;
		A.print();
	}

	return 0;
}
</pre>
<pre>
<font color="#0000FF"><b>Here is the result:<span lang="en-ca"> Please note that there are </span></b></font></pre>
<pre><font color="#0000FF"><b><span lang="en-ca">single rotating while inserting number 90, 93, 107, </span></b></font></pre>
<pre><span lang="en-ca"><font color="#0000FF"><b>double rotating while inserting number 36, 74, </b></font></span></pre>
<pre>===================insert number 53
53
===================insert number 79
53
  79
===================insert number 46
  46
53
  79
===================insert number 12
    12
  46
53
  79
===================insert number 81
    12
  46
53
  79
    81
===================insert number 36
    12
  36
    46
53
  79
    81
===================insert number 90
    12
  36
    46
53
    79
  81
    90
===================insert number 70
    12
  36
    46
53
      70
    79
  81
    90
===================insert number 74
    12
  36
    46
53
      70
    74
      79
  81
    90
===================insert number 76
    12
  36
    46
53
      70
    74
      76
  79
    81
      90

input the number to remove: 79

now remove number79
    12
  36
    46
53
      70
    74
      76
  81
    90

input the number to remove: 12

now remove number12
  36
    46
53
      70
    74
      76
  81
    90

input the number to remove: 46

now remove number46
    36
  53
    70
74
    76
  81
    90

input the number to remove: 81

now remove number81
    36
  53
    70
74
    76
  90

input the number to remove: 76

now remove number76
    36
  53
    70
74
  90

input the number to remove: 90

now remove number90
  36
53
    70
  74

input the number to remove: 36

now remove number36
  53
70
  74

input the number to remove: 70

now remove number70
  53
74

input the number to remove: 74

now remove number74
53

input the number to remove: 53

now remove number53
The BST is empty.
Press any key to continue</pre>
<pre>　</pre>

<pre></pre>

<pre></pre>
<pre>	
</pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp; <a href="WhoAmI.htm">                  







                       <img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<a href="index.htm">
<img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a>       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                         
<img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35">          


</p>

</body>

</html>