<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>Min-Max 
Heap</b></span><b>£¨<span lang="en-ca">3</span>£©</b></font></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A. <span lang="en-ca">Third</span> Edition</font></b></pre>
</div>
<div align="left">
  <pre><b>This is <span lang="en-ca">third edition of my min-max-heap and this edition is really a practical one which means it indeed solves</span></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>some problems</b></span><b><span lang="en-ca">.</span></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><font size="3"><span lang="en-ca"><b>How to find out the median of an array of integer with an algorithm of O(n)?</b></span></font></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><span lang="en-ca"><b>It is said that if you want to do a good job, you need 
first have a good tool. It is the case as I </b></span></p>
<p><span lang="en-ca"><b>plan this ahead for the tool in two editions. I created 
two heaps, one is max-heap and the other is</b></span></p>
<p><span lang="en-ca"><b>min-heap with such a property that the median is not 
less than the max of max-heap and is not bigger</b></span></p>
<p><span lang="en-ca"><b>than the min of min-heap. Then indeed the median is not 
less than all elements in max-heap and not</b></span></p>
<p><span lang="en-ca"><b>bigger than all elements in min-heap. Now the problem 
is how to keep this median to be median which</b></span></p>
<p><span lang="en-ca"><b>means that the two heaps must be in a balanced mode. 
Here &quot;balance&quot; is very similar to that of a </b></span></p>
<p><span lang="en-ca"><b>AVL Tree with two sides of maximum difference in number 
of elements not bigger than 1. If not </b></span></p>
<p><span lang="en-ca"><b>balanced, we need to shift. For example, the max-heap 
has 4 elements, and min-heap has 6 elements.</b></span></p>
<p><span lang="en-ca"><b>It means that the min-heap needs to remove the min one 
and makes it median and the original median</b></span></p>
<p><span lang="en-ca"><b>should be inserted into max-heap.</b></span></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 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><span lang="en-ca"><b><font size="3">I found out a serious bug  in previous edition of &quot;siftdown&quot; which exceeds the boundary of array.</font></b></span></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. heap.h</span></font></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>2. heap.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: heap.h</b></font></span></pre>
</div>
<pre>
template&lt;class Elem&gt;
void swap(Elem* array, int i, int j)
{
	Elem temp;
	temp=array[i];
	array[i]=array[j];
	array[j]=temp;
}

template&lt;class Key, class Elem,  class KEComp, class EEComp&gt;
class Heap
{
private:
	bool reversed;
	Elem* array;
	int maxLength;
	int curLength;
	void siftDown(int index);
	void siftUp(int index);
	int parent(int index) { return (index-1)/2;}
	int left(int index) { return index*2+1;}
	int right(int index) { return index*2+2;}
	bool isLeaf(int index) { return left(index)&gt;=curLength;}
	bool EEcompare(Elem e1, Elem e2);
	void insert(bool fromHead=false);//two choices:from head or from end
public:
	bool insert(const Elem&amp; e);
	void buildHeap();
	void display();
	bool removeHead(Elem&amp; e);
	void setDirection(bool direction){reversed=direction;}
	Heap(Elem* theArray, int size, int maxSize=20)
	{array=theArray; curLength=size; maxLength=maxSize; reversed=false;}
};

template&lt;class Key, class Elem, class KEComp, class EEComp&gt;
bool Heap&lt;Key, Elem, KEComp, EEComp&gt;::removeHead(Elem&amp; e)
{
	if (curLength==0)
	{
		cout&lt;&lt;&quot;heap is empty\n&quot;;
		return false;
	}
	curLength--;
	swap(array, 0, curLength);
	e=array[curLength];
	siftDown(0);
	return true;
}



template&lt;class Key, class Elem, class KEComp, class EEComp&gt;
bool Heap&lt;Key, Elem, KEComp, EEComp&gt;::insert(const Elem&amp; e)
{	
	if (curLength==maxLength)
	{
		cout&lt;&lt;&quot;the heap is full\n&quot;;
		return false;
	}
	//else
	curLength++;
	array[curLength-1]=e;
	siftUp(curLength-1);
	return true;
}


template&lt;class Key, class Elem, class KEComp, class EEComp&gt;
void Heap&lt;Key, Elem, KEComp, EEComp&gt;::insert(bool fromHead)
{
	curLength++;
	if (fromHead)
	{
		array--;
		siftDown(0);
	}
	else
	{
		siftUp(curLength-1);
	}
}


template&lt;class Key, class Elem,  class KEComp, class EEComp&gt;
void Heap&lt;Key, Elem, KEComp, EEComp&gt;::buildHeap()
{
	for (int i=(maxLength-1)/2; i&gt;=0; i--)
	{
		siftDown(i);
	}
}

template&lt;class Key, class Elem,  class KEComp, class EEComp&gt;
bool Heap&lt;Key, Elem, KEComp, EEComp&gt;::EEcompare(Elem e1, Elem e2)
{
	if (!reversed)
	{
		return EEComp::before(e1, e2);
	}
	else
	{
		return EEComp::after(e1, e2);
	}
}



template&lt;class Key, class Elem,  class KEComp, class EEComp&gt;
void Heap&lt;Key, Elem, KEComp, EEComp&gt;::display()
{
	for (int i=0; i&lt;curLength; i++)
	{
		cout&lt;&lt;array[i]&lt;&lt;&quot; &quot;;
	}
	cout&lt;&lt;endl;
}

template&lt;class Key, class Elem,  class KEComp, class EEComp&gt;
void Heap&lt;Key, Elem, KEComp, EEComp&gt;::siftUp(int index)
{
	int p;
	if (index&gt;0)
	{
		p=parent(index);
		//swap only if son is &quot;before&quot; parent
		if (EEcompare(array[index], array[p]))
		{
			swap(array, index, p);
			siftUp(p);
		}
	}
}


template&lt;class Key, class Elem,  class KEComp, class EEComp&gt;
void Heap&lt;Key, Elem, KEComp, EEComp&gt;::siftDown(int index)
{
	int l, r, result;
	l=left(index);
	r=right(index);

	if (l&lt;curLength)//index is not a leaf
	{
		result=l;
		if (r&lt;curLength)//if right is valid
		{
			//swap index only if right is &quot;before&quot; left
			if (EEcompare(array[r], array[l]))//if right is before left
			{
				result = r;
			}
		}
		//
		if (EEcompare(array[result], array[index]))//compare the &quot;bigger&quot; with parent
		{
			swap(array, result, index);
			siftDown(result);
		}
		//if not, simply end here
	}
}


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

using namespace std;


class intComp
{
public:
	static bool before(int i, int j) { return i&gt;j;} 
	static bool same(int i, int j) { return i==j;}
	static bool after(int i, int j) { return i&lt;j;}
};

int main()
{
	const int Length=20;
	int current, mid=0, leftSize=0, rightSize=0, hold;
	int myArray[Length];
	int leftArray[Length];//try to waste some memory
	int rightArray[Length];

	Heap&lt;int, int, intComp, intComp&gt; H(myArray, Length);

	srand(time(0));

	for (int i=0; i&lt;Length; i++)
	{
		myArray[i]=rand()%100+1;//1--100
		cout&lt;&lt;myArray[i]&lt;&lt;&quot;  &quot;;
	}


	cout&lt;&lt;endl;
	H.buildHeap();
	H.display();
	cout&lt;&lt;endl;
	
	Heap&lt;int, int, intComp, intComp&gt; left(leftArray, 0);

	Heap&lt;int, int, intComp, intComp&gt; right(rightArray, 0);
	//left is by default the max heap
	left.setDirection(false);
	//right is min heap
	right.setDirection(true);

	mid=myArray[0];
	

	for (i=1; i&lt;Length; i++)
	{
		current=myArray[i];
		if (current&lt;mid)
		{
			left.insert(current);
			leftSize++;
		}
		else
		{
			right.insert(current);
			rightSize++;
		}
		if (leftSize-rightSize&gt;1)
		{
			left.removeHead(hold);
			right.insert(mid);
			mid=hold;
			leftSize--;
			rightSize++;
		}
		else
		{
			if (leftSize-rightSize&lt;-1)
			{
				right.removeHead(hold);
				left.insert(mid);
				mid=hold;
				leftSize++;
				rightSize--;
			}
		}
	}

	cout&lt;&lt;&quot;the mid is:&quot;&lt;&lt;mid&lt;&lt;endl;
	cout&lt;&lt;&quot;the left is:&quot;&lt;&lt;endl;
	left.display();
	cout&lt;&lt;&quot;the right is:&quot;&lt;&lt;endl;
	right.display();
	cout&lt;&lt;endl;


	return 0;
}
</pre>
<pre><font color="#0000FF"><b>Here is the result:<span lang="en-ca"> In order for a better view, I &quot;sorted&quot; the heap a bit and increased the chance of &quot;shifting&quot;. </span></b></font><span lang="en-ca"><font color="#0000FF"><b> </b></font></span></pre>

<pre>65 21 79 82 68 10 83 40 51 25 54 73 16 99 13 93 91 43 96 75
99 96 83 93 75 73 79 91 82 68 54 10 16 65 13 40 21 43 51 25

the mid is:68
the left is:
65 54 16 43 51 10 13 21 40 25
the right is:
73 75 82 79 93 96 83 99 91

Press any key to continue</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>