Quantcast
Channel: Randy Riness @ SPSCC aggregator
Viewing all articles
Browse latest Browse all 3015

MSDN Blogs: Visual Sorting Algorithms part II

$
0
0

In the days before the internet, email and cell phones:

My ice hockey team was in the locker room talking about skating when the topic of a video showing me roller staking in Boston in 1980.

https://www.youtube.com/watch?v=IxlV_lOLmrk

see Visual Sorting Part I

Below is the new version that uses a background thread to do the work and allows multiple length data.

In this screenshot is the QuickSort running across 3 monitors was interrupted when about halfway done. The top half has already been sorted (no bolded items)

clip_image001

I wrote some simple tests to verify the algorithms worked and output the performance results to an Excel pivot chart

The multiple sorting algorithms have huge performance differences. The better performing tests were skewed toward the ones with the fewest screen updates, so the test code can change the visibility of the items when run.

It’s interesting that several of the algorithms were invented since my first implementation in the 1980’s

Start Visual Studio. (most versions)

File->New->Project->c#->Windows->WPF Application

replace the Mainwindow.Xaml.cs code with the code below

clip_image002

<SortingCode>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace WpfApplication1
{
    publicpartialclassMainWindow : Window
    {
        publicstaticstring[] _SortTypes =
        {
            "Bubble",
            "Unknown",
            "Stupid",
            "Insertion",
            "Selection",
            "OddEven",
            "Cycle",
            "Merge",
            "MergeIP",
            "MergeIP2",
            "Quick",
            "Shell",
            "Heap",
            "Super",
        };
        public MainWindow()
        {
            InitializeComponent();
            this.WindowState = WindowState.Maximized;
            this.Title = "Visual Sorter";
            this.Loaded += MainWindow_Loaded;
        }
        publicstaticCancellationTokenSource _cancelTokSrc;
        publicstaticbool _ShowSort = true;
        internalCanvas _canvas = newCanvas();
        publicstaticint _spControlsHeight = 60;
        publicint _nRows;

        publicclassSortBox : Label, IComparable
        {
            publicstructStats
            {
                publicDateTime startTime;
                publicint numItems;
                publiclong numCompares;
                publiclong numReads;
                publiclong numWrites;
                publicint MaxDepth;
                publicoverridestring ToString()
                {
                    var elapsed = (DateTime.Now - startTime).TotalSeconds;
                    var strDepth = string.Empty;
                    if (MaxDepth >= 0)
                    {
                        strDepth = $" MaxDepth= {MaxDepth}";
                    }
                    return$"Secs= {elapsed,9:n3} Items= {numItems,8} Compares= {numCompares,13:n0} Reads= {numReads,13:n0} Writes= {numWrites,13:n0}{strDepth}";
                }
            }
            publicstaticStats stats;
            internalstaticvoid InitStats(int nTotal)
            {
                stats = newStats()
                {
                    numItems = nTotal,
                    startTime = DateTime.Now,
                    MaxDepth = -1
                };
            }

            public SortBox()
            {
                //                this.FontSize = 8;
            }
            publicvoid Swap(SortBox other)
            {
                if (this != other)
                {
                    var temp = this.Data;
                    this.Data = other.Data;
                    other.Data = temp;
                }
            }
            privatestring _data;
            publicstring Data
            {
                get
                {
                    stats.numReads++;
                    return _data;
                }
                set
                {
                    _data = value;
                    stats.numWrites++;
                    this.Update();
                }
            }
            publicstaticbooloperator<(SortBox a, SortBox b)
            {
                stats.numCompares++;
                if (string.CompareOrdinal(a.Data, b.Data) < 0)
                {
                    returntrue;
                }
                returnfalse;
            }
            publicstaticbooloperator>(SortBox a, SortBox b)
            {
                stats.numCompares++;
                if (string.CompareOrdinal(a.Data, b.Data) > 0)
                {
                    returntrue;
                }
                returnfalse;
            }
            publicvoid Update()
            {
                if (_ShowSort)
                {
                    bool fCancel = false;
                    Dispatcher.Invoke(() =>
                    {
                        // set the content on the UI threadthis.Content = this.Data;
                        if (_cancelTokSrc != null)
                        {
                            // check input queue for messagesvar stat = GetQueueStatus(4);
                            if (stat != 0)
                            {
                                //need to throw on right thread
                                fCancel = true;
                            }
                        }
                    });
                    if (fCancel)
                    {
                        //need to throw on right thread
                        _cancelTokSrc.Cancel();
                        thrownewTaskCanceledException("User cancelled");
                    }
                }
            }
            publicoverridestring ToString()
            {
                return$"{this.Data}";
            }

            publicint CompareTo(object obj)
            {
                stats.numCompares++;
                var other = obj asSortBox;
                if (other != null)
                {
                    returnstring.CompareOrdinal(this.Data, other.Data);
                }
                var otherAsString = obj asstring;
                returnstring.CompareOrdinal(this.Data, otherAsString);
            }
        }
        privatevoid MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                _nRows = ((int)this.ActualHeight - _spControlsHeight - 50) / 10;
                this.Content = _canvas;
                var spControls = newStackPanel()
                {
                    Orientation = Orientation.Horizontal,
                    MaxHeight = _spControlsHeight
                };
                _canvas.Children.Add(spControls);
                var btnSort = newButton()
                {
                    Content = "Do_Sort",
                    ToolTip = "Will generate data and sort. Click to cancel. LeftShift-Click to continue an aborted sort, possibly with a different algorithm",
                    Height = 20,
                    VerticalAlignment = VerticalAlignment.Top
                };
                spControls.Children.Add(btnSort);
                var cboSortType = newComboBox()
                {
                    ItemsSource = _SortTypes,
                    Height = 20,
                    VerticalAlignment = VerticalAlignment.Top,
                    Width = 150,
                };
                cboSortType.SelectedIndex = 8;
                spControls.Children.Add(cboSortType);
                var txtNumItems = newTextBox()
                {
                    Text = "4000",
                    ToolTip = "Max Number of items to sort. (limited by display)",
                    Height = 20,
                    VerticalAlignment = VerticalAlignment.Top,
                    Width = 100
                };
                spControls.Children.Add(txtNumItems);
                var spVertControls = newStackPanel()
                {
                    Orientation = Orientation.Vertical
                };
                spControls.Children.Add(spVertControls);
                var chkLettersOnly = newCheckBox()
                {
                    Content = "_Letters only",
                    ToolTip = "Include just letters or other characters too",
                    IsChecked = true
                };
                spVertControls.Children.Add(chkLettersOnly);
                var chkShowSort = newCheckBox()
                {
                    Content = "Show ",
                    ToolTip = "Update display during sort. Turn this off to see performance without updaating",
                    IsChecked = true
                };
                chkShowSort.Checked += (os, es) => _ShowSort = true;
                chkShowSort.Unchecked += (os, es) => _ShowSort = false;
                spVertControls.Children.Add(chkShowSort);
                var txtMaxDataLength = newTextBox()
                {
                    Text = "0",
                    Width = 40,
                    ToolTip = "Max # of random chars per datum. 0 means use a dictionary of real words"
                };
                spVertControls.Children.Add(txtMaxDataLength);
                var txtStatus = newTextBox()
                {
                    Margin = newThickness(10, 0, 0, 0),
                    Width = 900,
                    Height = _spControlsHeight,
                    VerticalScrollBarVisibility = ScrollBarVisibility.Auto
                };
                Action<string> addStatusMsg = (str) =>
                {
                    Dispatcher.BeginInvoke(newAction(
                        () =>
                        {
                            txtStatus.AppendText($"{str}rn");
                            txtStatus.ScrollToEnd();
                        }
                        ));
                };
                spControls.Children.Add(txtStatus);
                List<SortBox> arrData = null;
                int nTotal = 0;
                btnSort.Click += (ob, eb) =>
                {
                    _cancelTokSrc = newCancellationTokenSource();
                    btnSort.IsEnabled = false;
                    var sortType = (string)cboSortType.SelectedValue;
                    if (arrData == null ||
                        !System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.LeftShift)
                    )
                    {
                        // lets create controls on main thread
                        _canvas.Children.Clear();
                        _canvas.Children.Add(spControls);
                        nTotal = int.Parse(txtNumItems.Text);
                        arrData = newList<SortBox>();
                        var maxDatalength = int.Parse(txtMaxDataLength.Text);
                        arrData = InitData(ref nTotal, maxDatalength, chkLettersOnly.IsChecked.Value);
                        addStatusMsg($"Starting {sortType} with {nTotal} items. Click anywhare to stop");
                    }
                    else
                    {// user left shift-click: continue sorting with a possible different algorithm// note: cancellation can result in slight data errors because exception thrownfor (int i = 1; i < nTotal; i++)
                        {
                            if (arrData[i] < arrData[i - 1])
                            {
                                arrData[i].FontWeight = FontWeights.Normal;
                            }
                        }
                        addStatusMsg($"Continuing with  {sortType}{nTotal} items. Click anywhare to stop");
                    }
                    var tsk = Task.Run(() =>
                    {
                        // do the sorting on a background threadtry
                        {
                            DoTheSorting(arrData, sortType, nTotal);
                        }
                        catch (TaskCanceledException)
                        {
                        }
                        catch (Exception ex)
                        {
                            addStatusMsg($"Exception {ex.ToString()}");
                        }

                        txtStatus.Dispatcher.BeginInvoke(newAction(
                            () =>
                            {
                                // now that we're done, let's verifyvar stats = SortBox.stats;
                                var hasError = ValidateSorted(arrData, nTotal);
                                if (!_ShowSort)
                                {
                                    // show sorted resultsfor (int i = 0; i < nTotal; i++)
                                    {
                                        arrData[i].Content = arrData[i].Data;
                                    }
                                }
                                string donemsg = _cancelTokSrc.IsCancellationRequested ? "Aborted" : "Done   ";
                                addStatusMsg($"{sortType,10}{donemsg}{stats}{hasError}");
                                btnSort.IsEnabled = true;
                            }));
                    });
                };
                btnSort.RaiseEvent(newRoutedEventArgs(Button.ClickEvent, this));
            }
            catch (Exception ex)
            {
                this.Content = ex.ToString();
            }
        }

        publicstring ValidateSorted(List<SortBox> arrData, int nTotal)
        {
            var hasError = string.Empty;

            int nErrors = 0;
            for (int i = 1; i < nTotal; i++)
            {
                if (arrData[i] < arrData[i - 1])
                {
                    nErrors++;
                    arrData[i].FontWeight = FontWeights.ExtraBold;
                }
            }
            if (nErrors > 0)
            {
                hasError = $"Error! {nErrors} not sorted";
            }
            return hasError;
        }

        publicList<SortBox> InitData(refint nTotal, int maxDatalength, bool ltrsOnly)
        {
            var arrData = newList<SortBox>();
            var rand = newRandom(1);
            /* to use without the dictionary (using random letters) comment the current line and the new Dictionary line below
             
            dynamic dict = null;
            maxDatalength = 5;

            /*/// get the dictionary from my OneDrive:// https://onedrive.live.com/redir?resid=D69F3552CEFC21!99083&authkey=!AFjyjUlZpH5sQy0&ithint=file%2cdll // then run the command RegSvr32 dictionary.dll// then add a reference to COM ->Dictionary 1.0 Type Library
            Dictionary.CDict dict = null;
            //*/int colWidth;
            // we will try to fill the screen with sort data. // However, there are times when a particular # of items is desired,// such as debugging a list of 5 items.// so we limit by nTotal or screen capacity if (maxDatalength == 0)
            {
                dict = new Dictionary.CDict(); // comment out this line if no dictionary
                dict.DictNum = 2;
                maxDatalength = 11;
                colWidth = 8 * (maxDatalength - 1);
            }
            else
            {
                colWidth = 20 + 8 * (maxDatalength - 1);
            }
            int nCols = (int)this.ActualWidth / colWidth;
            if (nCols == 0) //tests
            {
                nCols = 80;
            }
            for (int i = 0; i < _nRows; i++)
            {
                for (int j = 0; j < nCols; j++)
                {
                    if (arrData.Count < nTotal)
                    {
                        string dat = string.Empty;
                        switch (arrData.Count)
                        {
                            // set the first few items to const so easier to debug algorithmscase 0:
                                dat = "zero";
                                break;
                            case 1:
                                dat = "one";
                                break;
                            case 2:
                                dat = "two";
                                break;
                            case 3:
                                dat = "three";
                                break;
                            case 4:
                                dat = "four";
                                break;
                            case 5:
                                dat = "five";
                                break;
                            default:
                                var len = 1 + rand.Next(maxDatalength);
                                var datarray = newchar[len];
                                for (int k = 0; k < len; k++)
                                {
                                    // "A" is 65,"!" is 33
                                    datarray[k] = (char)(ltrsOnly == true ?
                                        65 + rand.Next(26) :
                                        33 + rand.Next(90));
                                }
                                dat = newstring(datarray);
                                break;
                        }
                        var box = newSortBox();
                        if (dict == null)
                        {
                            box.Data = dat.Substring(0, Math.Min(maxDatalength, dat.Length));
                        }
                        else
                        {
                            box.Data = dict.RandWord(0);
                        }
                        box.Content = box.Data;
                        arrData.Add(box);
                        if (_ShowSort)
                        {
                            Canvas.SetTop(box, 3 + _spControlsHeight + i * 10);
                            Canvas.SetLeft(box, j * colWidth);
                            _canvas.Children.Add(box);
                        }
                    }
                }
            }
            nTotal = arrData.Count; // could be lessif (!_ShowSort)
            {
                // show initial valuesfor (int i = 0; i < nTotal; i++)
                {
                    arrData[i].Content = arrData[i].Data;
                }
            }
            SortBox.InitStats(nTotal);
            return arrData;
        }

        publicvoid DoTheSorting(List<SortBox> arrData, string sortType, int nTotal)
        {
            switch (sortType)
            {
                case"Bubble":
                    var nEnd = nTotal;
                    var newEnd = 0;
                    do
                    {
                        newEnd = 0;
                        for (int i = 1; i < nEnd; i++)
                        {
                            if (arrData[i - 1] > arrData[i])
                            {
                                arrData[i - 1].Swap(arrData[i]);
                                newEnd = i;
                            }
                        }
                        nEnd = newEnd;
                    } while (newEnd != 0);
                    break;
                case"Unknown":
                    for (int i = 1; i < nTotal; i++)
                    {
                        for (int j = 0; j < i; j++)
                        {
                            if (arrData[i] < arrData[j])
                            {
                                arrData[i].Swap(arrData[j]);
                            }
                        }
                    }
                    break;
                case"Stupid": // gnomeSortfor (int i = 0; i < nTotal;)
                    {
                        if (i == 0 || !(arrData[i - 1] > arrData[i]))
                        {
                            i++;
                        }
                        else
                        {
                            arrData[i - 1].Swap(arrData[i]);
                            i--;
                        }
                    }
                    break;
                case"Insertion":
                    for (int i = 1; i < nTotal; i++)
                    {
                        var t = arrData[i].Data;
                        int j = i - 1;
                        for (; j >= 0 && arrData[j].CompareTo(t) > 0; j--)
                        {
                            arrData[j + 1].Data = arrData[j].Data;
                        }
                        //int j = i - 1;//while (j >= 0 && arrData[j].CompareTo(t) > 0)//{//    arrData[j + 1].Data = arrData[j].Data;//    j--;//}
                        arrData[j + 1].Data = t;
                    }
                    break;
                case"Selection":
                    // scan entire array for minimum, swap with 1st, then repeat for restfor (int i = 0; i < nTotal - 1; i++)
                    {
                        int minimum = i;
                        for (int j = i + 1; j < nTotal; j++)
                        {
                            if (arrData[j] < arrData[minimum])
                            {
                                minimum = j;
                            }
                        }
                        if (minimum != i)
                        {
                            arrData[i].Swap(arrData[minimum]);
                        }
                    }
                    break;
                case"OddEven":
                    var sorted = false;
                    while (!sorted)
                    {
                        sorted = true;
                        for (int i = 1; i < nTotal - 1; i += 2)
                        {
                            if (arrData[i + 1] < arrData[i])
                            {
                                arrData[i + 1].Swap(arrData[i]);
                                sorted = false;
                            }
                        }
                        for (int i = 0; i < nTotal - 1; i += 2)
                        {
                            if (arrData[i + 1] < arrData[i])
                            {
                                arrData[i + 1].Swap(arrData[i]);
                                sorted = false;
                            }
                        }
                    }
                    break;
                case"Cycle":
                    // deceptively fast because fewer updates, // which are expensive in this code because of thread// context switches and drawing updated data// note the # of updates <= ntotalfor (int cycleStart = 0; cycleStart < nTotal; cycleStart++)
                    {
                        // the item to placevar item = arrData[cycleStart].Data;
                        int pos = cycleStart;
                        do
                        {
                            int nextPos = 0;
                            // find it's position # in entire array// by finding how many should precede itfor (int i = 0; i < nTotal; i++)
                            {
                                if (i != cycleStart && arrData[i].CompareTo(item) < 0)
                                {
                                    nextPos++;
                                }
                            }
                            // if it's not in the correct positionif (pos != nextPos)
                            {
                                // move past duplicateswhile (pos != nextPos && arrData[nextPos].CompareTo(item) == 0)
                                {
                                    nextPos++;
                                }
                                // save the cur value at nextposvar temp = arrData[nextPos].Data;
                                // set the value at nextpos to the item to place
                                arrData[nextPos].Data = item;
                                // new value for which to seek position
                                item = temp;
                                pos = nextPos;
                            }
                        } while (pos != cycleStart);
                    }
                    break;
                case"Merge":
                    // not in place: uses additional storage// lets make a recursive lambdaAction<int, int, int> MergeSort = null;
                    MergeSort = (left, right, depth) =>
                    {
                        SortBox.stats.MaxDepth = Math.Max(depth, SortBox.stats.MaxDepth);
                        if (right > left)
                        {
                            int mid = (right + left) / 2;
                            MergeSort(left, mid, depth + 1);
                            mid++;
                            MergeSort(mid, right, depth + 1);
                            // now we merge 2 sections that are already sortedint leftNdx = left;
                            // use extra storagevar temp = newList<string>();
                            int pivot = mid;
                            while (leftNdx < pivot && mid <= right)
                            {
                                // fill temp from left or rightif (arrData[mid] < arrData[leftNdx])
                                {
                                    temp.Add(arrData[mid++].Data);
                                }
                                else
                                {
                                    temp.Add(arrData[leftNdx++].Data);
                                }
                            }
                            // deal with leftovers on left or rightwhile (leftNdx < pivot)
                            {
                                temp.Add(arrData[leftNdx++].Data);
                            }
                            while (mid <= right)
                            {
                                temp.Add(arrData[mid++].Data);
                            }
                            // fill the elements with the sorted listfor (int i = 0; i < temp.Count; i++)
                            {
                                arrData[left + i].Data = temp[i];
                            }
                        }
                    };
                    MergeSort(0, nTotal - 1, 0);
                    break;
                case"MergeIP":
                    Action<int, int, int> MergeSortIp = null;
                    MergeSortIp = (left, right, depth) =>
                    {
                        SortBox.stats.MaxDepth = Math.Max(depth, SortBox.stats.MaxDepth);
                        if (left >= right)
                        {
                            return;
                        }
                        int mid = (left + right) / 2;
                        MergeSortIp(left, mid, depth + 1);
                        mid++;
                        MergeSortIp(mid, right, depth + 1);
                        int leftNdx = left;
                        int pivot = mid;
                        int leftEnd = pivot - 1;
                        while (leftNdx <= leftEnd && mid <= right)
                        {
                            if (arrData[leftNdx] < arrData[mid])
                            {
                                // left already in place
                                leftNdx++;
                            }
                            else
                            {
                                // take from right: shift everyone over to make roomvar temp = arrData[mid].Data;
                                for (int j = mid - 1; j >= leftNdx; j--)
                                {
                                    arrData[j + 1].Data = arrData[j].Data;
                                }
                                arrData[leftNdx].Data = temp;
                                leftNdx++;
                                leftEnd++;
                                mid++;
                            }
                        }
                    };
                    MergeSortIp(0, nTotal - 1, 0);
                    break;
                case"MergeIP2":
                    //http://stackoverflow.com/questions/2571049/how-to-sort-in-place-using-the-merge-sort-algorithm/22839426#22839426Action<int, int> reverse = (a, b) =>
                    {
                        for (--b; a < b; a++, b--)
                        {
                            arrData[a].Swap(arrData[b]);
                        }
                    };
                    Func<int, int, int, int> rotate = (a, b, c) =>
                    {
                        //* swap the sequence [a,b) with [b,c). if (a != b && b != c)
                        {
                            reverse(a, b);
                            reverse(b, c);
                            reverse(a, c);
                        }
                        return a + c - b;
                    };
                    Func<int, int, SortBox, int> lower_bound = (a, b, key) =>
                    {
                        //* find first element not less than @p key in sorted sequence or end of// * sequence (@p b) if not found. for (int i = b - a; i != 0; i /= 2)
                        {
                            int mid = a + i / 2;
                            if (arrData[mid] < key)
                            {
                                a = mid + 1;
                                i--;
                            }
                        }
                        return a;
                    };
                    Func<int, int, SortBox, int> upper_bound = (a, b, key) =>
                    {
                        ///* find first element greater than @p key in sorted sequence or end of//* sequence (@p b) if not found. for (int i = b - a; i != 0; i /= 2)
                        {
                            int mid = a + i / 2;
                            if (arrData[mid].CompareTo(key) <= 0)
                            {
                                a = mid + 1;
                                i--;
                            }
                        }
                        return a;
                    };
                    Action<int, int, int, int> mergeInPlace = null;
                    mergeInPlace = (left, mid, right, depth) =>
                    {
                        SortBox.stats.MaxDepth = Math.Max(depth, SortBox.stats.MaxDepth);
                        int n1 = mid - left;
                        int n2 = right - mid;
                        if (n1 == 0 || n2 == 0)
                        {
                            return;
                        }
                        if (n1 == 1 && n2 == 1)
                        {
                            if (arrData[mid] < arrData[left])
                            {
                                arrData[mid].Swap(arrData[left]);
                            }
                        }
                        else
                        {
                            int p, q;
                            if (n1 <= n2)
                            {
                                q = mid + n2 / 2;
                                p = upper_bound(left, mid, arrData[q]);
                            }
                            else
                            {
                                p = left + n1 / 2;
                                q = lower_bound(mid, right, arrData[p]);
                            }
                            mid = rotate(p, mid, q);

                            mergeInPlace(left, p, mid, depth + 1);
                            mergeInPlace(mid, q, right, depth + 1);
                        }
                    };
                    Action<int, int, int> inPlaceMergeSort = null;
                    inPlaceMergeSort = (left, nElem, depth) =>
                    {
                        if (nElem > 1)
                        {
                            int mid = nElem / 2;
                            inPlaceMergeSort(left, mid, depth + 1);
                            inPlaceMergeSort(left + mid, nElem - mid, depth + 1);
                            mergeInPlace(left, left + mid, left + nElem, depth + 1);
                        }
                    };
                    inPlaceMergeSort(0, nTotal, 0);
                    break;
                case"Quick":
                    Action<int, int, int> quickSort = null;
                    quickSort = (left, right, depth) =>
                    {
                        SortBox.stats.MaxDepth = Math.Max(depth, SortBox.stats.MaxDepth);
                        if (left < right)
                        {
                            var pivot = arrData[left];
                            int i = left;
                            int j = right;
                            while (i < j)
                            {
                                // find the leftmost one that should be on the rightwhile (i < right && !(arrData[i] > pivot))
                                {
                                    i++;
                                }
                                // set j to the rightmost one that should be on the leftwhile (arrData[j] > pivot)
                                {
                                    j--;
                                }
                                if (i < j)
                                {
                                    arrData[i].Swap(arrData[j]);
                                }
                            }
                            // now put pivot into place
                            pivot.Swap(arrData[j]);
                            // now recur to sort left, then right sides 
                            quickSort(left, j - 1, depth + 1);
                            quickSort(j + 1, right, depth + 1);
                        }
                    };
                    // now do the actual sort
                    quickSort(0, nTotal - 1, 0);
                    break;
                case"Shell":
                    for (int g = nTotal / 2; g > 0; g /= 2)
                    {
                        for (int i = g; i < nTotal; i++)
                        {
                            for (int j = i - g; j >= 0 && arrData[j] > arrData[j + g]; j -= g)
                            {
                                arrData[j].Swap(arrData[j + g]);
                            }
                        }
                    }
                    break;
                case"Heap":
                    // https://simpledevcode.wordpress.com/2014/11/25/heapsort-c-tutorial/int heapSize = 0;
                    Action<int, int> Heapify = null;
                    Heapify = (index, depth) =>
                    {
                        SortBox.stats.MaxDepth = Math.Max(SortBox.stats.MaxDepth, depth);
                        int left = 2 * index;
                        int right = 2 * index + 1;
                        int largest = index;

                        if (left <= heapSize && arrData[left] > arrData[index])
                        {
                            largest = left;
                        }
                        if (right <= heapSize && arrData[right] > arrData[largest])
                        {
                            largest = right;
                        }

                        if (largest != index)
                        {
                            arrData[index].Swap(arrData[largest]);
                            Heapify(largest, depth + 1);
                        }
                    };
                    heapSize = nTotal - 1;
                    for (int i = nTotal / 2; i >= 0; i--)
                    {
                        Heapify(i, 0);
                    }
                    for (int i = nTotal - 1; i >= 0; i--)
                    {
                        arrData[0].Swap(arrData[i]);
                        heapSize--;
                        Heapify(0, 0);
                    }
                    break;
                case"Super":
                    var data = (from dat in arrData
                                orderby dat
                                select dat.Data).ToArray();
                    for (int i = 0; i < nTotal; i++)
                    {
                        arrData[i].Data = data[i];
                    }
                    break;
            }
        }

        [DllImport("user32.dll")]
        staticexternuint GetQueueStatus(uint flags);
    }
}

</SortingCode>

<TestCode>

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WpfApplication1;
using System.Linq;

namespace SorterTests
{
    [TestClass]
    publicclassUnitTest1
    {
        publicTestContext TestContext { get; set; }
        [TestMethod]
        publicvoid TestMethod1()
        {
            MainWindow._ShowSort = false;
            TestContext.WriteLine("Start");
            foreach (var sortType inMainWindow._SortTypes.Where(
                /*
                t => true
                /*/
                t => 
                t != "Cycle"&& t != "Bubble"&& t != "Unknown"&& t != "Stupid"&& t != "Selection"&& t != "Insertion"&& t != "MergeIP"&& t != "OddEven"//*/
                ))
            {
                for (int pow = 0, nTotal = 1; pow < 7; pow++)
                {
                    var mwindow = newMainWindow();
                    mwindow._nRows = 1000000; // don't limit data by # rowsvar arrData = mwindow.InitData(ref nTotal, maxDatalength: 4, ltrsOnly: false);
                    mwindow.DoTheSorting(arrData, sortType, nTotal);
                    var errs = mwindow.ValidateSorted(arrData, nTotal);
                    Assert.IsTrue(string.IsNullOrEmpty(errs), $"{sortType}{errs}");
                    TestContext.WriteLine($"{sortType,10}{MainWindow.SortBox.stats}");
                    nTotal *= 10;
                }
            }
        }
        /*
    ActiveSheet.PasteSpecial Format:="Unicode Text", Link:=False, _
        DisplayAsIcon:=False
    Range("A1:B5").Select
    Selection.EntireRow.Delete
    Columns("B:P").Select
    Columns("B:P").EntireColumn.AutoFit
    Range("C:C,E:E,G:G,I:I,K:K,M:M,O:O").Select
    Range("O1").Activate
    Selection.EntireColumn.Hidden = True
    Range("B1").Select
    Selection.EntireRow.Insert , CopyOrigin:=xlFormatFromLeftOrAbove
    ActiveCell.FormulaR1C1 = "Sort"
    Range("D1").Select
    ActiveCell.FormulaR1C1 = "Secs"
    Range("F1").Select
    ActiveCell.FormulaR1C1 = "Items"
    Range("H1").Select
    ActiveCell.FormulaR1C1 = "Compares"
    Range("J1").Select
    ActiveCell.FormulaR1C1 = "Updates"
    Range("L1").Select
    ActiveCell.FormulaR1C1 = "Reads"
    Range("N1").Select
    ActiveCell.FormulaR1C1 = "Writes"
    Range("P1").Select
    ActiveCell.FormulaR1C1 = "Depth"
    Range("H10").Select
    ActiveSheet.ListObjects.Add(xlSrcRange, Range("$B$1:$P$50"), , xlYes).Name = _
        "Table1"
    Range("Table1[#All]").Select
    Sheets.Add
    ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
        "Table1", Version:=6).CreatePivotTable TableDestination:="Sheet2!R3C1", _
        TableName:="PivotTable1", DefaultVersion:=6
    Sheets("Sheet2").Select
    Cells(3, 1).Select
    With ActiveSheet.PivotTables("PivotTable1").PivotFields("Sort")
        .Orientation = xlColumnField
        .Position = 1
    End With
    With ActiveSheet.PivotTables("PivotTable1").PivotFields("Items")
        .Orientation = xlRowField
        .Position = 1
    End With
    ActiveSheet.PivotTables("PivotTable1").AddDataField ActiveSheet.PivotTables( _
        "PivotTable1").PivotFields("Secs"), "Sum of Secs", xlSum
    ActiveChart.ClearToMatchStyle
    ActiveSheet.Shapes.AddChart2(227, xlLine).Select
    ActiveChart.SetSourceData Source:=Range("Sheet2!$A$3:$I$12")
    Application.Goto Reference:="Macro1"
        */
    }
}

</TestCode>


Viewing all articles
Browse latest Browse all 3015

Trending Articles