C # implementation of the eight major sorting algorithms (1 ),

Source: Internet
Author: User

C # implementation of the eight major sorting algorithms (1 ),
Introduction

Sorting algorithms are the most commonly used algorithms in programming. Currently, there are eight mainstream algorithms.

The average time complexity is from high to low:

Bubble sort (o (n2), select sort (o (n2), insert sort (o (n2), Heap Sort (o (nlogn )),

Merge Sorting (o (nlogn), fast sorting (o (nlogn), Hill sorting (o (n1.25), and base sorting (o (n ))

The average time complexity is listed by reference to the Wikipedia sorting algorithm.

It is the calculated theoretical average, and does not mean that your code implementation can reach this level.

For example, in Hill sorting, the time complexity is determined by the selected step size. Minimum base sorting time complexity,

However, the base sorting speed I achieved is not the fastest, as shown in the result test diagram below.

The data source type used in this code is IList <int>, which is compatible with int [] and List <int> (although int [] has ToList (),

List <int> has ToArray (), haha !).

Select sort

Selecting sorting is the simplest and most violent sorting method in my opinion.

When I first came into contact with sorting algorithms, I felt that there were too many unclear algorithms, but I remember how to select and implement sorting.

Principle: Find the maximum value of the array involved in sorting and put it at the end (or find the minimum value at the beginning). Wikipedia entry

The implementation is as follows:

public static void SelectSort(IList<int> data)        {            for (int i = 0; i < data.Count - 1; i++)            {                int min = i;                int temp = data[i];                for (int j = i + 1; j < data.Count; j++)                {                    if (data[j] < temp)                    {                        min = j;                        temp = data[j];                    }                }                if (min != i)                    Swap(data, min, i);            }        }

Process parsing: swap the minimum number of remaining arrays to the beginning.

Bubble Sorting

Bubble Sorting is often used for test interviews. Although it is the slowest sort speed (perspiration) in these algorithms, It is evidenced by tests later.

Principle: from the beginning, each element is compared with its next element. If it is large, it is exchanged with the comparison element. Otherwise, it will not move.

This means that a large element is always moving backward until it encounters a bigger element. Therefore, the maximum value can be set for each round of exchange.

Finally. Wiki Portal

The implementation is as follows:

public static void BubbleSort(IList<int> data)        {            for (int i = data.Count - 1; i > 0; i--)            {                for (int j = 0; j < i; j++)                {                    if (data[j] > data[j + 1])                        Swap(data, j, j + 1);                }            }        }

Process Analysis: It should be noted that j <I, each round of bubbles will inevitably route the maximum value to the end of the array, so the number of sorting should be reduced.

Many online versions still bubble all the data in the second round after each round, that is, j <data. Count-1, which increases the number of comparisons.

Improve Bubble Sorting by ID

On the Wiki, you can add an identifier to identify whether the remaining number is ordered to reduce the number of comparisons. It is very interesting. You can try it.

The implementation is as follows:

public static void BubbleSortImprovedWithFlag(IList<int> data)        {            bool flag;            for (int i = data.Count - 1; i > 0; i--)            {                flag = true;                for (int j = 0; j < i; j++)                {                    if (data[j] > data[j + 1])                    {                        Swap(data, j, j + 1);                        flag = false;                    }                }                if (flag) break;            }        }

Process Analysis: it is found that a certain round of bubble does not have any number for Exchange (that is, it is already ordered), and it jumps out of the sorting.

At first, I thought this method should have a good effect, but the actual test results were not as expected. It takes the same time (for a random number of columns) as not optimized ).

If the result is derived, it should be a bubble sort. For a random series, when the remaining series are ordered, there are not a few numbers to be arranged !?

However, if it is already an ordered series or partially ordered, this bubble method will increase the speed.

Sort cocktails (sort back and forth) to optimize Bubble Sorting

The Bubble Sorting is only one-way bubbling, while the cocktail is repeated and bidirectional bubbling.

Principle: from left to right, place a large number at the end, and then place the remainder series at the beginning from right to left. Wiki Portal

The implementation is as follows:

public static void BubbleCocktailSort(IList<int> data)        {            bool flag;            int m = 0, n = 0;            for (int i = data.Count - 1; i > 0; i--)            {                flag = true;                if (i % 2 == 0)                {                    for (int j = n; j < data.Count - 1 - m; j++)                    {                        if (data[j] > data[j + 1])                        {                            Swap(data, j, j + 1);                            flag = false;                        }                    }                    if (flag) break;                    m++;                }                else                {                    for (int k = data.Count - 1 - m; k > n; k--)                    {                        if (data[k] < data[k - 1])                        {                            Swap(data, k, k - 1);                            flag = false;                        }                    }                    if (flag) break;                    n++;                }            }        }

Process Analysis: analyze the I-round bubble. If I is an even number, the maximum value of the remaining series will bubble to the right to the end. If it is an odd number, the minimum value of the remaining series will be

Bubbles to the left to open the header. For the remainder of the series, n is the beginning, and data. Count-1-m is the end.

Back-and-forth bubbles are more likely to produce an ordered residual sequence for a random sequence. Therefore, using the logo here will be more obvious.

Insert sort

Insert sorting is an efficient sorting of ordered series. Very intelligent sorting. Only for random series, the efficiency is average and the switching frequency is high.

Principle: builds an ordered sequence, compares unordered numbers from the back to the front, finds a proper position, and inserts them. Wiki Portal

The first number is treated as an ordered sequence.

The implementation is as follows:

public static void InsertSort(IList<int> data)        {            int temp;            for (int i = 1; i < data.Count; i++)            {                temp = data[i];                for (int j = i - 1; j >= 0; j--)                {                    if (data[j] > temp)                    {                        data[j + 1] = data[j];                        if (j == 0)                        {                            data[0] = temp;                            break;                        }                    }                    else                    {                        data[j + 1] = temp;                        break;                    }                }            }        }

Process parsing: store the number of elements to be sorted (index is I), find the appropriate position j + 1 forward, and sort the elements from I-1 to j + 1 backward

Move one digit, empty j + 1, and put the previously stored value in this position.

This method is not as concise and clear as it is on the Wiki. Because the proper position is j + 1, the j = 0 judgment is provided, but the actual efficiency has no difference.

We recommend that you sort the logs by Wikipedia and by yourself.

Optimization of insertion sorting by binary search

Insert sorting is mainly used to find the proper position for the number to be sorted in an ordered series, and the classic binary search method in the search can be applied.

Principle: locate a location index using the binary search method. When the number to be sorted is inserted at this position, it is greater than the previous number and smaller than the last number.

The implementation is as follows:

public static void InsertSortImprovedWithBinarySearch(IList<int> data)        {            int temp;            int tempIndex;            for (int i = 1; i < data.Count; i++)            {                temp = data[i];                tempIndex = BinarySearchForInsertSort(data, 0, i, i);                for (int j = i - 1; j >= tempIndex; j--)                {                    data[j + 1] = data[j];                }                data[tempIndex] = temp;            }        }        public static int BinarySearchForInsertSort(IList<int> data, int low, int high, int key)        {            if (low >= data.Count - 1)                return data.Count - 1;            if (high <= 0)                return 0;            int mid = (low + high) / 2;            if (mid == key) return mid;            if (data[key] > data[mid])            {                if (data[key] < data[mid + 1])                    return mid + 1;                return BinarySearchForInsertSort(data, mid + 1, high, key);            }            else  // data[key] <= data[mid]            {                if (mid - 1 < 0) return 0;                if (data[key] > data[mid - 1])                    return mid;                return BinarySearchForInsertSort(data, low, mid - 1, key);            }        }

Process parsing: It should be noted that in the implementation of the binary search method, when high-low = 1, mid = low, so 33 rows are required.

If the value of mid-1 is <0, that is, the value of mid = 0, otherwise the row index is out of bounds.

Quick sorting

Quick sorting is a highly efficient sorting method. It contains the thoughts of "divide and conquer" and "Sentinel.

Principle: select a number from the series as the "Sentinel", so that the number is smaller than it on the left side of it, and the number is larger than it on the right side of it. The sequence to be sorted is recursively divided

The smallest number of columns. Each time the split sequence conforms to the "Sentinel" rule, the sequence is naturally ordered. Wiki Portal

The implementation is as follows:

public static void QuickSortStrict(IList<int> data)        {            QuickSortStrict(data, 0, data.Count - 1);        }        public static void QuickSortStrict(IList<int> data, int low, int high)        {            if (low >= high) return;            int temp = data[low];            int i = low + 1, j = high;            while (true)            {                while (data[j] > temp) j--;                while (data[i] < temp && i < j) i++;                if (i >= j) break;                Swap(data, i, j);                i++; j--;            }            if (j != low)                Swap(data, low, j);            QuickSortStrict(data, j + 1, high);            QuickSortStrict(data, low, j - 1);        }

Process parsing: The retrieved Sentinel is the first value of the series, and then searches for the second and the end at the same time. The left side is the value smaller than the sentry value,

So we need to find the I that is not less than, and the right side will display the j that is greater than the Sentinel value, so we need to find the j that is not greater. Swap the number of I and j found,

This reduces the number of exchanges. I> = j, the series are all searched, and not conforming to the condition j must be on the small side, while the Sentinel

Is the first number, and the position should be smaller than the number of its own. So exchange the sentinel with j to conform to the rules of the Sentinel.

The disadvantage of this version is that the number of recursion would be terrible if the sequence is sorted.

Another version

This is a C # version on the Wiki. I think it is very interesting. This version does not strictly comply with the Sentinel rules. However, it will "divide and conquer"

And the Sentinel idea. The code is concise.

The implementation is as follows:

public static void QuickSortRelax(IList<int> data)        {            QuickSortRelax(data, 0, data.Count - 1);        }        public static void QuickSortRelax(IList<int> data, int low, int high)        {            if (low >= high) return;            int temp = data[(low + high) / 2];            int i = low - 1, j = high + 1;            while (true)            {                while (data[++i] < temp) ;                while (data[--j] > temp) ;                if (i >= j) break;                Swap(data, i, j);            }            QuickSortRelax(data, j + 1, high);            QuickSortRelax(data, low, i - 1);        }

Process parsing: the number of the Referer is the number in the middle of the sequence. Divide the series into two waves. The left side is less than or equal to the Sentinel, and the right side is greater than or equal to the Sentinel.

That is to say, the Sentinel is not necessarily in the middle of the two wave numbers. Although the Sentinel is not in the middle, it does not hinder the implementation of the Sentinel idea. So

This implementation can also achieve quick sorting. However, each recursion is completed, and the total number of series to be sorted is not reduced (unless I = j ).

I have optimized the disadvantages of this version.

The implementation is as follows:

public static void QuickSortRelaxImproved(IList<int> data)        {            QuickSortRelaxImproved(data, 0, data.Count - 1);        }        public static void QuickSortRelaxImproved(IList<int> data, int low, int high)        {            if (low >= high) return;            int temp = data[(low + high) / 2];            int i = low - 1, j = high + 1;            int index = (low + high) / 2;            while (true)            {                while (data[++i] < temp) ;                while (data[--j] > temp) ;                if (i >= j) break;                Swap(data, i, j);                if (i == index) index = j;                else if (j == index) index = i;            }            if (j == i)            {                QuickSortRelaxImproved(data, j + 1, high);                QuickSortRelaxImproved(data, low, i - 1);            }            else //i-j==1            {                if (index >= i)                {                    if (index != i)                        Swap(data, index, i);                    QuickSortRelaxImproved(data, i + 1, high);                    QuickSortRelaxImproved(data, low, i - 1);                }                else //index < i                {                    if (index != j)                        Swap(data, index, j);                    QuickSortRelaxImproved(data, j + 1, high);                    QuickSortRelaxImproved(data, low, j - 1);                }            }        }
public static void QuickSortRelaxImproved(IList<int> data)        {            QuickSortRelaxImproved(data, 0, data.Count - 1);        }        public static void QuickSortRelaxImproved(IList<int> data, int low, int high)        {            if (low >= high) return;            int temp = data[(low + high) / 2];            int i = low - 1, j = high + 1;            int index = (low + high) / 2;            while (true)            {                while (data[++i] < temp) ;                while (data[--j] > temp) ;                if (i >= j) break;                Swap(data, i, j);                if (i == index) index = j;                else if (j == index) index = i;            }            if (j == i)            {                QuickSortRelaxImproved(data, j + 1, high);                QuickSortRelaxImproved(data, low, i - 1);            }            else //i-j==1            {                if (index >= i)                {                    if (index != i)                        Swap(data, index, i);                    QuickSortRelaxImproved(data, i + 1, high);                    QuickSortRelaxImproved(data, low, i - 1);                }                else //index < i                {                    if (index != j)                        Swap(data, index, j);                    QuickSortRelaxImproved(data, j + 1, high);                    QuickSortRelaxImproved(data, low, j - 1);                }            }        }

Process parsing: defines a variable Index to track the position of the sentry. We found that the Sentinel was at last in the heap smaller than itself,

Exchange with j; otherwise, exchange with I. This reduces the total number of series to be sorted in each recursion.

The above motion graphs are provided by "Graph dado ".

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.