<?xml version="1.0" encoding="UTF-8"?>
<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/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kerry D. Wong &#187; Algorithm</title>
	<atom:link href="http://www.kerrywong.com/tag/algorithm/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kerrywong.com</link>
	<description></description>
	<lastBuildDate>Fri, 03 Sep 2010 00:51:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Image Blur Detection via Hough Transform &#8212; IV</title>
		<link>http://www.kerrywong.com/2009/07/03/image-blur-detection-via-hough-transform-iv/</link>
		<comments>http://www.kerrywong.com/2009/07/03/image-blur-detection-via-hough-transform-iv/#comments</comments>
		<pubDate>Sat, 04 Jul 2009 01:06:30 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Blur Detection]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Edge Detection]]></category>
		<category><![CDATA[Hough Transform]]></category>
		<category><![CDATA[Intel IPP]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1277</guid>
		<description><![CDATA[In my previous three articles (1,2,3) I discussed how to use Canny edge detection and Hough transform to identify blur images. Here I will show some results from the algorithm discussed before. Results When presented with images that are clear, the algorithm correctly identified most of them (see images below): The following images illustrate how [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous three articles (<a href="/2009/06/19/image-blur-detection-via-hough-transform-i/">1</a>,<a href="/2009/06/24/image-blur-detection-via-hough-transform-ii/">2</a>,<a href="/2009/06/27/image-blur-detection-via-hough-transform-iii/">3</a>) I discussed how to use Canny edge detection and Hough transform to identify blur images. Here I will show some results from the algorithm discussed before.<span id="more-1277"></span></p>
<h3>Results</h3>
<p>When presented with images that are clear, the algorithm correctly identified most of them (see images below):</p>
<table>
<tr>
<td>
<div id="attachment_1285" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c1.jpg" alt="Building (Microsoft Research Digital Image)" title="Building (Microsoft Research Digital Image)" width="320" height="240" class="size-full wp-image-1285" /></a><p class="wp-caption-text">Building (Microsoft Research Digital Image)</p></div>
</td>
<td>
<div id="attachment_1286" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c2.jpg" alt="Street (Microsoft Research Digital Image)" title="Street (Microsoft Research Digital Image)" width="320" height="240" class="size-full wp-image-1286" /></a><p class="wp-caption-text">Street (Microsoft Research Digital Image)</p></div>
</td>
</tr>
</table>
<table>
<tr>
<td>
<div id="attachment_1289" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c5.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c5.jpg" alt="Sky" title="Sky" width="320" height="240" class="size-full wp-image-1289" /></a><p class="wp-caption-text">Sky</p></div>
</td>
<td>
<div id="attachment_1288" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c4.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c4.jpg" alt="Flower" title="Flower" width="320" height="240" class="size-full wp-image-1288" /></a><p class="wp-caption-text">Flower</p></div>
</td>
</tr>
</table>
<p>The following images illustrate how the original image (top right) is divided into sub regions. Canny detection is performed on each of the sub images.</p>
<table>
<tr>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/1.jpg" alt="1" title="1" width="214" height="160" class="aligncenter size-full wp-image-1300" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/4.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/4.jpg" alt="4" title="4" width="214" height="160" class="aligncenter size-full wp-image-1303" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/7.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/7.jpg" alt="7" title="7" width="214" height="160" class="aligncenter size-full wp-image-1306" /></a>
</td>
</tr>
<tr>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/2.jpg" alt="2" title="2" width="214" height="160" class="aligncenter size-full wp-image-1301" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/5.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/5.jpg" alt="5" title="5" width="214" height="160" class="aligncenter size-full wp-image-1304" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/8.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/8.jpg" alt="8" title="8" width="214" height="160" class="aligncenter size-full wp-image-1307" /></a>
</td>
</tr>
<tr>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/3.jpg" alt="3" title="3" width="214" height="160" class="aligncenter size-full wp-image-1302" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/6.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/6.jpg" alt="6" title="6" width="214" height="160" class="aligncenter size-full wp-image-1305" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/9.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/9.jpg" alt="9" title="9" width="214" height="160" class="aligncenter size-full wp-image-1331" /></a>
</td>
</tr>
</table>
<p>When performing Hough Transform, I chose to detect up to ten lines in each image, with the following stepping parameter (the detection results are very sensitive to these parameters, the following parameters were chosen based on experiment results):<br />
\[\rho=1, \theta=0.01\]</p>
<p>Out of all the detected lines, a few sections are selected based on line continuity and the calculated average gradients around the detected lines. The following images shows the chosen Hough line segments based on the algorithm. </p>
<table>
<tr>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/1_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/1_o.jpg" alt="1_o" title="1_o" width="214" height="160" class="aligncenter size-full wp-image-1309" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/4_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/4_o.jpg" alt="4_o" title="4_o" width="214" height="160" class="aligncenter size-full wp-image-1312" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/7_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/7_o.jpg" alt="7_o" title="7_o" width="214" height="160" class="aligncenter size-full wp-image-1315" /></a>
</td>
</tr>
<tr>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/2_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/2_o.jpg" alt="2_o" title="2_o" width="214" height="160" class="aligncenter size-full wp-image-1310" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/5_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/5_o.jpg" alt="5_o" title="5_o" width="214" height="160" class="aligncenter size-full wp-image-1313" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/8_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/8_o.jpg" alt="8_o" title="8_o" width="214" height="160" class="aligncenter size-full wp-image-1316" /></a>
</td>
</tr>
<tr>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/3_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/3_o.jpg" alt="3_o" title="3_o" width="214" height="160" class="aligncenter size-full wp-image-1311" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/6_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/6_o.jpg" alt="6_o" title="6_o" width="214" height="160" class="aligncenter size-full wp-image-1314" /></a>
</td>
<td>
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/9_o.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/07/9_o.jpg" alt="9_o" title="9_o" width="214" height="160" class="aligncenter size-full wp-image-1317" /></a>
</td>
</tr>
</table>
<p>The table below shows the gradient index calculated within each area (the average of the gradients along all the chosen line segments within a sub-image. The result is scaled by 1000, the scale factor is chosen such that for clear images the resulted index is greater than 1 and for blur images the resulted index is less than 1).</p>
<table>
<tr>
<td>1</td>
<td>1.709</td>
</tr>
<tr>
<td>2</td>
<td>2.383</td>
</tr>
<tr>
<td>3</td>
<td>1.012</td>
</tr>
<tr>
<td>4</td>
<td>2.842</td>
</tr>
<tr>
<td>5</td>
<td>3.389</td>
</tr>
<tr>
<td>6</td>
<td>2.419</td>
</tr>
<tr>
<td>7</td>
<td>2.933</td>
</tr>
<tr>
<td>8</td>
<td>2.168</td>
</tr>
<tr>
<td>9</td>
<td>2.534</td>
</tr>
</table>
<p>And the sub images are indexed as follows:</p>
<table>
<tr>
<td>1</td>
<td>4</td>
<td>7</td>
</tr>
<tr>
<td>2</td>
<td>5</td>
<td>8</td>
</tr>
<tr>
<td>3</td>
<td>6</td>
<td>9</td>
</tr>
</table>
<p>The algorithm can also detect images with deliberate blur regions (e.g. <a href="http://en.wikipedia.org/wiki/Bokeh">Bokeh</a>). The results are illustrated below:</p>
<div id="attachment_1287" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/c3.jpg" alt="Plant (Microsoft Research Digital Image)" title="Plant (Microsoft Research Digital Image)" width="320" height="240" class="size-full wp-image-1287" /></a><p class="wp-caption-text">Plant (Microsoft Research Digital Image)</p></div>
<table>
<tr>
<td>1</td>
<td><font color="red">0.000</font></td>
</tr>
<tr>
<td>2</td>
<td>1.750</td>
</tr>
<tr>
<td>3</td>
<td>1.973</td>
</tr>
<tr>
<td>4</td>
<td>1.595</td>
</tr>
<tr>
<td>5</td>
<td>2.815</td>
</tr>
<tr>
<td>6</td>
<td>3.188</td>
</tr>
<tr>
<td>7</td>
<td><font color="red">0.000</font></td>
</tr>
<tr>
<td>8</td>
<td>1.204</td>
</tr>
<tr>
<td>9</td>
<td>1.308</td>
</tr>
</table>
<p>Note that the 0&#8242;s in the detection results indicate that within those regions, no lines could be reliably detected and thus those regions are considered blurred.<br />
Generally speaking, when an image contains both blurred and clear regions, some of the indexes will be zero and others will be greater than one.</p>
<p>The following images are detected as blurred, with the detected indexes far less than one.</p>
<table>
<tr>
<td>
<div id="attachment_1294" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/b3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/b3.jpg" alt="Boat (Microsoft Research Digital Image)" title="Boat (Microsoft Research Digital Image)" width="320" height="240" class="size-full wp-image-1294" /></a><p class="wp-caption-text">Boat (Microsoft Research Digital Image)</p></div>
</td>
<td>
<div id="attachment_1295" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/b4.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/b4.jpg" alt="Candle" title="Candle" width="320" height="427" class="size-full wp-image-1295" /></a><p class="wp-caption-text">Candle</p></div>
</td>
</tr>
</table>
<h3>Limitations</h3>
<p>when image contrast is low, or when objects borders are not clearly defined, the algorithm may have difficulty in distinguishing whether an image is blurred. Take the following two cloud images for instance, the image on the left was correctly classified as a clear image due to the relatively high contrast around the center. But the image to the right was classified as blurred due to its lack of contrast. </p>
<table>
<tr>
<td>
<div id="attachment_1291" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/b1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/b1.jpg" alt="Cloud" title="Cloud" width="320" height="240" class="size-full wp-image-1291" /></a><p class="wp-caption-text">Cloud</p></div>
</td>
<td>
<div id="attachment_1293" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/b2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/b2.jpg" alt="Cloud" title="Cloud" width="320" height="240" class="size-full wp-image-1293" /></a><p class="wp-caption-text">Cloud</p></div>
</td>
</tr>
</table>
<h3>Update (7/12/2010)</h3>
<p>A few readers requested the code for calculating gradients. The method I used was quite simple, please see the LineUtils code below:</p>
<pre class="brush: cpp;">
/*
 * File:   lineutils.cpp
 * Author: kwong
 *
 * Created on June 5, 2009, 8:47 PM
 */

#include &quot;LineUtils.h&quot;

#include &lt;math.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;iostream&gt;
#include &lt;ios&gt;

using namespace std;

namespace KDW {
    const float PI = 3.14159265358979;
    const float Epsilon = 1e-5;
    const float MaxGradient = 1e6;

    LineUtils::LineUtils() {
    }

    LineUtils::LineUtils(const LineUtils&amp; orig) {
    }

    LineUtils::~LineUtils() {
    }

    /**
     * Get the equation parameters for the line that passes through (x,y) and is perpendicular
     * to the line specified by parameters (p0, theta0) in normal form.
     *
     * @param p0 : distance to line from origin.
     * @param theta0 : the slope of p0.
     * @param x : x coordinate of the point where the perpendicular line passes through
     * @param y : y coordinate of the point where the perpendicular line passes through
     * @param &amp;p : the perpendicular line's distance from origin.
     * @param &amp;theta : the slope of p.
     **/
    void LineUtils::GetPerpendicularLineParameters(float p0, float theta0, float x, float y, float &amp;p, float &amp;theta) {
        float x0 = p0 * cos(theta0);
        float y0 = p0 * sin(theta0);

        p = sqrt((x0 - x)*(x0 - x) + (y0 - y)*(y0 - y));

        float a1 = theta0 - PI / 2.0;
        float a2 = theta0 + PI / 2.0;

        //d=|x0 * cos a + y0 * sin a - p|
        float d1 = abs(x * cos(a1) + y * sin(a1) - p);
        float d2 = abs(x * cos(a2) + y * sin(a2) - p);

        if (d1 &lt; d2)
            theta = a1;
        else
            theta = a2;
    }

    /**
     * Get a line segement's coordinates. The segement is centered at x0, y0.
     *
     * @param p : distance to line from origin.
     * @param theta : the slope of p.
     * @param x0 : x coordinate of the segement center.
     * @param y0 : y coordinate of the segement center.
     * @param numOfPoints : the number of coordinate points to collect at either side
     *                      of (x0, y0)
     * @param points[] : returns the x,y coordinates of the points on the line segement in IppiPoint.
     **/
    void LineUtils::GetLineIntervalPoints(float p, float theta, float x0, float y0, int numOfPoints, IppiPoint points[]) {
        if (abs(sin(theta)) &lt; Epsilon) {
            for (int xp = x0 - numOfPoints; xp &lt;= x0 + numOfPoints; xp++) {
                points[(int) (xp + numOfPoints - x0)].x = xp;
                points[(int) (xp + numOfPoints - x0)].y = y0;
            }
        } else if (abs(cos(theta)) &lt; Epsilon) {
            for (int yp = y0 - numOfPoints; yp &lt;= y0 + numOfPoints; yp++) {
                points[(int) (yp + numOfPoints - y0)].y = yp;
                points[(int) (yp + numOfPoints - y0)].x = x0;
            }
        } else if ((abs(theta) &gt; 0 &amp;&amp; abs(theta) &lt;= 0.25 * PI) ||
                (abs(theta) &gt; 0.75 * PI &amp;&amp; abs(theta) &lt;= PI) ||
                (theta &gt; PI &amp;&amp; theta &lt;= 1.25 * PI) ||
                (theta &gt; 1.75 * PI and theta &lt;= 2.0 * PI)) {
            for (int xp = x0 - numOfPoints; xp &lt;= x0 + numOfPoints; xp++) {
                points[(int) (xp + numOfPoints - x0)].x = xp;
                points[(int) (xp + numOfPoints - x0)].y = (int) ((p - points[(int) (xp + numOfPoints - x0)].x * cos(theta)) / sin(theta));
            }
        } else {
            for (int yp = y0 - numOfPoints; yp &lt;= y0 + numOfPoints; yp++) {
                points[(int) (yp + numOfPoints - y0)].y = yp;
                points[(int) (yp + numOfPoints - y0)].x = (p - points[(int) (yp + numOfPoints - y0)].y * sin(theta)) / cos(theta);
            }
        }
    }

    /**
     * Get a line segement's coordinates. The segement is centered at x0, y0.
     *
     * @param points[] : the x,y coordinate of the input points (ordered).
     * @param threashold : the threashold of disconnected points before a line is considered no
     *              longer connected.
     * @param lpoints[] : the x,y coordinates of the points in the detected longest connected line.
     * @param &amp;maxLen : the maximum length of the output array, addtional line points
     *                  will be discarded if exceed this limit.
     **/
    void LineUtils::GetLongestConnectedLinePoints(IppiPoint points[], int len, int threshold, IppiPoint lpoints[], int &amp;maxLen) {
        int maxIndexEnd = 0, curRunLength = 0, maxRunLength = 0;

        lpoints[curRunLength] = points[0];

        for (int i = 1; i &lt; len; i++) {
            //if ((abs(points[i].x - points[i - 1].x) &gt; threshold) || (abs(points[i].y - points[i - 1].y) &gt; threshold)) {
            if ((abs(points[i].x - lpoints[curRunLength].x) &gt; threshold) || (abs(points[i].y - lpoints[curRunLength].y) &gt; threshold)) {
                //if (curRunLength &gt; maxRunLength) {
                if (curRunLength &gt; maxRunLength) {
                    maxRunLength = curRunLength;
                    maxIndexEnd = i;
                }
                curRunLength = 0;
                lpoints[curRunLength] = points[i];

                //}
            } else {
                if (curRunLength &gt;= maxLen) {
                    maxRunLength = maxLen;
                    break;
                }

                curRunLength++;
                lpoints[curRunLength] = points[i];
            }
        }

        for (int i = maxIndexEnd - maxRunLength - 1; i &lt; maxIndexEnd; i++) {
            if (i - (maxIndexEnd - maxRunLength) - 1 &lt; maxRunLength) {
                lpoints[i - (maxIndexEnd - maxRunLength - 1)] = points[i];
            }
        }

        maxLen = maxRunLength;
    }

    bool LineUtils::GetMinMaxIndicies(float pixels[], int len, int &amp;minIndex, int &amp;maxIndex) {
        bool isEdge = false;
        bool isPositive = true;

        int numCrossings = 0;

        minIndex = 0;
        maxIndex = 0;

        float avg = 0;

        for (int i = 0; i &lt; len; i++) {
            avg += pixels[i];
        }

        avg = avg / (float) len;        

        if (pixels[0] &gt; avg)
            isPositive = true;
        else
            isPositive = false;

        for (int i = 0; i &lt; len; i++) {
            if (pixels[i] &lt; pixels[minIndex]) {
                minIndex = i;
            } else if (pixels[i] &gt; pixels[maxIndex]) {
                maxIndex = i;
            }

            if (isPositive &amp;&amp; pixels[i] &lt; avg) {
                isPositive = false;
                numCrossings++;
            } else if (!isPositive &amp;&amp; pixels[i] &gt; avg) {
                isPositive = true;
                numCrossings++;
            }
        }

        if (numCrossings &lt; 3)
            return true;
        else
            return false;
    }

    float LineUtils::CalculateGradient(IppiPoint points[], float pixels[], int len, int minIndex, int maxIndex) {
        float lAvg = 0;
        float hAvg = 0;

        if (minIndex &gt; 0 &amp;&amp; minIndex &lt; len - 1) {
            lAvg = (pixels[minIndex] + pixels[minIndex - 1] + pixels[minIndex + 1]) / 3.0;
        } else if (minIndex &gt; 1) {
            lAvg = (pixels[minIndex] + pixels[minIndex - 1] + pixels[minIndex - 2]) / 3.0;
        } else if (minIndex &lt; len - 2) {
            lAvg = (pixels[minIndex] + pixels[minIndex + 1] + pixels[minIndex + 2]) / 3.0;
        } else {
            lAvg = pixels[minIndex];
        }

        if (maxIndex &gt; 0 &amp;&amp; maxIndex &lt; len - 1) {
            hAvg = (pixels[maxIndex] + pixels[maxIndex - 1] + pixels[maxIndex + 1]) / 3.0;
        } else if (maxIndex &gt; 1) {
            hAvg = (pixels[maxIndex] + pixels[maxIndex - 1] + pixels[maxIndex - 2]) / 3.0;
        } else if (maxIndex &lt; len - 2) {
            hAvg = (pixels[maxIndex] + pixels[maxIndex + 1] + pixels[maxIndex + 2]) / 3.0;
        } else {
            hAvg = pixels[maxIndex];
        }

        float h = hAvg - lAvg;
        float t = abs(h / (float) (points[maxIndex].x - points[minIndex].x));

        if (t &gt; 0)
            return t &gt; MaxGradient ? MaxGradient : t;
        else
            return MaxGradient;
    }

    float LineUtils::GetAverage(float gradients[], int count) {
        int zerosCount = 0;
        int minValIndex = 0, maxValIndex = 0;

        for (int i = 0; i &lt; count; i++) {
            if (gradients[i] == 0)
                zerosCount++;

            if (gradients[i] &gt; gradients[maxValIndex])
                maxValIndex = i;
            else if (gradients[i] &lt; gradients[minValIndex])
                minValIndex = i;
        }

        gradients[minValIndex] = 0;
        gradients[maxValIndex] = 0;

        zerosCount += 2;

        if (zerosCount &lt; 6) {
            for (int i = 0; i &lt; count; i++) {
                if (gradients[i] &gt; gradients[maxValIndex])
                    maxValIndex = i;
                else if (gradients[i] &lt; gradients[minValIndex])
                    minValIndex = i;
            }
        }

        gradients[minValIndex] = 0;
        gradients[maxValIndex] = 0;

        zerosCount += 2;

        if (zerosCount &lt; 6) {
            for (int i = 0; i &lt; count; i++) {
                if (gradients[i] &gt; gradients[maxValIndex])
                    maxValIndex = i;
                else if (gradients[i] &lt; gradients[minValIndex])
                    minValIndex = i;
            }
        }

        gradients[minValIndex] = 0;
        gradients[maxValIndex] = 0;

        float r = 0;
        zerosCount = 0;
        for (int i = 0; i &lt; count; i++) {
            if (gradients[i] &gt; 0) {
                r += gradients[i];
                zerosCount++;
            }
        }

        if (zerosCount == 0)
            return 0;
        else
            return r / (float) zerosCount;
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/07/03/image-blur-detection-via-hough-transform-iv/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Image Blur Detection via Hough Transform &#8212; III</title>
		<link>http://www.kerrywong.com/2009/06/27/image-blur-detection-via-hough-transform-iii/</link>
		<comments>http://www.kerrywong.com/2009/06/27/image-blur-detection-via-hough-transform-iii/#comments</comments>
		<pubDate>Sun, 28 Jun 2009 01:31:01 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Blur Detection]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Edge Detection]]></category>
		<category><![CDATA[Hough Transform]]></category>
		<category><![CDATA[Intel IPP]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1231</guid>
		<description><![CDATA[I will continue where I left off in my previous post. After performing Hough transform, and extracted the longest sections of lines for each corresponding Hough line detected, we will need to calculate the gradients of the image pixels luminance around the line sections. Gradient Calculation If you remember how the Hough parameters were determined [...]]]></description>
			<content:encoded><![CDATA[<p>I will continue where I left off in my <a href="/2009/06/24/image-blur-detection-via-hough-transform-ii/">previous post</a>. After performing Hough transform, and extracted the longest sections of lines for each corresponding Hough line detected, we will need to calculate the gradients of the image pixels luminance around the line sections.<span id="more-1231"></span></p>
<h3>Gradient Calculation</h3>
<p>If you remember how the Hough parameters were determined (in polar form, see figure below), it is not difficult to obtain the pixel coordinates centered around the points on the detected line. </p>
<div id="attachment_1214" class="wp-caption aligncenter" style="width: 554px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/polar.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/polar.png" alt="Region selection for gradient calculation" title="Region selection for gradient calculation" width="544" height="410" class="size-full wp-image-1214" /></a><p class="wp-caption-text">Region selection for gradient calculation</p></div>
<p>In fact, we can formulate a line that is perpendicular to the line section detected during Hough transform, and use the line section that is within a predefined region (e.g. the between the dotted lines) to calculate the gradients of luminance. The following code snippet shows how the perpendicular line&#8217;s parameters are obtained.</p>
<pre class="brush: cpp;">
    /**
     * Get the equation parameters for the line that passes through (x,y) and is perpendicular
     * to the line specified by parameters (p0, theta0) in normal form.
     *
     * @param p0 : distance to line from origin.
     * @param theta0 : the slope of p0.
     * @param x : x coordinate of the point where the perpendicular line passes through
     * @param y : y coordinate of the point where the perpendicular line passes through
     * @param &amp;p : the perpendicular line's distance from origin.
     * @param &amp;theta : the slope of p.
     **/
    void LineUtils::GetPerpendicularLineParameters(float p0, float theta0, float x, float y, float &amp;p, float &amp;theta) {
        float x0 = p0 * cos(theta0);
        float y0 = p0 * sin(theta0);

        p = sqrt((x0 - x)*(x0 - x) + (y0 - y)*(y0 - y));

        float a1 = theta0 - PI / 2.0;
        float a2 = theta0 + PI / 2.0;

        //d=|x0 * cos a + y0 * sin a - p|
        float d1 = abs(x * cos(a1) + y * sin(a1) - p);
        float d2 = abs(x * cos(a2) + y * sin(a2) - p);

        if (d1 &lt; d2)
            theta = a1;
        else
            theta = a2;
    }
</pre>
<p>In an ideal situation, the gradient of the line points obtained via the method above looks like the figures below, where the edges are clearly identified. </p>
<div id="attachment_1254" class="wp-caption aligncenter" style="width: 570px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/edge1.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/edge1.png" alt="Edge (dark to bright)" title="Edge (dark to bright)" width="560" height="420" class="size-full wp-image-1254" /></a><p class="wp-caption-text">Edge (dark to bright)</p></div>
<div id="attachment_1255" class="wp-caption aligncenter" style="width: 570px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/edge2.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/edge2.png" alt="Edge (dark to bright to dark)" title="Edge (dark to bright to dark)" width="560" height="420" class="size-full wp-image-1255" /></a><p class="wp-caption-text">Edge (dark to bright to dark)</p></div>
<p>Sometimes, when the lighting condition is poor, the image would appear to be &#8220;grainy&#8221;, which sometimes led to poor line detection. For instance, the following figure shows the the gradient when the region around the detected edge is grainy:</p>
<div id="attachment_1258" class="wp-caption aligncenter" style="width: 570px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/noneedge.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/noneedge.png" alt="None-Edge" title="None-Edge" width="560" height="420" class="size-full wp-image-1258" /></a><p class="wp-caption-text">None-Edge</p></div>
<p>We use the number of times the luminance increases above or decreases below its mean along the perpendicular line interval as a measure of whether we accept the detection results as gradients or not. Typically when such number of crossings is less than 3 (see the first two images above) the curve is either monotonic or has a single peak, we assume that gradients can be correctly calculated and if the crossings are more than 3 we discard the results. The gradient is calculated as the slope of the curve. In the examples above, we used ten pixels on each side of the Hough line to calculate gradients.</p>
<h3>Image Regions</h3>
<p>For images with complex contents, it becomes difficult for the Hough transform to reliably identify line structures within the image. Future more, certain photography techniques (i.e. <a href="http://en.wikipedia.org/wiki/Bokeh">Bokeh</a>) leave portions of images deliberately blurred. Without dividing image into different sub-regions, the classification results would be compromised.</p>
<p>Thus, images are divided into 9 (3&#215;3) sub-images after Canny edge detection, and Hough transform is performed against each sub-images. The figure below illustrates how an image is divided:<br />
<div id="attachment_1267" class="wp-caption aligncenter" style="width: 654px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/3x3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/3x3.jpg" alt="Image divided into 3x3 sub-images (Microsoft Research Digital Image)" title="Image divided into 3x3 sub-images (Microsoft Research Digital Image)" width="644" height="482" class="size-full wp-image-1267" /></a><p class="wp-caption-text">Image divided into 3x3 sub-images (Microsoft Research Digital Image)</p></div></p>
<p>This technique is especially useful when portions of images are deliberately blurred, like the image shown above. It also helps the line detection accuracy when the image contains complex scenes. By dividing up the image, each sub area&#8217;s complexity is greatly reduced. Other methods in scene separation might achieve even better results, but it is out of the scope for our discussion here.</p>
<p>In my next post, I will show some results obtained from using the method mentioned in this and the previous articles and will also discuss its limitations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/06/27/image-blur-detection-via-hough-transform-iii/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Image Blur Detection via Hough Transform &#8212; II</title>
		<link>http://www.kerrywong.com/2009/06/24/image-blur-detection-via-hough-transform-ii/</link>
		<comments>http://www.kerrywong.com/2009/06/24/image-blur-detection-via-hough-transform-ii/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 01:44:44 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Blur Detection]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Edge Detection]]></category>
		<category><![CDATA[Hough Transform]]></category>
		<category><![CDATA[Intel IPP]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1194</guid>
		<description><![CDATA[In my previous post, I briefly discussed the rationale behind automated blur detection in digital imagery and did an overview of an algorithm that could be used to detect blur images. Here I will show some implementation details along with some C++ code snippets. Experience tells us that blur images tend to contain less details [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="/2009/06/19/image-blur-detection-via-hough-transform-i/">my previous post</a>, I briefly discussed the rationale behind automated blur detection in digital imagery and did an overview of an algorithm that could be used to detect blur images. Here I will show some implementation details along with some C++ code snippets.<span id="more-1194"></span></p>
<p>Experience tells us that blur images tend to contain less details then their sharper counterparts. And the areas where <a href="http://en.wikipedia.org/wiki/Intensity">intensity</a> transitions occur (e.g. the border of an object) are more well defined in clear images. Mathematically speaking, the <a href="http://en.wikipedia.org/wiki/Slope">slope</a> of the intensity transition is statistically deeper in clear images than blur ones. Since whether an image is blurred or not is not affected by color space, it is sufficient to perform detection in the <a href="http://en.wikipedia.org/wiki/Luminance">luminance</a> space (i.e. gray scale images):</p>
<p>\[I=0.299R\times0.587G\times0.114B\]</p>
<h3>Canny Edge Detection</h3>
<p>Thus the very first step in deciding whether an image or an area within an image is blurred is to use some sort of edge detection algorithms to obtain a collection of the edges in the image.</p>
<p><a href="http://en.wikipedia.org/wiki/Canny_edge_detector">Canny edge detection</a> is a good candidate since it is optimal in terms of good detection and localization. And hysteresis is used to reduce streaking and thus Canny edge detection achieves relatively continuous edge boundaries comparing to other edge detection methods.</p>
<p>In <a href="/2009/05/07/canny-edge-detection-auto-thresholding/">one of my previous posts</a>, I discussed Canny edge detection using auto thresholding utilizing Intel&#8217;s <a href="http://software.intel.com/en-us/intel-ipp/">Integrated Performance Primitives</a> (IPP). I used the same algorithm here for the image pre-processing process.</p>
<h3>Hough Transform</h3>
<p>In order to analyze the gradients along detected edges, it is necessary to first parameterize them. <a href="http://en.wikipedia.org/wiki/Hough_transform">Hough transform</a> comes in handy for this task. </p>
<p>While Hough transform is capable of identifying arbitrary shapes, for the purpose of detecting image blurs simple line detection is more robust. Besides, IPP has an implementation for line detection using Hough transform out of the box.</p>
<p>Since our goal is to determine the quality of the image within a region of interest, we do not need to analyze all the edges identified within that region. But rather, we could select a few based on some pre-determined criteria that would maximize our ability to correctly determine the luminance gradients.</p>
<p>The following code snippet shows my implementation of the edge parameterization method using IPP:</p>
<pre class="brush: cpp;">
    bool CompareIppiPoint(IppiPoint &amp;p1, IppiPoint &amp;p2) {
        if (p1.x == p2.x) {
            return p1.y &lt; p2.y;
        } else {
            return p1.x &lt; p2.x;
        }
    }

    void IPPGrayImage::HoughLine(IppPointPolar delta, int threshold, int maxLineCount, int* pLineCount, IppPointPolar pLines[], list&lt;IppiPoint&gt; pList[]) {
        IppStatus sts;
        IppiSize roiSize = {_width, _height};

        int bufSize;
        sts = ippiHoughLineGetSize_8u_C1R(roiSize, delta, maxLineCount, &amp;bufSize);
        assert(sts == ippStsNoErr);
        Ipp8u * pBuf = ippsMalloc_8u(bufSize);

        Ipp8u *imgBuf;
        int stepSize;
        imgBuf = ippiMalloc_8u_C1(_width, _height, &amp;stepSize);

        sts = ippiConvert_32f8u_C1R(_imgBuffer, _width * PIXEL_SIZE, imgBuf, _width, roiSize, ippRndNear);
        assert(sts == ippStsNoErr);
        assert(imgBuf != NULL);

        sts = ippiHoughLine_8u32f_C1R(imgBuf, _width, roiSize, delta, threshold, pLines, maxLineCount, pLineCount, pBuf);
        assert(sts == ippStsNoErr);

        //d=|x0 * cos a + y0 * sin a - p|
        int val = 0;
        float d;
        for (int x = 0; x &lt; _width; x++) {
            for (int y = 0; y &lt; _height; y++) {
                if (imgBuf[x + y * _width] &gt; 0) {
                    val = imgBuf[x + y * _width];

                    for (int i = 0; i &lt; *pLineCount; i++) {
                        d = abs((float) cos(pLines[i].theta) * (float) x + (float) sin(pLines[i].theta) * (float) y - abs(pLines[i].rho));
                        if (d &lt; threshold) {
                            IppiPoint p;
                            p.x = x;
                            p.y = y;

                            pList[i].push_back(p);
                        }
                    }
                }
            }
        }

        for (int i = 0; i &lt; *pLineCount; i++) {
            pList[i].sort(CompareIppiPoint);
        }

        ippsFree(pBuf);
        ippiFree(imgBuf);
    }
</pre>
<p>Note that the selection for <em>delta</em> is crucial for the line detection quality. In the code above, up to <em>maxLineCount</em> number of lines are detected and each line&#8217;s parameters are stored in <em>pLines[]</em>. The edge image pixel coordinates within a given range that is less than <em>threshold</em> are collected into the list. Because the Hough detection does not indicate the begin and the end point of a line, we need to iterate through the pixels in <em>pList[]</em> and find the sections that the detected lines pass through. The image below illustrates how the edge regions are chosen based on detected line parameters. Image features within a region between the dotted line are recorded based on the distances to the line defined by:<br />
\[d=\vert x_0cos\alpha+y_0sin\alpha-p\vert\]</p>
<div id="attachment_1214" class="wp-caption aligncenter" style="width: 554px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/polar.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/06/polar.png" alt="Region selection for gradient calculation" title="Region selection for gradient calculation" width="544" height="410" class="size-full wp-image-1214" /></a><p class="wp-caption-text">Region selection for gradient calculation</p></div>
<p>In practice, for each parameterized line I chose to select the longest section where the line approximates a section of the edge. Other line sections can be used as well, but the longest portion tends to offer better classification results. The code is shown below, and the thickened section in the figure above illustrates the selected section.</p>
<pre class="brush: cpp;">
    void LineUtils::GetLongestConnectedLinePoints(IppiPoint points[], int len, int threshold, IppiPoint lpoints[], int &amp;maxLen) {
        int maxIndexEnd = 0, curRunLength = 0, maxRunLength = 0;

        lpoints[curRunLength] = points[0];

        for (int i = 1; i &lt; len; i++) {
            if ((abs(points[i].x - lpoints[curRunLength].x) &gt; threshold) || (abs(points[i].y - lpoints[curRunLength].y) &gt; threshold)) {
                if (curRunLength &gt; maxRunLength) {
                    maxRunLength = curRunLength;
                    maxIndexEnd = i;
                }
                curRunLength = 0;
                lpoints[curRunLength] = points[i];
            } else {
                if (curRunLength &gt;= maxLen) {
                    maxRunLength = maxLen;
                    break;
                }

                curRunLength++;
                lpoints[curRunLength] = points[i];
            }
        }

        for (int i = maxIndexEnd - maxRunLength - 1; i &lt; maxIndexEnd; i++) {
            if (i - (maxIndexEnd - maxRunLength) - 1 &lt; maxRunLength) {
                lpoints[i - (maxIndexEnd - maxRunLength - 1)] = points[i];
            }
        }

        maxLen = maxRunLength;
    }
</pre>
<p>In my next post, I will continue with the gradient calculation and some methods to enhance the detection accuracies.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/06/24/image-blur-detection-via-hough-transform-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Image Blur Detection via Hough Transform &#8212; I</title>
		<link>http://www.kerrywong.com/2009/06/19/image-blur-detection-via-hough-transform-i/</link>
		<comments>http://www.kerrywong.com/2009/06/19/image-blur-detection-via-hough-transform-i/#comments</comments>
		<pubDate>Sat, 20 Jun 2009 02:41:13 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Blur Detection]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Edge Detection]]></category>
		<category><![CDATA[Hough Transform]]></category>
		<category><![CDATA[Intel IPP]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1172</guid>
		<description><![CDATA[It is often necessary to identify and classify images based on their clarities. For instance, it is desirable for an automated process to locate blurred images within a large digitized image library and then automatically sharpen the blurred images via inverse filtering or blind deconvolution. In the following series of articles, I will discuss a [...]]]></description>
			<content:encoded><![CDATA[<p>It is often necessary to identify and classify images based on their clarities. For instance, it is desirable for an automated process to locate blurred images within a large digitized image library and then automatically sharpen the blurred images via inverse filtering or blind deconvolution. In the following series of articles, I will discuss a practical method in detecting blur images using <a href="http://en.wikipedia.org/wiki/Hough_transform">Hough Transform</a>.<span id="more-1172"></span></p>
<h3>Background</h3>
<p>Image blur is typically caused by</p>
<ul>
<li>Motion (e.g. the relative movement between the camera and the object during exposure)</li>
<li>Out-of-focus</li>
<li>Low lighting condition</li>
</ul>
<p>Other types of image blur may also occur in photography (such as <a href="http://en.wikipedia.org/wiki/Bokeh">Bokeh</a>). And it is desirable to be able to automatically distinguish desired image blur (e.g. Bokeh caused by camera lens with a shallow depth of field) from un-intended blur (e.g. out of focus).</p>
<p>When reference images (e.g. a series of images with different focus settings) are present, detecting image blur is a relatively simple task. For instance, in passive auto-focus cameras, a series of scene images are captured with progressive focus settings. And the intensity differences are calculated within the same region across these different images. Thus, the image with the highest intensity difference corresponds to the correct focus setting. In Active-focus cameras, image blur detection problem is circumvented by measuring the distance between the lens and the object.</p>
<p>The problem becomes more difficult if we are only given a single image. Since many parameters that we used above in camera auto-focusing are not present in a single image setting, we could not reliably infer image sharpness by the method used in passive auto-focusing as we do not have sufficient knowledge to re-construct the series of images necessary for comparison.</p>
<p>We can however, tell whether an image is in-focus by calculating the intensity differences along the edges in an image. If the calculated intensity is higher than a predefined threshold, we deduce that the image is sharp. And if the calculated intensity is lower than a predefined threshold, we conclude that the image is blurred. So now we shifted the problem to identifying such optimal regions where the intensities are calculated.</p>
<h3>Algorithm Overview</h3>
<p>In this algorithm, we first use <a href="http://en.wikipedia.org/wiki/Canny_edge_detector">Canny edge detection</a> to obtain the edges in the image. The edges are then parameterized using Hough transform. We then calculate the pixel gradients along the parameterized lines detected and finally we use the gradients to decide whether the image is blurred.</p>
<p>I will discuss some technical and implementation details in the up-coming posts. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/06/19/image-blur-detection-via-hough-transform-i/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Canny Edge Detection Auto Thresholding</title>
		<link>http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/</link>
		<comments>http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/#comments</comments>
		<pubDate>Fri, 08 May 2009 02:15:41 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Image Processing]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=999</guid>
		<description><![CDATA[In the example I gave in &#8220;Interfacing IPP with Magick++&#8220;, I illustrated how to use Intel’s Integrated Performance Primitives (IPP) to perform edge detection. One issue with Canny edge detection algorithm is that we need to specify a high threshold and a low threshold. How to select those threshold values affect the quality of the [...]]]></description>
			<content:encoded><![CDATA[<p>In the example I gave in &#8220;<a href="/2009/03/17/interfacing-ipp-with-magick/">Interfacing IPP with Magick++</a>&#8220;, I illustrated how to use <a href="http://software.intel.com/en-us/intel-ipp/">Intel’s Integrated Performance Primitives (IPP)</a> to perform edge detection. One issue with <a href="http://en.wikipedia.org/wiki/Canny_edge_detector">Canny edge detection</a> algorithm is that we need to specify a high threshold and a low threshold. How to select those threshold values affect the quality of the detected edge greatly. And in my previous example, the threshold values were chosen manually. In this blog post, I will examine a couple of simple methods that can be used to automatically determine the threshold values.<span id="more-999"></span></p>
<p>The simplest way is to use the mean value of the gray scale image pixel values. As a rule of thumb, we set the low threshold to 0.66*[mean value] and set the high threshold to 1.33*[mean value]. Another way is to use the median color in the gray scale image and uses 0.66*[median value] and 1.33*[median value] accordingly. For typical images, these two methods achieve comparable results.</p>
<p>For example, the following shows the picture of a building along with its histogram (original image from <a href="ftp://ftp.research.microsoft.com/pub/download/orid">Microsoft Research Digital Image</a>. Please see <a href="http://research.microsoft.com/en-us/um/people/antcrim/data_objrec/msr%20cambridge%20eula%20for%20digital%20images_download.rtf">Microsoft Research Digital Image License Agreement</a> for more information):</p>
<table>
<tr>
<td>
<div id="attachment_1011" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_gray.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_gray.jpg" alt="Building" title="Building" width="320" height="240" class="size-full wp-image-1011" /></a><p class="wp-caption-text">Building</p></div>
</td>
<td>
<div id="attachment_1012" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_hist.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_hist.png" alt="Building Histogram" title="Building Histogram" width="320" height="240" class="size-full wp-image-1012" /></a><p class="wp-caption-text">Building Histogram</p></div>
</td>
</tr>
</table>
<p>The following shows the edge detection results using Canny algorithm (left image uses mean value auto-thresholding, right image uses median value auto-thresholding) and the results exhibit very little visible differences. </p>
<table>
<tr>
<td>
<div id="attachment_1006" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_canny_mean.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_canny_mean.jpg" alt="Building (Canny Mean)" title="Building (Canny Mean)" width="320" height="240" class="size-full wp-image-1006" /></a><p class="wp-caption-text">Building (Canny Mean)</p></div>
</td>
<td>
<div id="attachment_1007" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_canny_median.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_canny_median.jpg" alt="Building (Canny Median)" title="Building (Canny Median)" width="320" height="240" class="size-full wp-image-1007" /></a><p class="wp-caption-text">Building (Canny Median)</p></div>
</td>
</tr>
</table>
<p>However, for images has non-equalized histogram (see the picture of cloud and its histogram below): </p>
<table>
<tr>
<td>
<div id="attachment_1018" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_gray.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_gray.jpg" alt="Cloud" title="Cloud" width="240" height="320" class="size-full wp-image-1018" /></a><p class="wp-caption-text">Cloud</p></div>
</td>
<td>
<div id="attachment_1019" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_hist.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_hist.png" alt="Cloud Histogram" title="Cloud Histogram" width="320" height="240" class="size-full wp-image-1019" /></a><p class="wp-caption-text">Cloud Histogram</p></div>
</td>
</tr>
</table>
<p>Canny Edge detection result based on mean value auto-thresholding is pretty poor (see image on the left below), while edge detection based on median value auto-thresholding achieved much better result (see image on the right below)</p>
<table>
<tr>
<td>
<div id="attachment_1021" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_canny_mean.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_canny_mean.jpg" alt="Cloud (Canny Mean)" title="Cloud (Canny Mean)" width="240" height="320" class="size-full wp-image-1021" /></a><p class="wp-caption-text">Cloud (Canny Mean)</p></div>
</td>
<td>
<div id="attachment_1024" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_median.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_median.jpg" alt="Cloud (Canny Median)" title="Cloud (Canny Median)" width="240" height="320" class="size-full wp-image-1024" /></a><p class="wp-caption-text">Cloud (Canny Median)</p></div>
</td>
</tr>
</table>
<p>Alternatively, we could have performed histogram equalization on the image first before applying Canny edge detection with mean auto-thresholding:</p>
<table>
<tr>
<td>
<div id="attachment_1026" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq.png" alt="Cloud Equalized" title="Cloud Equalized" width="240" height="320" class="size-full wp-image-1026" /></a><p class="wp-caption-text">Cloud Equalized</p></div>
</td>
<td>
<div id="attachment_1028" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_hist_eq.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_hist_eq.png" alt="Cloud Equalized Histogram" title="Cloud Equalized Histogram" width="320" height="240" class="size-full wp-image-1028" /></a><p class="wp-caption-text">Cloud Equalized Histogram</p></div>
</td>
</tr>
</table>
<p>And after image equalization, both mean and median value auto-thresholding achieved similar results.</p>
<table>
<tr>
<td>
<div id="attachment_1030" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_mean.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_mean.jpg" alt="Cloud Equalized (Canny Mean)" title="Cloud Equalized (Canny Mean)" width="240" height="320" class="size-full wp-image-1030" /></a><p class="wp-caption-text">Cloud Equalized (Canny Mean)</p></div>
</td>
<td>
<div id="attachment_1031" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_median.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_median.jpg" alt="Cloud Equalized (Canny Median)" title="Cloud Equalized (Canny Median)" width="240" height="320" class="size-full wp-image-1030" /></a><p class="wp-caption-text">Cloud Equalized (Canny Median)</p></div>
</td>
</tr>
</table>
<p>So the Canny edge detection using median value auto-thresholding seems to adapt to different types of images very well (note selecting the median value selection can be thought as equalizing the histogram, except that the pixel values are not changed during such operation).</p>
<p>The following is the code listing for the histogram calculation using IPP (based on the <a href="/2009/04/10/an-image-class-based-on-ipp/">image class I created earlier</a>)</p>
<pre class="brush: cpp;">
/** @brief Get the min max mean value statistics for the current image
 *   @param min, max, mean: these are output parameters that are passed
 *         back by reference.
 */
void IPPGrayImage::MinMaxMean(float&amp; min, float&amp; max, double&amp; mean)
{
    IppStatus sts;
    IppiSize origImgSize = {_width, _height};

    sts = ippiMinMax_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, &amp;min, &amp;max);
    assert(sts == ippStsNoErr);
    sts = ippiMean_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, &amp;mean, ippAlgHintFast);
    assert(sts == ippStsNoErr);
}

/** @brief Calculate the histogram of the image
 *   @param nLevel: the number of bins in the histogram
 *        levels: this is the optional levels user can pass in (histogram will be then
 *                calculated with these levels instead of the uniform levels by default.
 *   @return an integer array which contains the histogram.
 *   @note the histogram is by default calculated using uniform bins across the color range.
 */
unsigned int * IPPGrayImage::GetHistogram(unsigned int nLevel, float levels[])
{
    IppStatus sts;
    Ipp32f* l = new Ipp32f[nLevel];
    IppiSize origImgSize = {_width, _height};

    unsigned int* bins = new unsigned int[nLevel - 1];

    float minVal = 0, maxVal = 0, stepVal = 0;
    double meanVal = 0;
    if (levels != NULL)
    {
        for (unsigned int i = 0; i &lt; nLevel; i++)
        {
            l[i] = levels[i];
        }
    }
    else
    {
        MinMaxMean(minVal, maxVal, meanVal);
        stepVal = (maxVal - minVal) / (float) nLevel;

        for (unsigned int i = 0; i &lt; nLevel; i++)
        {
            l[i] = minVal + stepVal * i;
        }
    }

    sts = ippiHistogramRange_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, (Ipp32s*) bins, (Ipp32f*) l, nLevel);
    return bins;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Interfacing IPP with Magick++</title>
		<link>http://www.kerrywong.com/2009/03/17/interfacing-ipp-with-magick/</link>
		<comments>http://www.kerrywong.com/2009/03/17/interfacing-ipp-with-magick/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 01:01:24 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[IPP]]></category>
		<category><![CDATA[Multi-threading]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=864</guid>
		<description><![CDATA[Intel&#8217;s Integrated Performance Primitives (IPP) is a low level C++ library. It provides routines that are highly optimized on Intel processors. I recently started using it because its vast speed advantage in signal and image processing applications. Since the implementation of many of the functions are threaded, it makes the task of writing high performance [...]]]></description>
			<content:encoded><![CDATA[<p>Intel&#8217;s <a href="http://www.intel.com/cd/software/products/asmo-na/eng/302910.htm">Integrated Performance Primitives (IPP)</a> is a low level C++ library. It provides routines that are highly optimized on Intel processors. I recently started using it because its vast speed advantage in signal and image processing applications.<span id="more-864"></span></p>
<p>Since the implementation of many of the functions are threaded, it makes the task of writing high performance applications much easier. Since it is a set of &#8220;performance primitives&#8221; as the name suggests, it uses its own data structures (e.g. Ipp8u) and does not provide functions to directly inter-operate with data coming from other sources (e.g. image files).</p>
<p>Fortunately, such data conversion is pretty straight forward. In this post, I will illustrate how to convert an image file (e.g. .jpg, .png, .gif) to the data IPP uses, and how to save the result into a standard image file once the processing is done.</p>
<p><a href="http://www.imagemagick.org/Magick%2B%2B/">Magick++</a> is a very comprehensive image-processing C++ library and the Image class it provides handles image files quite well. So I chose to use Magic++&#8217;s API to convert image files to the data structure IPP uses. In this particular example, I will use a gray level image. But in practice, color images can be easily handled in a similar fashion.</p>
<p>For the code mentioned below, the following headers and namespaces are used:</p>
<pre class="brush: cpp;">
#include &lt;Magick++/Image.h&gt;
#include &lt;Magick++.h&gt;
#include &lt;ipp.h&gt;

using namespace std;
using namespace Magick;
</pre>
<p>And the following code shows how to convert a standard image file data into format that is suitable for IPP.</p>
<pre class="brush: cpp;">
    IppStatus sts;
    Image img(&quot;{Image File Name}&quot;);
    Geometry g = img.size();

    unsigned int width = g.width();
    unsigned int height= g.height();

    Pixels view(img);
    PixelPacket *pixels = view.get(0,0,width,height);

    int stepByte = 0;
    //allocating a buffer of unsigned char (Ipp8u) for the image.
    Ipp8u *imgCache = ippiMalloc_8u_C1(width,height, &amp;stepByte);

    for (unsigned int row = 0; row &lt; height ; row++)
    {
        for (unsigned int column = 0; column &lt; width ; column++)
        {
            PixelPacket *p = &amp;pixels[column + row * width];
            Color c = Color(p-&gt;red, p-&gt;green, p-&gt;blue);
            double i = c.scaleQuantumToDouble(c.intensity()) * 255;
            imgCache[column + row * width] = (char) i;
        }
    }
</pre>
<p>The above code snippet first reads the image data into *PixelPacket and the pixel buffer is then converted into a one channel buffer of chars (color value 0-255). Note that the range of the image data Magick++ reads in is between 0 and <strong><em>QuantumRange</em></strong>, which needs to be converted back to the range 0-255 accepted by the Ipp8u buffer. If other types of <strong><em>IPP</em></strong> image buffers are used (e.g. Ipp32f), this <strong><em>scaleQuantumToDouble()</em></strong> conversion may not be necessary. At the end, the image data is converted into the one dimensional array <strong><em>imgCache</em></strong> which can be used by <em>IPP</em> procedures.</p>
<p>Once we are in the <strong><em>IPP</em></strong> data domain, we can proceed with whatever processing we had in mind. Here I will show the code for edge detection using <a href="http://en.wikipedia.org/wiki/Canny_edge_detector">Canny algorithm</a>.</p>
<pre class="brush: cpp;">
    IppiSize orgImgSize = {width, height};
    IppiSize newImgSize = {width + 2, height + 2};

    Ipp8u *imgCache1 = ippiMalloc_8u_C1(width + 2,height + 2, &amp;stepByte);
    sts = ippiCopyReplicateBorder_8u_C1R(imgCache, width, orgImgSize,  imgCache1,
            width + 2 , newImgSize, 2, 2);
    IppiSize roi = {width, height};

    Ipp32f low=30.0f, high=100.0f;
    int size, size1, srcStep, dxStep, dyStep, dstStep;

    Ipp8u *src, *dst, *buffer;
    Ipp16s *dx, *dy;

    sts = ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(
            roi, ippMskSize3x3, &amp;size);
    sts = ippiFilterSobelHorizGetBufferSize_8u16s_C1R(
            roi, ippMskSize3x3, &amp;size1);

    if (size&lt;size1) size=size1;
    ippiCannyGetSize(roi, &amp;size1);
    if (size&lt;size1) size=size1;

    buffer = ippsMalloc_8u(size);
    dx = ippsMalloc_16s(size);
    dy = ippsMalloc_16s(size);
    dst = ippsMalloc_8u(size);

    sts = ippiFilterSobelNegVertBorder_8u16s_C1R (
            imgCache1, width + 2 , dx, (width + 2) * 2 ,
            roi, ippMskSize3x3, ippBorderRepl, 0, buffer);
    sts = ippiFilterSobelHorizBorder_8u16s_C1R(
            imgCache1, width + 2, dy, (width + 2) *2 ,
            roi, ippMskSize3x3, ippBorderRepl, 0, buffer);
    sts = ippiCanny_16s8u_C1R(dx,
            (width + 2) * 2, dy, (width + 2) * 2,
            dst, width, roi, low, high, buffer);
</pre>
<p>The code shown above is adopted from Intel&#8217;s IPP manual for image and video processing (by default it is located at /opt/intel/ipp/<em>{version number}</em>/em64t/doc/ippiman.pdf).</p>
<p>Please pay special attention to how the original image is extended via <strong><em>ippiCopyReplicateBorder_8u_C1R</em></strong>. The image is extended by 2 pixels in each direction because the 3&#215;3 mask used for the filtering operation. I omitted error checking code for simplicity, but in general you need to check the return status of each ippi function call. When the call is successful, the status is <strong><em>ippStsNoErr</em></strong>. If you receive a value other than <strong><em>ippStsNoErr</em></strong> (e.g. <strong><em>ippStsStepErr</em></strong>) you will need to check your buffer size to make sure that they are adjusted according to the data type. For instance, in the code above <strong><em>dx</em> </strong>and <strong><em>dy</em></strong> are both 16bit signed integers and thus they both occupy two bytes each. </p>
<p>To save the result image, we convert the pixel buffer back to <strong><em>PixelPacket</em></strong> type. Again we need to convert the data in the buffer (<strong><em>Ipp8u</em></strong>) to the range accepted by Magick++ API.</p>
<pre class="brush: cpp;">
    for (unsigned int y = 0; y&lt; height ; y++)
    {
        for (unsigned int x = 0; x &lt; width; x++)
        {
            Color c;
            float clr = (float) dst[x + y * width] /255;
            float q = c.scaleDoubleToQuantum(clr);
            pixels[x+ y * width] = Color(q, q, q);
        }
    }

    view.sync();
    img.syncPixels();

    img.write(&quot;{Image File Name}&quot;);
</pre>
<p>We can also save the result data into a new image (instead of syncing the data back to the image object holding the original image data) using the code below:</p>
<pre class="brush: cpp;">
    Image img1(Geometry(width, height),&quot;white&quot;);

    for (unsigned int y = 0; y&lt; height ; y++)
    {
        for (unsigned int x = 0; x &lt; width; x++)
        {
            Color c;
            float clr = (float) dst[x + y * width] /255;
            float q = c.scaleDoubleToQuantum(clr);
            img1.pixelColor(x,y, Color(q, q, q));
        }
    }

    img1.write(&quot;{Image File Name}&quot;);
</pre>
<p>And finally the buffers used are freed.</p>
<pre class="brush: cpp;">
    ippiFree(imgCache);
    ippsFree(buffer);
</pre>
<p>The following images show Canny edge detector in action using the code in this article:</p>
<div id="attachment_876" class="wp-caption aligncenter" style="width: 573px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/test.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/test.jpg" alt="Original" title="Original" width="563" height="422" class="size-full wp-image-876" /></a><p class="wp-caption-text">Original</p></div>
<div id="attachment_879" class="wp-caption aligncenter" style="width: 573px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/test_canny.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/test_canny.png" alt="Canny Edge Detector applied" title="Canny Edge Detector applied" width="563" height="422" class="size-full wp-image-879" /></a><p class="wp-caption-text">Canny Edge Detector applied</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/03/17/interfacing-ipp-with-magick/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Matrix Multiplication Performance in C++</title>
		<link>http://www.kerrywong.com/2009/03/07/matrix-multiplication-performance-in-c/</link>
		<comments>http://www.kerrywong.com/2009/03/07/matrix-multiplication-performance-in-c/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 04:16:14 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[BLAS]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[MATLAB]]></category>
		<category><![CDATA[matrix multiplication]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=586</guid>
		<description><![CDATA[A few days ago, I ran across this article by Dmitri Nesteruk. In his article, he compared the performance between C# and C++ in matrix multiplication. From the data he provided, matrix multiplication using C# is two to three times slower than using C++ in comparable situations. Even though a lot of optimizations have been [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago, I ran across <a href="http://mindstudies.psy.soton.ac.uk/dmitri/blog/index.php/archives/160">this article by Dmitri Nesteruk</a>. In his article, he compared the performance between C# and C++ in <a href="http://en.wikipedia.org/wiki/Matrix_multiplication">matrix multiplication</a>. From the data he provided, matrix multiplication using C# is two to three times slower than using C++ in comparable situations.<span id="more-586"></span></p>
<p>Even though a lot of optimizations have been done in the .Net runtime to make it more efficient, it is apparent that scientific programming still favors C and C++ because that the performance advantage is huge.</p>
<p>In this article, I will examine some matrix multiplication algorithms that are commonly used and illustrate the efficiencies of the various methods. All the tests are done using C++ only and matrices size ranging from 500&#215;500 to 2000&#215;2000. When the matrix sizes are small (e.g. &lt;50), you can pretty much use any matrix multiplication algorithms without observing any significant performance differences. This is largely due to the fact that the typical stable matrix multiplication algorithms are O(n^3) and sometimes array operation overheads outweigh the benefit of algorithm efficiencies. But for matrices of larger dimensions, the efficiency of the multiplication algorithm becomes extremely important.</p>
<p>Since <a href="http://mindstudies.psy.soton.ac.uk/dmitri/blog/index.php/archives/160">Dmitri&#8217;s article</a> has already captured pretty detailed data using the standard matrix multiplication algorithm, I will not repeat his findings in this article. What I intended to show was the performance data of <a href="http://www.boost.org/doc/libs/1_38_0/libs/numeric/ublas/doc/overview.htm">uBLAS</a>, <a href="http://openmp.org/wp/">OpenMP</a>, <a href="http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms">cBLAS</a> and <a href="http://www.mathworks.com/">MATLAB</a>.</p>
<p>The following sample code are compiled under Ubuntu 8.10 64 bit (kernel 2.6.24.23) on Intel Q9450@3.2GHz.</p>
<h4>Standard Matrix Multiplication (Single Threaded)</h4>
<p>This is our reference code. Later on, I will only show the critical portion of the code and not repeat the common portion of code that initializes/finalizes the arrays. Similarly, the timing method used is also the same across all the tests and will be omitted later on.</p>
<pre class="brush: cpp;">
float **A, **B, **C;

A = new float*[matrix_size];
B = new float*[matrix_size];
C = new float*[matrix_size];

for (int i = 0 ; i &lt; matrix_size; i++)
{
    A[i] = new float[matrix_size];
    B[i] = new float[matrix_size];
    C[i] = new float[matrix_size];
}

for (int i=0; i&lt;matrix_size; i++)
{
    for (int j = 0 ; j &lt; matrix_size; j++)
    {
        A[i][j]=rand();
        B[i][j]=rand();
    }
}

timeval t1, t2, t;
gettimeofday(&amp;t1, NULL);

for (int i = 0 ; i &lt; matrix_size; i++)
{
    for (int j = 0;  j &lt; matrix_size; j++)
    {
        C[i][j] = 0;
        for (int k = 0; k &lt; matrix_size; k++)
        {
            C[i][j] += A[i][k] * B[k][j];
        }
    }
}

gettimeofday(&amp;t2, NULL);
timersub(&amp;t2, &amp;t1, &amp;t);

cout &lt;&lt; t.tv_sec + t.tv_usec/1000000.0 &lt;&lt; &quot; Seconds -- Standard&quot; &lt;&lt; endl;

for (int i = 0 ; i &lt; matrix_size; i++)
{
    delete A[i];
    delete B[i];
    delete C[i];
}

delete A;
delete B;
delete C;
</pre>
<h4>OpenMP With Two Dimensional Arrays</h4>
<p>Using OpenMP, we are able to multiple threads via the #pragma omp directives. For the simple algorithm we used here, the speed increase is almost proportional to the number of available cores within the system.</p>
<pre class="brush: cpp;">
...
#pragma omp parallel for shared(a,b,c)
for (long i=0; i&lt;matrix_size; i++)
{
    for (long j = 0; j &lt; matrix_size; j++)
    {
        float sum = 0;
        for (long k = 0; k &lt; matrix_size; k++)
        {
            sum +=a[i][k]*b[k][j];
        }
        c[i][j] = sum;
    }
}
...
</pre>
<h4>OpenMP With One Dimensional Arrays</h4>
<p>Cache locality is poor using the simple algorithm I showed above. The performance can be easily improved however by improving the locality of the references. One way to achieve better cache locality is to use one dimensional array instead of two dimensional array and as you will see later, the performance of the following implementation has as much as 50% speed gains over the previous OpenMP implementation using two dimensional arrays.</p>
<pre class="brush: cpp;">
float *a, *b, *c;

a = new float[matrix_size * matrix_size];
b = new float[matrix_size * matrix_size];
c = new float[matrix_size * matrix_size];

for (long i=0; i&lt;matrix_size * matrix_size; i++)
{
    a[i]=rand();
    b[i] = rand();
    c[i] = 0;
}

#pragma omp parallel for shared(a,b,c)
for (long i=0; i&lt;matrix_size; i++)
{
    for (long j = 0; j &lt; matrix_size; j++)
    {
        long idx = i * matrix_size;
        float sum = 0;
        for (long k = 0; k &lt; matrix_size; k++)
        {
            sum +=a[idx + k]*b[k * matrix_size +j];
        }
        c[idx + j] = sum;
    }
}

delete a;
delete b;
delete c;
</pre>
<h4>Boost Library uBLAS (Single Threaded)</h4>
<p>Boost library provides a convenient way to perform matrix multiplication. However, the performance is very poor compared to all other approaches mentioned in this article. The performance of the uBLAS implementation is largely on par with that using C# (see benchmarks towards the end of the article). Intel&#8217;s Math Kernal Library (MKL) 10.1 does provide functionality to dynamically convert code using uBLAS syntax into highly efficient code using MKL by the inclusion of header file mkl_boost_ublas_matrix_prod.hpp. I have not tried it myself though, but the performance should be comparible to algorithms using the native MKL BLAS interface.</p>
<p>By default (without using MKL&#8217;s uBLAS capability) though, uBLAS is single threaded and due to its poor performance and I would strongly suggest avoid using uBLAS in any high performance scientific applications.</p>
<pre class="brush: cpp;">
matrix&lt;float&gt; A, B, C;

A.resize(matrix_size,matrix_size);
B.resize(matrix_size,matrix_size);

for (int i = 0; i &lt; matrix_size; ++ i)
{
    for (int j = 0; j &lt; matrix_size; ++ j)
    {
        A(i, j) = rand();
        B(i, j) = rand();
    }
}

C =prod(A, B);
</pre>
<h4>Intel Math Kernel Library (MKL) cBLAS</h4>
<p>Intel&#8217;s Math Kernel Library (MKL) is highly optimized on Intel&#8217;s microprocessor platforms. Given that Intel developed this library for its own processor platforms we can expect significant performance gains. I am still surprised at how fast the code runs using cBLAS though. In fact, it was so fast that I doubted the validity of the result at first. But after checking the results against those obtained by other means, those doubts were putting into rest.</p>
<p>The cBLAS matrix multiplication uses blocked matrix multiplication method which further improves cache locality. And it is more than thirty times faster then the fastest OMP 1D algorithm listed above! Another benefit is that by default it automatically detects the number of CPUs/cores available and uses all available threads. This behavior greatly simplifies the code since threading is handled transparently within the library.</p>
<pre class="brush: cpp;">
float *A, *B, *C;

A = new float[matrix_size * matrix_size];
B = new float[matrix_size * matrix_size];
C = new float[matrix_size * matrix_size];

for (int i = 0; i &lt; matrix_size * matrix_size; i++)
{
    A[i] = rand();
    B[i] = rand();
    C[i] = 0;
}

cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
    matrix_size,  matrix_size,  matrix_size, 1.0, A,matrix_size,
    B, matrix_size, 0.0, C, matrix_size);
</pre>
<h4>MATLAB (Single Threaded)</h4>
<p>MATLAB is known for its efficient algorithms. In fact it uses BLAS libraries for its own matrix calculation routines. The version of MATLAB I have is a little dated (7.0.1), but nevertheless it would be interesting to see how its performance compares with that of latest MKL&#8217;s. MATLAB 7 is single threaded, and given the same matrix size, it runs roughly three times slower than the fastest MKL routine listed above (per core).</p>
<pre>    a = rand(i,i);
    b = rand(i,i);
    tic;
    c = a*b;
    t = toc</pre>
<p>
The following table shows the results I obtained by running the code listed above. The results are time in seconds. (note, S.TH means single threaded and M.TH means multi-threaded).</p>
<table border="0" cellspacing="0" frame="void" rules="none">
<colgroup>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
</colgroup>
<tbody>
<tr>
<td style="border: 1px solid #000000;" width="116" height="17" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">Size/Algorithm</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">uBLAS S.TH</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">STD S.TH</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">OMP 2D</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">OMP 1D</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">MATLAB S.TH</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">cBLAS M.TH</span></strong></td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">500&#215;500</span></strong></td>
<td style="border: 1px solid #000000;" align="right">3.2435</td>
<td style="border: 1px solid #000000;" align="right">0.5253</td>
<td style="border: 1px solid #000000;" align="right">0.1939</td>
<td style="border: 1px solid #000000;" align="right">0.0536</td>
<td style="border: 1px solid #000000;" align="right">0.0810</td>
<td style="border: 1px solid #000000;" align="right">0.0206</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">600&#215;600</span></strong></td>
<td style="border: 1px solid #000000;" align="right">5.7854</td>
<td style="border: 1px solid #000000;" align="right">0.9349</td>
<td style="border: 1px solid #000000;" align="right">0.3223</td>
<td style="border: 1px solid #000000;" align="right">0.1655</td>
<td style="border: 1px solid #000000;" align="right">0.1410</td>
<td style="border: 1px solid #000000;" align="right">0.0093</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">700&#215;700</span></strong></td>
<td style="border: 1px solid #000000;" align="right">9.2292</td>
<td style="border: 1px solid #000000;" align="right">1.2928</td>
<td style="border: 1px solid #000000;" align="right">0.3529</td>
<td style="border: 1px solid #000000;" align="right">0.2797</td>
<td style="border: 1px solid #000000;" align="right">0.2230</td>
<td style="border: 1px solid #000000;" align="right">0.0122</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">800&#215;800</span></strong></td>
<td style="border: 1px solid #000000;" align="right">13.7711</td>
<td style="border: 1px solid #000000;" align="right">2.3746</td>
<td style="border: 1px solid #000000;" align="right">0.7259</td>
<td style="border: 1px solid #000000;" align="right">0.4135</td>
<td style="border: 1px solid #000000;" align="right">0.3320</td>
<td style="border: 1px solid #000000;" align="right">0.0310</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">900&#215;900</span></strong></td>
<td style="border: 1px solid #000000;" align="right">20.3245</td>
<td style="border: 1px solid #000000;" align="right">3.4983</td>
<td style="border: 1px solid #000000;" align="right">1.0146</td>
<td style="border: 1px solid #000000;" align="right">0.7449</td>
<td style="border: 1px solid #000000;" align="right">0.4740</td>
<td style="border: 1px solid #000000;" align="right">0.0306</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1000&#215;1000</span></strong></td>
<td style="border: 1px solid #000000;" align="right">28.8345</td>
<td style="border: 1px solid #000000;" align="right">3.4983</td>
<td style="border: 1px solid #000000;" align="right">1.4748</td>
<td style="border: 1px solid #000000;" align="right">1.0548</td>
<td style="border: 1px solid #000000;" align="right">0.6530</td>
<td style="border: 1px solid #000000;" align="right">0.0700</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1100&#215;1100</span></strong></td>
<td style="border: 1px solid #000000;" align="right">38.2545</td>
<td style="border: 1px solid #000000;" align="right">7.0240</td>
<td style="border: 1px solid #000000;" align="right">1.9383</td>
<td style="border: 1px solid #000000;" align="right">1.6257</td>
<td style="border: 1px solid #000000;" align="right">0.8620</td>
<td style="border: 1px solid #000000;" align="right">0.1250</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1200&#215;1200</span></strong></td>
<td style="border: 1px solid #000000;" align="right">50.4964</td>
<td style="border: 1px solid #000000;" align="right">9.9319</td>
<td style="border: 1px solid #000000;" align="right">2.8411</td>
<td style="border: 1px solid #000000;" align="right">2.1215</td>
<td style="border: 1px solid #000000;" align="right">1.1170</td>
<td style="border: 1px solid #000000;" align="right">0.0440</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1300&#215;1300</span></strong></td>
<td style="border: 1px solid #000000;" align="right">64.5064</td>
<td style="border: 1px solid #000000;" align="right">12.8344</td>
<td style="border: 1px solid #000000;" align="right">3.6277</td>
<td style="border: 1px solid #000000;" align="right">2.9720</td>
<td style="border: 1px solid #000000;" align="right">1.4250</td>
<td style="border: 1px solid #000000;" align="right">0.0440</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1400&#215;1400</span></strong></td>
<td style="border: 1px solid #000000;" align="right">81.1826</td>
<td style="border: 1px solid #000000;" align="right">17.1119</td>
<td style="border: 1px solid #000000;" align="right">4.8309</td>
<td style="border: 1px solid #000000;" align="right">3.5977</td>
<td style="border: 1px solid #000000;" align="right">1.7760</td>
<td style="border: 1px solid #000000;" align="right">0.0938</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1500&#215;1500</span></strong></td>
<td style="border: 1px solid #000000;" align="right">100.1330</td>
<td style="border: 1px solid #000000;" align="right">21.0622</td>
<td style="border: 1px solid #000000;" align="right">6.1689</td>
<td style="border: 1px solid #000000;" align="right">4.8022</td>
<td style="border: 1px solid #000000;" align="right">2.1870</td>
<td style="border: 1px solid #000000;" align="right">0.1111</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1600&#215;1600</span></strong></td>
<td style="border: 1px solid #000000;" align="right">120.3400</td>
<td style="border: 1px solid #000000;" align="right">26.4316</td>
<td style="border: 1px solid #000000;" align="right">7.3189</td>
<td style="border: 1px solid #000000;" align="right">5.0451</td>
<td style="border: 1px solid #000000;" align="right">2.6490</td>
<td style="border: 1px solid #000000;" align="right">0.1699</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1700&#215;1700</span></strong></td>
<td style="border: 1px solid #000000;" align="right">145.8550</td>
<td style="border: 1px solid #000000;" align="right">31.2706</td>
<td style="border: 1px solid #000000;" align="right">8.7525</td>
<td style="border: 1px solid #000000;" align="right">6.8915</td>
<td style="border: 1px solid #000000;" align="right">3.1870</td>
<td style="border: 1px solid #000000;" align="right">0.1452</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1800&#215;1800</span></strong></td>
<td style="border: 1px solid #000000;" align="right">174.6860</td>
<td style="border: 1px solid #000000;" align="right">38.9293</td>
<td style="border: 1px solid #000000;" align="right">11.1060</td>
<td style="border: 1px solid #000000;" align="right">8.1316</td>
<td style="border: 1px solid #000000;" align="right">3.7940</td>
<td style="border: 1px solid #000000;" align="right">0.1989</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1900&#215;1900</span></strong></td>
<td style="border: 1px solid #000000;" align="right">206.0520</td>
<td style="border: 1px solid #000000;" align="right">45.8589</td>
<td style="border: 1px solid #000000;" align="right">13.0832</td>
<td style="border: 1px solid #000000;" align="right">9.9527</td>
<td style="border: 1px solid #000000;" align="right">4.4450</td>
<td style="border: 1px solid #000000;" align="right">0.2725</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">2000&#215;2000</span></strong></td>
<td style="border: 1px solid #000000;" align="right">240.7820</td>
<td style="border: 1px solid #000000;" align="right">55.4392</td>
<td style="border: 1px solid #000000;" align="right">16.0542</td>
<td style="border: 1px solid #000000;" align="right">11.0314</td>
<td style="border: 1px solid #000000;" align="right">5.1820</td>
<td style="border: 1px solid #000000;" align="right">0.3359</td>
</tr>
</tbody>
</table>
<p style="text-align: left;">
The following figure shows the results. Since uBLAS and single threaded matrix multiplications took significantly longer to compute, I did not include them in the figure below.
</p>
<p style="text-align: center;">
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/linearplot.png"><img class="size-full wp-image-645" title="Matrix Multiplication (Linear)" src="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/linearplot.png" alt="Matrix Multiplication (Linear)" width="560" height="420" /></a></p>
<p style="text-align: left;">
The following figure shows the same data but uses log-scale Y axis instead so that all the data can show up nicely. You can get a sense of various algorithms&#8217; efficiencies here:</p>
<p style="text-align: center;">
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/logplot.png"><img class="alignnone size-full wp-image-646"  title="Matrix Multiplication (Log)" src="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/logplot.png" alt="Matrix Multiplication (Log)" width="560" height="420" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/03/07/matrix-multiplication-performance-in-c/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Two Level Tree and Its Applications — II</title>
		<link>http://www.kerrywong.com/2008/12/22/two-level-tree-and-its-applications-%e2%80%94-ii/</link>
		<comments>http://www.kerrywong.com/2008/12/22/two-level-tree-and-its-applications-%e2%80%94-ii/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 00:37:27 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[Tree]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=480</guid>
		<description><![CDATA[In my previous post, I discussed how to merge and split a two level tree. Before moving on to discuss its applications, let us take a look at the output of the sample program I gave before.&#160; &#160;&#160;&#160; &#160;&#160;&#160; static void Main(string[] args) &#160;&#160;&#160; &#160;&#160;&#160; { &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; TreeNode n1 = new TreeNode(&#34;t1&#34;); &#160;&#160;&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="/2008/12/21/two-level-tree-and-its-applications-i/">previous post</a>, I discussed how to merge and split a two level tree. Before moving on to discuss its applications, let us take a look at the output of the sample program I gave before.&nbsp;<span id="more-480"></span></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">static</span> <span style="color: blue; font-weight: bold;">void</span> Main(<span style="color: blue; font-weight: bold;">string</span>[] args)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t1&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t2&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n3 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t3&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n4 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t4&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n5 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t5&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n6 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t6&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> n1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(n2)<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(n3);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t1);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> n4<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(n5)<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(n6);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t2);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t3 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> t1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(t2);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t3);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t4 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> t3<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Remove(n4);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t4);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t5 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> t4<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Remove(n1);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t5);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>ReadKey();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p>Here is the output from the main routine:</p>
<blockquote>
<div><font face="Courier New">(t1);t2;t3;<br />
(t4);t5;t6;<br />
(t1);t2;t3;t4;t5;t6;<br />
(t1);t2;t3;t5;t6;<br />
(t2);t3;t5;t6;</font></div>
</blockquote>
<p>As you can see, tree t1 is formed by adding nodes t2 and t3 and the resulting tree is a two-level tree with t1 being the root. Similarly, t4 is formed by adding nodes t5 and t6. We then combined this two tree we just created, note how node t4 changed to a leaf in order to satisfy the two level property. In the next two output lines, we removed nodes from the two level tree. Note the last line: when we removed the root node, a leaf node (t2) is chosen as the new root of the tree.</p>
<p>Two level tree is extremely useful in capturing relationships in real world applications. For instance, if a is related to b and c, and d is related to e and f. Now we have two sets of distinct relationships (both are two level trees):</p>
<blockquote>
<div><font face="Courier New">(a);b;c</font></div>
<div><font face="Courier New">(d);e;f</font></div>
</blockquote>
<p>Now suppose that we also know c is related to e, what would the new relationship be? We know that a, b, c, d, e, f are then all related. But how do we capture this kind of relationships programmatically? As it turned out, we can use two level trees. In the example we just discussed, the relationship between e and c are captured via combining the two trees. And thus we get the following two level tree:</p>
<blockquote>
<div><font face="Courier New">(a);b;c;d;e;f</font></div>
</blockquote>
<p>Since related items are not necessarily limited to just tree roots (e.g. c and e are both leafs), we needed to be able to refer to a tree by either its root or its nodes and this is why in my <a href="/2008/12/21/two-level-tree-and-its-applications-i/">previous post</a> I mentioned that it would be a lot easier if we allowed referencing a tree by either the root node or its leafs.</p>
<p>One benefit of using a two level tree to capture relationships is that finding out the related items is a constant time operation since all of the related items are in a two level tree and no further tree traversal is required. In a large data set, this algorithm becomes very effective since no recursion is required.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/12/22/two-level-tree-and-its-applications-%e2%80%94-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Two Level Tree and Its Applications &#8212; I</title>
		<link>http://www.kerrywong.com/2008/12/21/two-level-tree-and-its-applications-i/</link>
		<comments>http://www.kerrywong.com/2008/12/21/two-level-tree-and-its-applications-i/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 02:19:59 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[Tree]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=474</guid>
		<description><![CDATA[A two level tree is a simple tree data structure. Unlike in a typical tree where the tree depths could be arbitrary, a two level tree has only two levels as its name suggests. Two level tree is also equivalent to a star.The following graph illustrates what a two level tree looks like: A two [...]]]></description>
			<content:encoded><![CDATA[<p>A two level tree is a simple <a href="http://en.wikipedia.org/wiki/Tree_(data_structure)">tree data structure</a>. Unlike in a typical tree where the tree depths could be arbitrary, a two level tree has only two levels as its name suggests. Two level tree is also equivalent to a <a href="http://en.wikipedia.org/wiki/Star_(graph_theory)">star</a>.<span id="more-474"></span>The following graph illustrates what a two level tree looks like:</p>
<p align="center"><img alt="Two Level Tree" src="/blog/wp-content/uploads/2008/12/twoleveltree1.png" /></p>
<p align="center">A two level tree</p>
<p align="left">There is no internal nodes in a two level tree. A two level tree has only a root node and a set of leaf nodes.</p>
<p align="left">There are two types basic of operations we can perform on a two level tree: we can Add a two level tree to another two level tree and thus form a new two level tree or we can remove a node or a set of nodes from a two level tree.</p>
<p align="left">To add a two level tree to another two level tree, we need to ensure that the combined tree remains a two level tree. when we say adding a tree, it means adding the &quot;whole tree&quot;. But in practice, we really do not care which part of the tree we refer to. For instance, the above tree can be referred to by A (the root node), or by any of the four children (e.g. C). Thus there are four scenarios when adding two trees together, depending on how the tree is referenced. The following graph illustrate this:</p>
<p align="center"><img alt="Merging Two Two Level Trees" src="/blog/wp-content/uploads/2008/12/twoleveltree2.png" /></p>
<p align="center">Merging Two Two Level Trees</p>
<p align="left">The above four different scenarios depend on how the tree is referenced (the shaded letters). We could mandate that a tree referenced by its root node and thus simplify the merging algorithm, but you will see in a later post that this approach adds more flexibility. The following code (C#) shows how the above steps are accomplished:&nbsp;</p>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New"><span style="font-weight: bold; color: blue">namespace</span> TwoLevelTree</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">{</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: blue">class</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">private</span> <span style="font-weight: bold; color: blue">string</span> _ID <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">private</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span> _parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">private</span> <span style="font-weight: bold; color: #2b91af">List</span><span style="font-weight: bold; color: #8080c0">&lt;</span><span style="font-weight: bold; color: #2b91af">TreeNode</span><span style="font-weight: bold; color: #8080c0">&gt;</span> _children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: blue">string</span> ID</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">get</span> { <span style="font-weight: bold; color: blue">return</span> _ID; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">set</span> { _ID <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">value</span>; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span> Parent</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">get</span> { <span style="font-weight: bold; color: blue">return</span> _parent; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">set</span> { _parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">value</span>; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: #2b91af">List</span><span style="font-weight: bold; color: #8080c0">&lt;</span><span style="font-weight: bold; color: #2b91af">TreeNode</span><span style="font-weight: bold; color: #8080c0">&gt;</span> Children</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">get</span> { <span style="font-weight: bold; color: blue">return</span> _children; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">set</span> { _children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">value</span>; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> TreeNode(<span style="font-weight: bold; color: blue">string</span> id)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _ID <span style="font-weight: bold; color: #8080c0">=</span> id;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span> Add(<span style="font-weight: bold; color: #2b91af">TreeNode</span> node)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (<span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">==</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (<span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">==</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">List</span><span style="font-weight: bold; color: #8080c0">&lt;</span><span style="font-weight: bold; color: #2b91af">TreeNode</span><span style="font-weight: bold; color: #8080c0">&gt;</span>();</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Add(node);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; node<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (node<span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> node<span style="font-weight: bold; color: #8080c0">.</span>Children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Add(n);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; n<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; node<span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">else</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent<span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Add(node);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; node<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (node<span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> node<span style="font-weight: bold; color: #8080c0">.</span>Children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent<span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Add(n);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; n<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; node<span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">return</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span> Remove(<span style="font-weight: bold; color: #2b91af">TreeNode</span> node)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (node<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Remove(node);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">else</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>ID <span style="font-weight: bold; color: #8080c0">=</span> _children[<span style="color: teal">0</span>]<span style="font-weight: bold; color: #8080c0">.</span>ID;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _children<span style="font-weight: bold; color: #8080c0">.</span>RemoveAt(<span style="color: teal">0</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> _children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; n<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">return</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: blue">override</span> <span style="font-weight: bold; color: blue">string</span> ToString()</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">StringBuilder</span> sb <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">StringBuilder</span>();</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (_parent <span style="font-weight: bold; color: #8080c0">==</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb<span style="font-weight: bold; color: #8080c0">.</span>Append(<span style="font-weight: bold; color: blue">string</span><span style="font-weight: bold; color: #8080c0">.</span>Format(<span style="font-weight: bold; color: #a31515">&quot;({0});&quot;</span>, _ID));</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (_children <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> _children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb<span style="font-weight: bold; color: #8080c0">.</span>Append(n<span style="font-weight: bold; color: #8080c0">.</span>ToString());</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">else</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb<span style="font-weight: bold; color: #8080c0">.</span>Append(<span style="font-weight: bold; color: blue">string</span><span style="font-weight: bold; color: #8080c0">.</span>Format(<span style="font-weight: bold; color: #a31515">&quot;{0};&quot;</span>, _ID));</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (_children <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> _children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb<span style="font-weight: bold; color: #8080c0">.</span>Append(n<span style="font-weight: bold; color: #8080c0">.</span>ToString());</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">return</span> sb<span style="font-weight: bold; color: #8080c0">.</span>ToString();</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">class</span> <span style="font-weight: bold; color: #2b91af">Program</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">static</span> <span style="font-weight: bold; color: blue">void</span> Main(<span style="font-weight: bold; color: blue">string</span>[] args)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n1 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t1&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n2 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t2&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n3 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t3&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n4 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t4&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n5 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t5&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n6 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t6&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t1 <span style="font-weight: bold; color: #8080c0">=</span> n1<span style="font-weight: bold; color: #8080c0">.</span>Add(n2)<span style="font-weight: bold; color: #8080c0">.</span>Add(n3);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t1);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t2 <span style="font-weight: bold; color: #8080c0">=</span> n4<span style="font-weight: bold; color: #8080c0">.</span>Add(n5)<span style="font-weight: bold; color: #8080c0">.</span>Add(n6);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t2);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t3 <span style="font-weight: bold; color: #8080c0">=</span> t1<span style="font-weight: bold; color: #8080c0">.</span>Add(t2);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t3);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t4 <span style="font-weight: bold; color: #8080c0">=</span> t3<span style="font-weight: bold; color: #8080c0">.</span>Remove(n4);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t4);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t5 <span style="font-weight: bold; color: #8080c0">=</span> t4<span style="font-weight: bold; color: #8080c0">.</span>Remove(n1);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t5);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>ReadKey();</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">}</div>
<p><!--EndFragment--></p>
<p align="left">The &quot;remove&quot; operation is pretty simple as well. Bascically, when the node to be removed is leaf, we simply remove it. When it is root, we select one of the leave nodes to be root and forming a new two level tree.</p>
<p align="left">In the next post, I will show you one of the applications of a two level tree.</p>
<p align="left">&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/12/21/two-level-tree-and-its-applications-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Producer-Consumer: A Duplicate File Finder</title>
		<link>http://www.kerrywong.com/2008/09/05/producer-consumer-a-duplicate-file-finder/</link>
		<comments>http://www.kerrywong.com/2008/09/05/producer-consumer-a-duplicate-file-finder/#comments</comments>
		<pubDate>Sat, 06 Sep 2008 01:08:16 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/2008/09/05/producer-consumer-a-duplicate-file-finder/</guid>
		<description><![CDATA[Processes tend to benefit greatly from multi-core processors if they are CPU bound (i.e. computational intensive tasks). The actual speedup depends on the portion of the code that must remain sequential. The multi-core benefit diminishes for IO bound processes however since hard drive performance becomes the limiting factor. Unlike solid state drives (SSD), traditional hard [...]]]></description>
			<content:encoded><![CDATA[<p>Processes tend to benefit greatly from multi-core processors if they are CPU bound (i.e. computational intensive tasks). The actual speedup <a href="http://en.wikipedia.org/wiki/Amdahl%27s_Law">depends on the portion of the code that must remain sequential</a>.<span id="more-334"></span> The multi-core benefit diminishes for IO bound processes however since hard drive performance becomes the limiting factor. Unlike solid state drives (SSD), traditional hard drives are very good at handling large sequential reads/writes but handle random accesses poorly. In fact, parallelizing sequential read/write access can actually cause performance degradation since sequential data might be accessed by different threads and parallelizing the access makes the access pattern of each thread more random. So the performance of such IO bound task is largely determined by the IO sub-system performance.</p>
<p>For tasks that contain both intensive IO operations and CPU usages however it is desirable to parallelize the IO bound portion and the CPU bound portion of code so that maximum parallelism can be achieved.</p>
<p>An example of such IO and CPU intensive tasks is finding duplicate files in a file system. To find duplicate files, files or their hashes must be compared. In this post, I will discuss a couple of different approaches to achieve this using threading.</p>
<p><strong>1. Sequential find</strong><br />
First let us take a look at how to find duplicate files sequentially (all the sample code can be downloaded from <a href="/blog/wp-content/uploads/2008/09/dupfinder.zip">here</a>):</p>
<p>Suppose we have a function that returns a list of files within a directory (see GetFileList in FileUtils). In function FindDuplicates, we loop through the list of files and calculate the hash of each file. The file name and hash are used together as a key to a hash table. Whenever the same key is indexed the count is incremented by one indicating a duplicate file is found. Here is what the code looks like:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> FindDuplicates(<span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> files)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">foreach</span> (<span style="color: blue; font-weight: bold;">string</span> fn <span style="color: blue; font-weight: bold;">in</span> files)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">string</span> h <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> ComputeMD5(fn);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (h <span style="color: rgb(128, 128, 192); font-weight: bold;">!=</span> <span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Empty)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span> def <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetFileName(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FilePath <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetDirectoryName(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>LastModifiedDate <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetLastWriteTime(fn);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span> fileInfo <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span>(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> fileInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (Hash<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Contains(<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)))</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> l <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> Hash[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)] <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(def);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Hash[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> l;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> l <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(def);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Hash<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h), l);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p>
<strong>2. ThreadPool</strong><br />
We could improve the performance by moving the hash calculation to separate threads. </p>
<p>The first approach to parallelize the task is to use a thread pool to queue the work of calculating file hashes. Since calculating file hash involves reading in the whole file (IO bound) and some calculation on the content, there is some inherent parallelism so using multiple threads could potentially improve performance.</p>
<p>The code below shows this approach:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> FindDuplicates(<span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> files)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> (<span style="color: blue; font-weight: bold;">int</span> n <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span>; n <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> files<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Count; n <span style="color: rgb(128, 128, 192); font-weight: bold;">+=</span> _numOfThreads)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _autoEvents <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">AutoResetEvent</span>[_numOfThreads];</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> (<span style="color: blue; font-weight: bold;">int</span> i <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span>; i <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> _numOfThreads; i<span style="color: rgb(128, 128, 192); font-weight: bold;">++</span>)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (n <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> i <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> files<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Count)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _autoEvents[i] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">AutoResetEvent</span>(<span style="color: blue; font-weight: bold;">false</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">ThreadPool</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>QueueUserWorkItem(CalculateFileHash, <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileThreadInfo</span>(i, files[n <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> i]));</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _autoEvents[i] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">AutoResetEvent</span>(<span style="color: blue; font-weight: bold;">true</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">WaitHandle</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WaitAll(_autoEvents);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">private</span> <span style="color: blue; font-weight: bold;">void</span> CalculateFileHash(<span style="color: blue; font-weight: bold;">object</span> stateInfo)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileThreadInfo</span> threadInfo <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> stateInfo <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileThreadInfo</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">string</span> h <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> ComputeMD5(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Thread</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>CurrentThread<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Name <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (h <span style="color: rgb(128, 128, 192); font-weight: bold;">!=</span> <span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Empty)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span> def <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetFileName(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FilePath <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetDirectoryName(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>LastModifiedDate <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetLastWriteTime(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span> fileInfo <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span>(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> fileInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (Hash<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Contains(<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)))</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> l <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> Hash[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)] <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(def);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Hash[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> l;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> l <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(def);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Hash<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h), l);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _autoEvents[threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>ID]<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Set();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p><strong><br />
3. Producer and Consumer</strong><br />
Even through the previous approach improved the duplicated file finding performance, it is still not optimum. For example, even though multiple threads are used to calculate file hashes, they are joined at the end before another set of calculation is queued. Also, the IO is operations are distributed across multiple threads and on some older hard drives handling IO in multiple threads can actually slow things down. An ideal solution would be to use a single thread for IO operation since IO is inherently sequential. </p>
<p>As it turned out, this problem is a classic <a href="http://en.wikipedia.org/wiki/Producer-consumer ">producer-consumer</a> problem. In this third approach, we will examine how to use the producer consumer model to solve the problem of finding duplicates. In this approach, the producer thread searches for files within a given directory. It opens each file as it encounters and read the content into a <a href="http://research.microsoft.com/~birrell/papers/ThreadsCSharp.pdf">ProducerConsuerQueue</a>. At the same time, the consumer computes the hash from the bytes stored in the queue and determines whether a file is duplicated or not. The code is slightly different than what you saw above as files are being added to the queue and consumed from the queue simultaneously.</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">ProducerConsumerQueue</span> _q <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">null</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> FindDuplicates(<span style="color: blue; font-weight: bold;">string</span> rootDir)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">using</span> (_q <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">ProducerConsumerQueue</span>())</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GetFiles(rootDir);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _q<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>OutputDuplicates();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> GetFiles(<span style="color: blue; font-weight: bold;">string</span> rootDir)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">string</span>[] files <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">null</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">try</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; files <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetFiles(rootDir);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">foreach</span> (<span style="color: blue; font-weight: bold;">string</span> fn <span style="color: blue; font-weight: bold;">in</span> files)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span> def <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetFileName(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FilePath <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetDirectoryName(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>LastModifiedDate <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetLastWriteTime(fn);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span> fileInfo <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span>(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> fileInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileStream</span> f <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileStream</span>(fn, <span style="color: olive; font-weight: bold;">FileMode</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Open);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">byte</span>[] bytes <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: blue; font-weight: bold;">byte</span>[f<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length];&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Read(bytes, <span style="color: teal;">0</span>, (<span style="color: blue; font-weight: bold;">int</span>) f<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length <span style="color: rgb(128, 128, 192); font-weight: bold;">-</span> <span style="color: teal;">1</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Close();</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _q<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>EnqueueTask(<span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileBytes</span>(def, bytes));</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">catch</span> (<span style="color: rgb(43, 145, 175); font-weight: bold;">Exception</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">string</span>[] dirs <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">null</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">try</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dirs <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetDirectories(rootDir);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">foreach</span> (<span style="color: blue; font-weight: bold;">string</span> s <span style="color: blue; font-weight: bold;">in</span> dirs)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GetFiles(s);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">catch</span> (<span style="color: rgb(43, 145, 175); font-weight: bold;">Exception</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p>If you run each versions of the code, you will see that this approach has most of the performance gains. It has better performance than ThreadPool approach since the IO thread always tries to keep the queue. Further, concentrate IO operations into a single thread helps the system optimize IO requests and thus increases the IO subsystem performance.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/09/05/producer-consumer-a-duplicate-file-finder/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Same Method, Different Speed</title>
		<link>http://www.kerrywong.com/2007/12/31/same-method-different-speed/</link>
		<comments>http://www.kerrywong.com/2007/12/31/same-method-different-speed/#comments</comments>
		<pubDate>Tue, 01 Jan 2008 03:06:59 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/2007/12/31/same-method-different-speed/</guid>
		<description><![CDATA[I came across something rather interesting the other day when trying to determine what sorting algorithms .Net Framework uses in its list class: The built-in&#160; sorting method runs much faster than the reverse-engineered and then compiled code, even though in theory the code being executed is identical.Using Lutz Roeder&#8217;s .Net Reflector, I was able to [...]]]></description>
			<content:encoded><![CDATA[<p>I came across something rather interesting the other day when trying to determine what sorting algorithms .Net Framework uses in its list class: The built-in&nbsp; sorting method runs much faster than the reverse-engineered and then compiled code, even though in theory the code being executed is identical.<span id="more-258"></span>Using <a href="http://www.aisto.com/roeder/dotnet">Lutz Roeder&#8217;s .Net Reflector</a>, I was able to determine that QuickSort is used when List.Sort() is called.</p>
<p>Here is the generic QuickSort (I have left out some error handling portion) method that .Net 2.0 uses within it&#8217;s framework:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 50%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div>&nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">internal</span> <span style="color: blue; font-weight: bold;">class</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">ArraySortHelper</span><span style="color: navy;">&lt;</span>T<span style="color: navy;">&gt;</span></div>
<div>&nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">private</span> <span style="color: blue; font-weight: bold;">void</span> QuickSort<span style="color: navy;">&lt;</span>TValue<span style="color: navy;">&gt;</span>(T[] keys, TValue[] values, <span style="color: blue; font-weight: bold;">int</span> left, <span style="color: blue; font-weight: bold;">int</span> right, <span style="color: rgb(43, 145, 175); font-weight: bold;">IComparer</span><span style="color: navy;">&lt;</span>T<span style="color: navy;">&gt;</span> comparer)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">do</span></div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">int</span> index <span style="color: navy;">=</span> left;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">int</span> num2 <span style="color: navy;">=</span> right;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; T y <span style="color: navy;">=</span> keys[index <span style="color: navy;">+</span> ((num2 <span style="color: navy;">-</span> index) <span style="color: navy;">&gt;&gt;</span> <span style="color: teal;">1</span>)];</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">do</span></div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">while</span> (comparer<span style="color: navy;">.</span>Compare(keys[index], y) <span style="color: navy;">&lt;</span> <span style="color: teal;">0</span>)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; index<span style="color: navy;">++</span>;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">while</span> (comparer<span style="color: navy;">.</span>Compare(y, keys[num2]) <span style="color: navy;">&lt;</span> <span style="color: teal;">0</span>)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; num2<span style="color: navy;">&#8211;</span>;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (index <span style="color: navy;">&gt;</span> num2)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">break</span>;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (index <span style="color: navy;">&lt;</span> num2)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; T local2 <span style="color: navy;">=</span> keys[index];</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; keys[index] <span style="color: navy;">=</span> keys[num2];</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; keys[num2] <span style="color: navy;">=</span> local2;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (values <span style="color: navy;">!=</span> <span style="color: blue; font-weight: bold;">null</span>)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; TValue local3 <span style="color: navy;">=</span> values[index];</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; values[index] <span style="color: navy;">=</span> values[num2];</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; values[num2] <span style="color: navy;">=</span> local3;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; index<span style="color: navy;">++</span>;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; num2<span style="color: navy;">&#8211;</span>;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">while</span> (index <span style="color: navy;">&lt;=</span> num2);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> ((num2 <span style="color: navy;">-</span> left) <span style="color: navy;">&lt;=</span> (right <span style="color: navy;">-</span> index))</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (left <span style="color: navy;">&lt;</span> num2)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">this</span><span style="color: navy;">.</span>QuickSort<span style="color: navy;">&lt;</span>TValue<span style="color: navy;">&gt;</span>(keys, values, left, num2, comparer);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; left <span style="color: navy;">=</span> index;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (index <span style="color: navy;">&lt;</span> right)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">this</span><span style="color: navy;">.</span>QuickSort<span style="color: navy;">&lt;</span>TValue<span style="color: navy;">&gt;</span>(keys, values, index, right, comparer);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; right <span style="color: navy;">=</span> num2;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">while</span> (left <span style="color: navy;">&lt;</span> right);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> Sort(T[] items, <span style="color: blue; font-weight: bold;">int</span> index, <span style="color: blue; font-weight: bold;">int</span> length, <span style="color: rgb(43, 145, 175); font-weight: bold;">IComparer</span><span style="color: navy;">&lt;</span>T<span style="color: navy;">&gt;</span> comparer)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">this</span><span style="color: navy;">.</span>Sort<span style="color: navy;">&lt;</span><span style="color: blue; font-weight: bold;">object</span><span style="color: navy;">&gt;</span>(items, <span style="color: blue; font-weight: bold;">null</span>, index, length, comparer);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">virtual</span> <span style="color: blue; font-weight: bold;">void</span> Sort<span style="color: navy;">&lt;</span>TValue<span style="color: navy;">&gt;</span>(T[] keys, TValue[] values, <span style="color: blue; font-weight: bold;">int</span> index, <span style="color: blue; font-weight: bold;">int</span> length, <span style="color: rgb(43, 145, 175); font-weight: bold;">IComparer</span><span style="color: navy;">&lt;</span>T<span style="color: navy;">&gt;</span> comparer)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> ((comparer <span style="color: navy;">==</span> <span style="color: blue; font-weight: bold;">null</span>) <span style="color: navy;">||</span> (comparer <span style="color: navy;">==</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Comparer</span><span style="color: navy;">&lt;</span>T<span style="color: navy;">&gt;.</span>Default))</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; comparer <span style="color: navy;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Comparer</span><span style="color: navy;">&lt;</span>T<span style="color: navy;">&gt;.</span>Default;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">this</span><span style="color: navy;">.</span>QuickSort<span style="color: navy;">&lt;</span>TValue<span style="color: navy;">&gt;</span>(keys, values, index, index <span style="color: navy;">+</span> (length <span style="color: navy;">-</span> <span style="color: teal;">1</span>), comparer);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; }</div>
</div>
<p>&nbsp;</p>
<p>Out of curiosity, I ran the following methods to determine the approximate time required when sorting 2,000,000 random numbers:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 50%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div>&nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">class</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Program</span></div>
<div>&nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> Test1()</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: navy;">&lt;</span><span style="color: blue; font-weight: bold;">int</span><span style="color: navy;">&gt;</span> l <span style="color: navy;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: navy;">&lt;</span><span style="color: blue; font-weight: bold;">int</span><span style="color: navy;">&gt;</span>();</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Random</span> r <span style="color: navy;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Random</span>();</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> (<span style="color: blue; font-weight: bold;">int</span> i <span style="color: navy;">=</span> <span style="color: teal;">0</span>; i <span style="color: navy;">&lt;</span> <span style="color: teal;">20000000</span>; i<span style="color: navy;">++</span>)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: navy;">.</span>Add(r<span style="color: navy;">.</span>Next());</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">DateTime</span> t1 <span style="color: navy;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">DateTime</span><span style="color: navy;">.</span>Now;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: navy;">.</span>Write(<span style="color: rgb(163, 21, 21);">&quot;1&#8230;&quot;</span>);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: navy;">.</span>Sort();</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TimeSpan</span> t <span style="color: navy;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">DateTime</span><span style="color: navy;">.</span>Now <span style="color: navy;">-</span> t1;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: navy;">.</span>WriteLine(<span style="color: blue; font-weight: bold;">string</span><span style="color: navy;">.</span>Format(<span style="color: rgb(163, 21, 21);">&quot;{0} seconds.&quot;</span> , t<span style="color: navy;">.</span>Seconds));</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> Test2()</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">int</span>[] n <span style="color: navy;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: blue; font-weight: bold;">int</span>[<span style="color: teal;">20000000</span>];</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Random</span> r <span style="color: navy;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Random</span>();</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> (<span style="color: blue; font-weight: bold;">int</span> i <span style="color: navy;">=</span> <span style="color: teal;">0</span>; i <span style="color: navy;">&lt;</span> <span style="color: teal;">20000000</span>; i<span style="color: navy;">++</span>)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; n[i] <span style="color: navy;">=</span> r<span style="color: navy;">.</span>Next();</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">ArraySortHelper</span><span style="color: navy;">&lt;</span><span style="color: blue; font-weight: bold;">int</span><span style="color: navy;">&gt;</span> qSort <span style="color: navy;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">ArraySortHelper</span><span style="color: navy;">&lt;</span><span style="color: blue; font-weight: bold;">int</span><span style="color: navy;">&gt;</span>();</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">DateTime</span> t1 <span style="color: navy;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">DateTime</span><span style="color: navy;">.</span>Now;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: navy;">.</span>Write(<span style="color: rgb(163, 21, 21);">&quot;2&#8230;&quot;</span>);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; qSort<span style="color: navy;">.</span>Sort(n, <span style="color: teal;">0</span>, n<span style="color: navy;">.</span>Length <span style="color: navy;">-</span> <span style="color: teal;">1</span>, <span style="color: blue; font-weight: bold;">null</span>);</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TimeSpan</span> t <span style="color: navy;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">DateTime</span><span style="color: navy;">.</span>Now <span style="color: navy;">-</span> t1;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: navy;">.</span>WriteLine(<span style="color: blue; font-weight: bold;">string</span><span style="color: navy;">.</span>Format(<span style="color: rgb(163, 21, 21);">&quot;{0} seconds.&quot;</span>, t<span style="color: navy;">.</span>Seconds));</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">static</span> <span style="color: blue; font-weight: bold;">void</span> Main(<span style="color: blue; font-weight: bold;">string</span>[] args)</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Program</span> p <span style="color: navy;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Program</span>();</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; p<span style="color: navy;">.</span>Test1();</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; p<span style="color: navy;">.</span>Test2();</div>
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp; }</div>
</div>
<p>In the code above, Test1() calls the Sort() method within List class and Test2() calls the revere-engineered QuickSort() directly. The code is compiled with csc /o+ so that it is optimized. The result is rather interesting: Test1() used a bit more than 3 seconds to complete but Test2() used more than 9 second to complete! Even though in theory Test2() and Test1() should be approximately identical in terms of performance since they both invoke the same underlying QuickSort() method. The only explanation I have is that Microsoft has optimized its Framework code more than the framework itself can achieve (e.g. using some advanced tools that are only available to Microsoft).</p>
<p>If the above code is run under <a href="http://www.mono-project.com/">Mono</a>, the result is exact the opposite: Test2() runs almost twice as fast as Test1(), finishing in roughly 10 seconds (Mono runs the same .Net code much slower than Microsoft&#8217;s implementation). My guess is that since Mono developers develop their framework code independently, the sorting algorithm used in Mono might be slightly less efficient than Microsoft&#8217;s version of QuickSort(), so there is no surprise there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2007/12/31/same-method-different-speed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generating Unique Permutations Programmatically</title>
		<link>http://www.kerrywong.com/2006/04/14/generating-unique-permutations-programmatically/</link>
		<comments>http://www.kerrywong.com/2006/04/14/generating-unique-permutations-programmatically/#comments</comments>
		<pubDate>Fri, 14 Apr 2006 15:23:15 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[Unique Permutation]]></category>

		<guid isPermaLink="false">http://dimension/2006/04/14/generating-unique-permutations-programmatically/</guid>
		<description><![CDATA[Download UniquePermutation.zip The numbers of permutations on a set of n elements is n! (see definition). or example permutations of the word &#8220;ask&#8221; are: ask, aks, sak, ska, kas, ksa We often need to obtain unique permutations over a given set programmatically. Take the word &#8220;good&#8221; for example, the unique permutations are: good, godo, gdoo, [...]]]></description>
			<content:encoded><![CDATA[<p>Download <a href="/blog/wp-content/uploads/2007/09/uniquepermutation.zip" title="UniquePermutation.zip">UniquePermutation.zip</a>  The numbers of permutations on a set of n elements is <strong>n!</strong> (see <a href="http://mathworld.wolfram.com/Permutation.html">definition</a>).<span id="more-76"></span>  or example permutations of the word &ldquo;ask&rdquo; are:</p>
<blockquote dir="ltr" style="margin-right: 0px;">
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: Verdana;"><font color="#000000"><font color="#a52a2a">ask, aks, sak, ska, kas, ksa<o:p></o:p></font></font></span></p>
</blockquote>
<p>We often need to obtain unique permutations over a given set programmatically. Take the word &ldquo;good&rdquo; for example, the unique permutations are:</p>
<blockquote dir="ltr" style="margin-right: 0px;">
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: Verdana;"><font color="#000000"><font color="#a52a2a">good, godo, gdoo, ogod, ogdo, oogd, oodg, odgo, odog, dgoo, dogo, doog<o:p></o:p></font></font></span></p>
</blockquote>
<p>And we can prove mathematically that the total number of the permutations is :<span style="position: relative; top: 24pt;"><v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"> <v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></v:path><o:lock aspectratio="t" v:ext="edit"></o:lock></v:shapetype></span><span> </span></p>
<p align="center"><a href="/blog/wp-content/uploads/2007/09/uniquepermutation.GIF" title="Unique Permutation Calculation"><img src="/blog/wp-content/uploads/2007/09/uniquepermutation.GIF" alt="Unique Permutation Calculation" /></a></p>
<p align="left">&nbsp;</p>
<p>where <strong>n</strong> is the length of the sequence and <strong>m</strong> is the number of a non-unique letter. In the example given above, <strong>n = 4</strong> and <strong>i = 1</strong> (only one letter &ldquo;o&rdquo; is non-unique and it has two o&rsquo;s, so <strong>m = 2</strong> and <strong>4!/2! = 12</strong>.  The following is the C# code I wrote to achieve this:</p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p><font color="#000000"><font size="3" face="Times New Roman"> </font></font></o:p></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">    </font></span><font color="#000000"><strong><span style="color: blue;">class</span></strong> <span style="color: teal;">Program</span> {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><font color="#000000"><strong><span style="color: blue;">public</span></strong> <span style="color: teal;">ArrayList</span> Unique(<strong><span style="color: blue;">string</span></strong> s) {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">char</span></strong>[] c <span style="color: gray;">=</span> s<span style="color: gray;">.</span>ToCharArray();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000">ArrayList</font></span><font color="#000000"> ayList <span style="color: gray;">=</span> <strong><span style="color: blue;">new</span></strong> <span style="color: teal;">ArrayList</span>();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">for</span></strong> (<strong><span style="color: blue;">int</span></strong> i <span style="color: gray;">=</span> <span style="color: fuchsia;">0</span>; i <span style="color: gray;">&lt;</span> c<span style="color: gray;">.</span>Length; i<span style="color: gray;">++</span>)<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><font color="#000000"><strong><span style="color: blue;">if</span></strong> (<span style="color: gray;">!</span>ayList<span style="color: gray;">.</span>Contains(c[i])) ayList<span style="color: gray;">.</span>Add(c[i]);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">return</span></strong> ayList;<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><font color="#000000"><strong><span style="color: blue;">public</span></strong> <span style="color: teal;">ArrayList</span> Permute(<strong><span style="color: blue;">string</span></strong> s) {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000">ArrayList</font></span><font color="#000000"> tmpList <span style="color: gray;">=</span> <strong><span style="color: blue;">new</span></strong> <span style="color: teal;">ArrayList</span>();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">    </font></span><span><font color="#000000">        </font></span><span style="color: teal;"><font color="#000000">ArrayList</font></span><font color="#000000"> permList <span style="color: gray;">=</span> <strong><span style="color: blue;">new</span></strong> <span style="color: teal;">ArrayList</span>();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">if</span></strong> (s<span style="color: gray;">.</span>Length <span style="color: gray;">==</span> <span style="color: fuchsia;">1</span>) {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><font color="#000000"><strong><span style="color: blue;">if</span></strong> (<span style="color: gray;">!</span>permList<span style="color: gray;">.</span>Contains(s)) permList<span style="color: gray;">.</span>Add(s);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><font color="#000000"><strong><span style="color: blue;">return</span></strong> permList;<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000">} <strong><span style="color: blue;">else</span></strong> {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><span style="color: teal;"><font color="#000000">ArrayList</font></span><font color="#000000"> list <span style="color: gray;">=</span> Unique(s);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><font color="#000000"><strong><span style="color: blue;">foreach</span></strong> (<strong><span style="color: blue;">char</span></strong> c <strong><span style="color: blue;">in</span></strong> list) {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                    </font></span><font color="#000000"><strong><span style="color: blue;">for</span></strong> (<strong><span style="color: blue;">int</span></strong> i <span style="color: gray;">=</span> <span style="color: fuchsia;">0</span>; i <span style="color: gray;">&lt;</span> s<span style="color: gray;">.</span>Length; i<span style="color: gray;">++</span>) {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                        </font></span><font color="#000000"><strong><span style="color: blue;">string</span></strong> tempS <span style="color: gray;">=</span> <strong><span style="color: blue;">string</span></strong><span style="color: gray;">.</span>Empty;<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                        </font></span><font color="#000000"><strong><span style="color: blue;">if</span></strong> (s<span style="color: gray;">.</span>Substring(i, <span style="color: fuchsia;">1</span>) <span style="color: gray;">==</span> c<span style="color: gray;">.</span>ToString())<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                            </font></span><font color="#000000">tempS <span style="color: gray;">=</span> s<span style="color: gray;">.</span>Remove(i, <span style="color: fuchsia;">1</span>);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">     </font></span><span><font color="#000000">                   </font></span><font color="#000000"><strong><span style="color: blue;">else</span></strong><span style="color: blue;"><o:p></o:p></span></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                            </font></span><font color="#000000"><strong><span style="color: blue;">continue</span></strong>;<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                        </font></span><font color="#000000">tmpList <span style="color: gray;">=</span> Permute(tempS);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                        </font></span><font color="#000000"><strong><span style="color: blue;">foreach</span></strong> (<strong><span style="color: blue;">string</span></strong> t <strong><span style="color: blue;">in</span></strong> tmpList) {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                            </font></span><font color="#000000"><strong><span style="color: blue;">if</span></strong> (<span style="color: gray;">!</span>permList<span style="color: gray;">.</span>Contains(c<span style="color: gray;">.</span>ToString() <span style="color: gray;">+</span> t))<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                 </font></span><span><font color="#000000">               </font></span><font color="#000000">permList<span style="color: gray;">.</span>Add(c<span style="color: gray;">.</span>ToString() <span style="color: gray;">+</span> t);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                        </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                    </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">return</span></strong> permList;<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><font color="#000000"><strong><span style="color: blue;">static</span></strong> <strong><span style="color: blue;">void</span></strong> <st1:place w:st="on">Main</st1:place>(<strong><span style="color: blue;">string</span></strong>[] args) {<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000">Program</font></span><font color="#000000"> p <span style="color: gray;">=</span> <strong><span style="color: blue;">new</span></strong> <span style="color: teal;">Program</span>();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">      </font></span><span><font color="#000000">      </font></span><span style="color: teal;"><font color="#000000">ArrayList</font></span><font color="#000000"> ayList <span style="color: gray;">=</span> p<span style="color: gray;">.</span>Permute(<span style="color: red;">&quot;good&quot;</span>);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">foreach</span></strong> (<strong><span style="color: blue;">string</span></strong> s <strong><span style="color: blue;">in</span></strong> ayList) <span style="color: teal;">Console</span><span style="color: gray;">.</span>WriteLine(s);<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000">Console</font></span><span style="color: gray;"><font color="#000000">.</font></span><font color="#000000">WriteLine();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000">Console</font></span><span style="color: gray;"><font color="#000000">.</font></span><font color="#000000">ReadKey();<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">    </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p class="MsoNormal" style="margin: 0in 0in 0pt;"><o:p><font color="#000000"><font size="3" face="Times New Roman"> </font></font></o:p></p>
<p>The main routine is the function <strong>Permute</strong>(string s), it takes a string s and builds an array list of permutated strings recursively. Note the function <strong>Unique</strong>(string s), which takes a string and returns an array list of the unique characters in that string. The uniqueness of the permutation is guaranteed by the foreach loop over tmpList, where only the unique permutations are added to the permList.  The routine works pretty well for sequences lengths up to about eight. And because of the complexity grows exponentially, this algorithm is not suited for finding unique permutations over a large set.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2006/04/14/generating-unique-permutations-programmatically/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing a Trie in C#</title>
		<link>http://www.kerrywong.com/2006/04/01/implementing-a-trie-in-c/</link>
		<comments>http://www.kerrywong.com/2006/04/01/implementing-a-trie-in-c/#comments</comments>
		<pubDate>Sat, 01 Apr 2006 10:13:58 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://dimension/2006/04/01/implementing-a-trie-in-c/</guid>
		<description><![CDATA[Download Trie.zip Trie is a tree like data structure that can be used for fast text search. While there are a lot of examples on the internet, very few if any are written in C#. In this post, I would like to show a complete implementation in C#. In my implementation, the Trie nodes are [...]]]></description>
			<content:encoded><![CDATA[<p>Download <a title="Trie.zip" href="http://en.wikipedia.org/wiki/Trie">Trie.zip</a> <a href="http://en.wikipedia.org/wiki/Trie">Trie</a> is a tree like data structure that can be used for fast text search. <span id="more-72"></span>While there are a lot of examples on the internet, very few if any are written in C#. In this post, I would like to show a complete implementation in C#.  In my implementation, the Trie nodes are represented by an array of pointers. While it is not the most efficient way to do, it nevertheless gets the point through. An alternative and more efficient way to do would utilize a linked list in place of the array of pointers. The following figure illustrates how I implement the Trie structure.</p>
<p style="text-align: center;"><a title="Trie" href="/blog/wp-content/uploads/2007/09/trie1.gif"><img alt="Trie" src="/blog/wp-content/uploads/2007/09/trie1.gif" /></a></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal">Here is the code for the TrieNode class.</p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal">&nbsp;</p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">    </font></span><strong><span style="color: blue;">class</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">public</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000">[] nodes;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">public</span></strong><font color="#000000"> </font><strong><span style="color: blue;">bool</span></strong><font color="#000000"> isEnd </font><span style="color: gray;">=</span><font color="#000000"> </font><strong><span style="color: blue;">false</span></strong><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">public</span></strong><font color="#000000"> </font><strong><span style="color: blue;">const</span></strong><font color="#000000"> </font><strong><span style="color: blue;">int</span></strong><font color="#000000"> ASCIIA </font><span style="color: gray;">=</span><font color="#000000"> </font><span style="color: fuchsia;">97</span><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">public</span></strong><font color="#000000"> <span class="searchword">Trie</span>Node() {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>            </span>nodes </font><span style="color: gray;">=</span><font color="#000000"> </font><strong><span style="color: blue;">new</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000">[</font><span style="color: fuchsia;">26</span><font color="#000000">];<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>        </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">public</span></strong><font color="#000000"> </font><strong><span style="color: blue;">bool</span></strong><font color="#000000"> Contains(</font><strong><span style="color: blue;">char</span></strong><font color="#000000"> c)  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">int</span></strong><font color="#000000"> n </font><span style="color: gray;">=</span><font color="#000000"> </font><span style="color: teal;">Convert</span><span style="color: gray;">.</span><font color="#000000">ToByte(c) </font><span style="color: gray;">-</span><font color="#000000"> ASCIIA;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">if</span></strong><font color="#000000"> (n </font><span style="color: gray;">&lt;</span><font color="#000000"> </font><span style="color: fuchsia;">26</span><font color="#000000">)<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><strong><span style="color: blue;">return</span></strong><font color="#000000"> (nodes[n] </font><span style="color: gray;">!=</span><font color="#000000"> </font><strong><span style="color: blue;">null</span></strong><font color="#000000">);<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">else</span></strong><span style="color: blue;"><o:p></o:p></span></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><strong><span style="color: blue;">return</span></strong><font color="#000000"> </font><strong><span style="color: blue;">false</span></strong><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>        </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">public</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> GetChild(</font><strong><span style="color: blue;">char</span></strong><font color="#000000"> c) {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">int</span></strong><font color="#000000"> n </font><span style="color: gray;">=</span><font color="#000000"> </font><span style="color: teal;">Convert</span><span style="color: gray;">.</span><font color="#000000">ToByte(c) </font><span style="color: gray;">-</span><font color="#000000"> ASCIIA;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">return</span></strong><font color="#000000">  nodes[n];<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>        </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>    </span>}</font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal">&nbsp;</p>
<p>Whenever the TrieNode gets initialized, an array (representing 26 letters) of pointers is created. And Contains() method returns true if the corresponding node contains a reference (think of pointers) to a child. And finally, GetChild() function returns a child tree that is rooted at the character passed in. Note that the GetChild function only works level by level, e.g. for word &ldquo;boot&rdquo;, you will need to pass in the whole word and then scanning from left to right, and at each letter, you would call GetChild to get a tree that representing the current tree from that letter on. This makes intuitive sense, because if you do not call this function sequentially, how would you tell which &ldquo;o&rdquo; you are referring to? Take a look at the Tries class, and this concept should become clearer.</p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">    </font></span><strong><span style="color: blue;">class</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>s</span><font color="#000000"> {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">private</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> root </font><span style="color: gray;">=</span><font color="#000000"> </font><strong><span style="color: blue;">new</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000">();<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">public</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> Insert(</font><strong><span style="color: blue;">string</span></strong><font color="#000000"> s) {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">char</span></strong><font color="#000000">[] charArray </font><span style="color: gray;">=</span><font color="#000000"> s</font><span style="color: gray;">.</span><font color="#000000">ToLower()</font><span style="color: gray;">.</span><font color="#000000">ToCharArray();<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> node </font><span style="color: gray;">=</span><font color="#000000">  root;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">foreach</span></strong><font color="#000000"> (</font><strong><span style="color: blue;">char</span></strong><font color="#000000"> c </font><strong><span style="color: blue;">in</span></strong><font color="#000000"> charArray)  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>                </span>node </font><span style="color: gray;">=</span><font color="#000000"> Insert(c,  node);<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>            </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>            </span>node</font><span style="color: gray;">.</span><font color="#000000">isEnd </font><span style="color: gray;">=</span><font color="#000000"> </font><strong><span style="color: blue;">true</span></strong><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">return</span></strong><font color="#000000">  root;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>        </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">private</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> Insert(</font><strong><span style="color: blue;">char</span></strong><font color="#000000"> c, </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> node)  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">if</span></strong><font color="#000000"> (node</font><span style="color: gray;">.</span><font color="#000000">Contains(c)) </font><strong><span style="color: blue;">return</span></strong><font color="#000000"> node</font><span style="color: gray;">.</span><font color="#000000">GetChild(c);<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">else</span></strong><font color="#000000">  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><strong><span style="color: blue;">int</span></strong><font color="#000000"> n </font><span style="color: gray;">=</span><font color="#000000"> </font><span style="color: teal;">Convert</span><span style="color: gray;">.</span><font color="#000000">ToByte(c) </font><span style="color: gray;">-</span><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><span style="color: gray;">.</span><font color="#000000">ASCIIA;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> t </font><span style="color: gray;">=</span><font color="#000000"> </font><strong><span style="color: blue;">new</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000">();<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>                </span>node</font><span style="color: gray;">.</span><font color="#000000">nodes[n] </font><span style="color: gray;">=</span><font color="#000000"> t;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><strong><span style="color: blue;">return</span></strong><font color="#000000">  t;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>            </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>        </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">public</span></strong><font color="#000000"> </font><strong><span style="color: blue;">bool</span></strong><font color="#000000"> Contains(</font><strong><span style="color: blue;">string</span></strong><font color="#000000"> s)  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">char</span></strong><font color="#000000">[] charArray </font><span style="color: gray;">=</span><font color="#000000"> s</font><span style="color: gray;">.</span><font color="#000000">ToLower()</font><span style="color: gray;">.</span><font color="#000000">ToCharArray();<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> node </font><span style="color: gray;">=</span><font color="#000000">  root;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">bool</span></strong><font color="#000000"> contains </font><span style="color: gray;">=</span><font color="#000000"> </font><strong><span style="color: blue;">true</span></strong><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">foreach</span></strong><font color="#000000"> (</font><strong><span style="color: blue;">char</span></strong><font color="#000000"> c </font><strong><span style="color: blue;">in</span></strong><font color="#000000"> charArray)  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>                </span>node </font><span style="color: gray;">=</span><font color="#000000"> Contains(c,  node);<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><strong><span style="color: blue;">if</span></strong><font color="#000000"> (node </font><span style="color: gray;">==</span><font color="#000000"> </font><strong><span style="color: blue;">null</span></strong><font color="#000000">)  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>                    </span>contains </font><span style="color: gray;">=</span><font color="#000000"> </font><strong><span style="color: blue;">false</span></strong><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                    </font></span><strong><span style="color: blue;">break</span></strong><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>                </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>            </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">if</span></strong><font color="#000000"> ((node </font><span style="color: gray;">==</span><font color="#000000"> </font><strong><span style="color: blue;">null</span></strong><font color="#000000">) </font><span style="color: gray;">||</span><font color="#000000"> (</font><span style="color: gray;">!</span><font color="#000000">node</font><span style="color: gray;">.</span><font color="#000000">isEnd))<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>                </span>contains </font><span style="color: gray;">=</span><font color="#000000"> </font><strong><span style="color: blue;">false</span></strong><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">return</span></strong><font color="#000000">  contains;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>        </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><strong><span style="color: blue;">private</span></strong><font color="#000000"> </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> Contains(</font><strong><span style="color: blue;">char</span></strong><font color="#000000"> c, </font><span style="color: teal;"><span class="searchword">Trie</span>Node</span><font color="#000000"> node)  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><strong><span style="color: blue;">if</span></strong><font color="#000000"> (node</font><span style="color: gray;">.</span><font color="#000000">Contains(c))  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><strong><span style="color: blue;">return</span></strong><font color="#000000"> node</font><span style="color: gray;">.</span><font color="#000000">GetChild(c);<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>            </span>} </font><strong><span style="color: blue;">else</span></strong><font color="#000000">  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><strong><span style="color: blue;">return</span></strong><font color="#000000"> </font><strong><span style="color: blue;">null</span></strong><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>            </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>        </span>}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><span>    </span>}</font></span><span style="font-size: 10pt; font-family: Verdana;"><o:p></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal">&nbsp;</p>
<p>Now let&rsquo;s see how we would use our Trie class to check whether a given string is present from an input string.</p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000"><strong><span style="color: blue;">class</span></strong> <span style="color: teal;">Program</span>  {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><font color="#000000"><strong><span style="color: blue;">static</span></strong> <strong><span style="color: blue;">void</span></strong> <st1:place w:st="on">Main</st1:place>(<strong><span style="color: blue;">string</span></strong>[]  args) {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000"><span class="searchword">Trie</span>s</font></span><font color="#000000"> <span class="searchword">trie</span>s <span style="color: gray;">=</span> <strong><span style="color: blue;">new</span></strong> <span style="color: teal;"><span class="searchword">Trie</span>s</span>();<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000"><span class="searchword">Trie</span>Node</font></span><font color="#000000"> n;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">string</span></strong> s <span style="color: gray;">=</span> <span style="color: maroon;">@&quot;<o:p></o:p></span></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">In computer science, a <span class="searchword">trie</span>, or  prefix tree, <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">is an ordered tree data structure that is used to  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">store an associative array where the keys are strings.  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">Unlike a binary search tree, no node in the tree  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">stores the key associated with that node;  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">instead, its position in the tree shows what key  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">it is associated with. All the descendants  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">of any one node have a common prefix of the string  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">associated with that node, and the root is associated  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">with the empty string. Values are normally not associated  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">with every node, only with leaves and some inner nodes  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">that happen to correspond to keys of interest.  <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; color: maroon; font-family: 'Courier New';"><font color="#000000">&quot;</font></span><span style="font-size: 10pt; font-family: 'Courier New';"><font color="#000000">;<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000">s <span style="color: gray;">=</span> s<span style="color: gray;">.</span>Replace(<span style="color: red;">&quot;\r\n&quot;</span>, <span style="color: red;">&quot;&quot;</span>);<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">string</span></strong>[] ay <span style="color: gray;">=</span>  s<span style="color: gray;">.</span>Split(<span style="color: red;">&#8216; &#8216;</span>,  <span style="color: red;">&#8216;,&#8217;</span>, <span style="color: red;">&#8216;;&#8217;</span>, <span style="color: red;">&#8216;.&#8217;</span>);<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p><font color="#000000"> </font></o:p></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000"><strong><span style="color: blue;">foreach</span></strong> (<strong><span style="color: blue;">string</span></strong> str <strong><span style="color: blue;">in</span></strong> ay) {<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                </font></span><font color="#000000"><strong><span style="color: blue;">if</span></strong> (str <span style="color: gray;">!=</span> <span style="color: red;">&quot;&quot;</span>)<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">                    </font></span><font color="#000000">n <span style="color: gray;">=</span> <span class="searchword">trie</span>s<span style="color: gray;">.</span>Insert(str);<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000">Console</font></span><span style="color: gray;"><font color="#000000">.</font></span><font color="#000000">WriteLine(<span class="searchword">trie</span>s<span style="color: gray;">.</span>Contains(<span style="color: red;">&quot;prefix&quot;</span>)); <o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000">Console</font></span><span style="color: gray;"><font color="#000000">.</font></span><font color="#000000">WriteLine(<span class="searchword">trie</span>s<span style="color: gray;">.</span>Contains(<span style="color: red;">&quot;come&quot;</span>));<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">            </font></span><span style="color: teal;"><font color="#000000">Console</font></span><span style="color: gray;"><font color="#000000">.</font></span><font color="#000000">ReadKey();<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">        </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p style="margin: 0in 0in 0pt;" class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><span><font color="#000000">    </font></span><font color="#000000">}<o:p></o:p></font></span></p>
<p align="left" style="margin: 0in 0in 0pt;" class="MsoNormal">&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2006/04/01/implementing-a-trie-in-c/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Three Ways to Reverse a String in C# &#8211; Update</title>
		<link>http://www.kerrywong.com/2006/03/11/three-ways-to-reverse-a-string-in-c-update/</link>
		<comments>http://www.kerrywong.com/2006/03/11/three-ways-to-reverse-a-string-in-c-update/#comments</comments>
		<pubDate>Sat, 11 Mar 2006 10:11:32 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://dimension/2007/03/11/three-ways-to-reverse-a-string-in-c-update/</guid>
		<description><![CDATA[In my post a week ago, I mentioned three ways to reverse a string. OK, I really meant three alternative ways to reverse a string. And the post was done from an algorithmic stand point of view. I guess in the real world, you can achieve this in just three lines of code: public string [...]]]></description>
			<content:encoded><![CDATA[<p class="itemBody">In my <a href="/2006/03/04/three-ways-to-reverse-a-string-in-c/">post</a> a week ago, I mentioned three ways to reverse a string. OK, I really meant three alternative ways to reverse a string.<span id="more-68"></span> And the post was done from an algorithmic stand point of view. I guess in the real world, you can achieve this in just three lines of code:</p>
<blockquote style="margin-right: 0px;" dir="ltr"><p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent;"><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">public</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">string</span> Reverse(<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">string</span> s) { <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">   char</span>[] c <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> s.ToCharArray(); Array.Reverse(c); <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">   return</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">new</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">string</span>(c); }</span></p></blockquote>
<p>But I think that from an interviewer&#8217;s perspective, the previous <a href="/2006/03/04/three-ways-to-reverse-a-string-in-c/">three approaches </a>would definitely do better&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2006/03/11/three-ways-to-reverse-a-string-in-c-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Three Ways to Reverse a String in C#</title>
		<link>http://www.kerrywong.com/2006/03/04/three-ways-to-reverse-a-string-in-c/</link>
		<comments>http://www.kerrywong.com/2006/03/04/three-ways-to-reverse-a-string-in-c/#comments</comments>
		<pubDate>Sat, 04 Mar 2006 15:09:02 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://dimension/2006/03/04/three-ways-to-reverse-a-string-in-c/</guid>
		<description><![CDATA[OK, conceptually, it&#8217;s quite easy. A couple of my friends got asked this question when interviewing. Here are what my solutions are: 1. The trivial way This is the probably the most trivial version: public string Reverse1(string s) {    char[] c = s.ToCharArray();    string ts = string.Empty;    for (int i = c.Length - 1; i [...]]]></description>
			<content:encoded><![CDATA[<p class="itemBody">OK, conceptually, it&#8217;s quite easy. A couple of my friends got asked this question when interviewing. Here are what my solutions are:<span id="more-66"></span></p>
<p><strong>1. The trivial way</strong></p>
<p>This is the probably the most trivial version:</p>
<blockquote dir="ltr" style="margin-right: 0px"><p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent"><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">public</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span> Reverse1(<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span> s)<br />
{<br />
<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   char</span>[] c <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">=</span> s.ToCharArray();<br />
<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   string</span> ts <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">=</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span>.Empty;</p>
<p><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   for</span> (<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">int</span> i <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">=</span> c.Length <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">-</span> 1; i &gt;= 0; i&#8211;)<br />
ts += c[i].ToString();</p>
<p><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   return</span> ts;<br />
}</span></p></blockquote>
<p><strong>2. Using a stack</strong></p>
<p>This method is essentially the same as the first one, however it uses the FILO nature of the stack to accomplish the same task.</p>
<p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent"></p>
<blockquote dir="ltr" style="margin-right: 0px"><p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent"><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">public</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span> Reverse(<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span> s)<br />
{<br />
Stack&lt;<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span>&gt; stack <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">=</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">new</span> Stack&lt;<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span>&gt;();</p>
<p><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   for</span> (<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">int</span> i <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">=</span> 0; i &lt; s.Length; i++)<br />
stack.Push(s.Substring(i, 1));</p>
<p><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   string</span> ts <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">=</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span>.Empty;<br />
<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   for</span> (<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">int</span> i <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">=</span> 0; i &lt; s.Length; i++)<br />
ts += stack.Pop();</p>
<p><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   return</span> ts;<br />
}</span></p></blockquote>
<p></span><strong>3. Using recursion (The cool way)</strong></p>
<p>This version is probably the coolest and might just be what your interviewer was looking for. It actually does not need extra storage (it uses the stack but you do not need to programmatically allocate space in your code like the previous two cases).</p>
<p>Here&#8217;s the how you would use the Reverse method:</p>
<blockquote dir="ltr" style="margin-right: 0px"><p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent"><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">public</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span> Reverse(<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span> s, <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">int</span> l)<br />
{<br />
<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   if</span> (l == 1)<br />
<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">      return</span> s;<br />
<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">   else</span><br />
<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">      return</span> Reverse(s.Substring(1, s.Length <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">-</span> 1), &#8211;l) <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">+</span> s[0].ToString();<br />
}</span></p></blockquote>
<p dir="ltr"><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent"><font color="#003300" face="Verdana" size="2">Here&#8217;s the how you would use the Reverse method:</font></span></p>
<blockquote dir="ltr" style="margin-right: 0px"><p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent"><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent">string</span> s <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent">=</span> <span style="font-size: 11px; color: #666666; font-family: Courier New; background-color: #e4e4e4">&#8220;ABCDEFGHIJK&#8221;</span>;<br />
Console.WriteLine(Reverse(s, s.Length));</span></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2006/03/04/three-ways-to-reverse-a-string-in-c/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Performance Comparison: Rectangular Array vs. Jagged Array (Update)</title>
		<link>http://www.kerrywong.com/2005/10/26/performance-comparison-rectangular-array-vs-jagged-array-update/</link>
		<comments>http://www.kerrywong.com/2005/10/26/performance-comparison-rectangular-array-vs-jagged-array-update/#comments</comments>
		<pubDate>Wed, 26 Oct 2005 10:32:55 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://dimension/2005/10/26/performance-comparison-rectangular-array-vs-jagged-array-update/</guid>
		<description><![CDATA[As I mentioned earlier (see Performance Comparison: Rectangular Array vs. Jagged Array) I ran the same set of tests in .Net framework 2.0 (Beta 2) and the results are still pretty similar to that in 1.0. I would suspect that the test results be similar in the final product of .Net 2.0. While I mentioned [...]]]></description>
			<content:encoded><![CDATA[<p>As I mentioned earlier (see <a href="/2005/10/06/performance-comparison-rectangular-array-vs-jagged-array/">Performance Comparison: Rectangular Array vs. Jagged Array</a>) I ran the same set of tests in .Net framework 2.0 (Beta 2) and the results are still pretty similar to that in 1.0. I would suspect that the test results be similar in the final product of .Net 2.0.<span id="more-41"></span></p>
<p>While I mentioned that the performance of the jagged array is better than rectangular array, I guess we need to put this conclusion in context. That is, if you are mostly doing sequential access to the arrays.</p>
<p>An article on MSDN magazine (see <a href="http://msdn.microsoft.com/msdnmag/issues/04/03/ScientificC/">Harness the Features of C# to Power Your Scientific Computing Projects</a>) suggests that the performance of jagged array actually degrades significantly when accessed randomly. A scenario that would fit this case is the operation of sparse matrices.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2005/10/26/performance-comparison-rectangular-array-vs-jagged-array-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Performance Comparison: Rectangular Array vs. Jagged Array</title>
		<link>http://www.kerrywong.com/2005/10/06/performance-comparison-rectangular-array-vs-jagged-array/</link>
		<comments>http://www.kerrywong.com/2005/10/06/performance-comparison-rectangular-array-vs-jagged-array/#comments</comments>
		<pubDate>Thu, 06 Oct 2005 11:05:23 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://dimension/2005/10/06/performance-comparison-rectangular-array-vs-jagged-array/</guid>
		<description><![CDATA[Jagged arrays (e.g. a[i][j]) are named such so because it is an array of array. Because each dimension within an array can be different for different indices, jagged arrays can be much more efficient in terms of the memory usage in certain scenarios such as sparse matrices manipulation when compared to rectangular arrays. But the [...]]]></description>
			<content:encoded><![CDATA[<p>Jagged arrays (e.g. a[i][j]) are named such so because it is an array of array. <span id="more-34"></span>Because each dimension within an array can be different for different indices, jagged arrays can be much more efficient in terms of the memory usage in certain scenarios such as sparse matrices manipulation when compared to rectangular arrays. But the perception of the rectangular array (a continuous block of memory) has somehow suggested its superior performance comparing to a jagged array.</p>
<p>This, however, is not true within the .Net Framework (the analysis herein is based on .Net Framework 1.1). And synthetic tests suggest that we should use jagged arrays whenever it is possible, since it is always superior to it&rsquo;s counterpart in almost every way (both speed and memory usage). Even when used as a full rectangular array, jagged arrays still have some performance advantages to rectangular array.  Here is a concrete test I did.</p>
<p>In order to measure the performance of each of the methods, we created an array of 40000000 elements. And we measure how fast it is to populate these two arrays.</p>
<blockquote dir="ltr" style="margin-right: 0px;"><p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent;"><span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">const</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">long</span> dimension <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> 2000;  <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">void</span> jagged() { <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">double</span>[][] a; a <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">new</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">double</span>[dimension][]; <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">for</span> (<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">int</span> i <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> 0 ; i &lt; dimension ; i ++) a[i] <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">new</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">double</span>[dimension];  <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">for</span> (<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">int</span> i <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> 0 ; i &lt; dimension; i ++) <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">for</span> (<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">int</span> j <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> 0 ; j &lt; dimension ; j++) a[i][j] <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> i*j; }  <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">void</span> rectangular() { <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">double</span>[,] a <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">new</span> <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">double</span>[dimension,dimension]; <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">for</span> (<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">int</span> i <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> 0 ; i &lt; dimension; i ++) <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">for</span> (<span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">int</span> j <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> 0 ; j &lt; dimension ; j++) a[i,j] <span style="font-size: 11px; color: red; font-family: Courier New; background-color: transparent;">=</span> i*j; }  </span></p></blockquote>
<p>The result shows that the jagged array performed roughly 12% better then the rectangular array. It took 56 ms to execute the jagged() while it took 63 ms to execute rectangular(). I will explain how the time is measured in some later blogs.  So, why is jagged array more efficiently in .Net? Maybe we can find out some clues from the ILs the code generates.</p>
<p>&nbsp;</p>
<p align="left">&nbsp;</p>
<p style="text-align: center;"><a><img src="/blog/wp-content/uploads/2007/09/rect1.jpg" alt="Rectangular Array" /></a></p>
<p>&nbsp;</p>
<p align="center"><a href="/blog/wp-content/uploads/2007/09/jagged.jpg" title="Jagged Array"><img src="/blog/wp-content/uploads/2007/09/jagged.jpg" alt="Jagged Array" /></a></p>
<p align="left">&nbsp;</p>
<p>It seesms that we have found our answer. In the ILDASM screen for the rectangular array method, we saw that the two dimensional array was treated as a whole object:</p>
<blockquote dir="ltr" style="margin-right: 0px;"><p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent;">IL_000e: newobj instance <span style="font-size: 11px; color: blue; font-family: Courier New; background-color: transparent;">void</span> float64[0...,0...]::.ctor(int32, int32) </span></p></blockquote>
<p>Whereas in the IL generated for the jagged array method, the array is treated differently:</p>
<blockquote dir="ltr" style="margin-right: 0px;"><p><span style="font-size: 11px; color: black; font-family: Courier New; background-color: transparent;">IL_0007: newarr float64[] IL_001a: newarr [mscorlib]System.Double </span></p></blockquote>
<p>And I suspect that that&rsquo;s where the efficiency comes from.  The conclusion is, jagged array performs superior than rectangular array in .Net framework 1.1 (I will perform some analysis in 2.0 later), so we should use jagged array instead of rectangular arrays whenever we can.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2005/10/06/performance-comparison-rectangular-array-vs-jagged-array/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
