Introduction to sorting algorithms

Source: Internet
Author: User
Tags array sort comparable

Before introducing sorting, let's first describe a few of the methods that need to be used in each sorting algorithm, and I write them separately in a class that is less (), the Exchange (), the Issort () method, the less () method to determine the size of two elements, Exchange () The Issort () method is used to exchange the position of two elements to determine if the current array is ordered, and their implementation is as follows

package com.sort;@SuppressWarnings("rawtypes")public class Sort {    @SuppressWarnings("unchecked")    public static boolean less(Comparable a, Comparable b) {        return a.compareTo(b) < 0;    }    public static void exchange(Comparable[] a, int i, int j) {        if (i == j)            return;        Comparable t = a[i];        a[i] = a[j];        a[j] = t;    }    public static boolean isSorted(Comparable[] a) {        for (int i = 1; i < a.length; i++) {            if (less(a[i], a[i - 1])) {                return false;            }        }        return true;    }}

The reason the data type is set to comparable is to be compatible with more types of data, such as this, we can operate on any data that implements the comparable interface, such as the integer,double,string of the system system. If we want to manipulate the custom data, we implement the comparable interface and rewrite the CompareTo () method to define our own rules of judgment.

Select sort

This sort is one of the simplest sorting algorithms, and the other is the insertion sort that will be described below. The basic idea of selecting a sort is to first find the smallest element in the array, and secondly, to swap it and the first element of the group for a position. Again, find the smallest element in the remaining element, and swap it with the second element for the position. So reciprocating until the entire array is sorted.

For an array of length n, it takes approximately N^2/2 and N times to select a sort, so it is always proportional to the n^2 of execution time.

There are two characteristics of this algorithm
1. Run time and input independent. That is to say, we traverse through the array to find the smallest element without providing any useful information for the next scan. This means that an array with an ordered array or a primary key that is all equal, and an array that is randomly arranged by an element, are sorted as long as the sort time.
2. The movement of the data is minimal. Because we change the value of two elements each time, the selection of the sort will only be done in N-times, the number of exchanges and the size of the array is linear, this feature is unique to the selection of sorts, other sorting algorithms do not have this feature.

Let's take a look at the implementation of select sort

public final class SelectionSort {    @SuppressWarnings("rawtypes")    public static void sort(Comparable[] a) {        if (Sort.isSorted(a)) {            return;        }        int length = a.length;        for (int i = 0; i < length; i++) {            int min = i;            for (int j = i + 1; j < length; j++) {                if (Sort.less(a[j], a[min])) {                    min = j;                }            }            if (min != i) {                Sort.exchange(a, i, min);            }        }    }}
Insert Sort

The common denominator of insert sorting and selection sorting is that all elements on the left side of the current index are ordered, but the difference is that the insertion sort operates only on the left side of the current index, and the selection sort is the number to the right of the index.

In performance, the time it takes to insert a sort depends on the initial order of the input elements, and if an array is large and where the elements are already basically ordered, the time it takes to insert the sort is very short. Inserting a sort is a very efficient algorithm in the following cases

    1. Each element in the array is not far from its final position.
    2. An ordered large array followed by a decimal group
    3. Only a few elements in the array are positioned incorrectly

About selecting sort and insert sort, if it is for a random array, then the ratio of time required for the two sorting algorithms is a very small constant, and if it is for a partially ordered array, the gap will be more pronounced.

Implementation of the Insert sort

package com.sort;public class InsertSort {    @SuppressWarnings("rawtypes")    public static void sort(Comparable[] a) {        int length = a.length;        for (int i = 1; i < length; i++) {            for (int j = i; j > 0 && Sort.less(a[j], a[j - 1]); j--) {                Sort.exchange(a, j, j - 1);            }        }    }}
Hill sort

The hill sort is based on the insertion sort, which is a quick sort of insertion. Imagine, for a very large array, the smallest element at the end of the array, and if you use an insert sort, it will move step to the beginning of the array, which is very time consuming. So Hill sort argues that the elements in an array that are arbitrarily spaced h are ordered, called an H ordered array, in other words, a small array of all elements that are spaced h, and if H is large, we can move the smaller element to a far place at a time instead of moving it in a step.

The reason the hill sort is efficient is that it balances the size and order of the sub-arrays. Of course, the performance of Hill sort is also related to H, for different h shows different speed, but can not determine which is the best, so here choose H from N/3 decrement to 1.

The run time of the hill sort is not up to the square level, and it is in the worst case proportional to the N^3/2.

Implementation of the Hill sort

package com.sort;public class ShellSort {    @SuppressWarnings("rawtypes")    public static void sort(Comparable[] a) {        int length = a.length;        int h = 1;        while (h < length / 3)            h = 3 * h + 1;        while (h >= 1) {            for (int i = h; i < length; i++) {                for (int j = i; j >= h && Sort.less(a[j], a[j - h]); j -= h) {                    Sort.exchange(a, j, j - h);                }            }            h = h / 3;        }    }}
Merge sort

In fact, when the scale of the problem reaches a certain level, the above algorithm is powerless, especially the insertion sort and the selection sort, so the following describes the merge sort.

The main idea of merge sort is to divide an array into two parts, sort them separately, and then merge the results.

The advantage of the merge sort is that it guarantees that the array sort time of any length n is proportional to the nlogn, and the disadvantage is that the extra space he needs is proportional to n, which means that the ordering needs to be aided by the auxiliary space.

Here's a look at the code

  Package Com.sort;public class MergeSort {private static comparable[] aux;        public static void sort (comparable[] a) {aux = new comparable[a.length];    Sort (A, 0, a.length-1);        } private static void sort (comparable[] A, int low, int.) {if (High <= low) return;        int mid = low + (high-low)/2;        Sort (A, low, mid);        Sort (A, mid + 1, high);    Merge (A, low, mid, high);        } private static void merge (comparable[] A, int low, int mid, int.) {int i = low;        Int J = mid + 1;        for (int k = low, k <= High; k++) {aux[k] = a[k];            } for (int k = low, k <= High; k++) {if (I > Mid) a[k] = aux[j++];            else if (J > High) a[k] = aux[i++];            else if (sort.less (Aux[i], aux[j])) a[k] = aux[i++];        else a[k] = aux[j++]; }    }}

After analyzing the above code, we first apply for a secondary space of the same size as the original array A, call the sort () method, recursively split the array, until high <= low, which indicates that there is only one element in the array, the meaning of recursive segmentation is to shrink the size of the array, and then sort the group into a merge. Using a binary tree to describe this process is the most appropriate, left and right children to synthesize the root node after sorting.

Quick Sort

Fast sorting is currently the most popular sorting algorithm and is the most widely used sorting algorithm. It is so popular because it requires only a small secondary stack, and the time required to sort an array of length n is proportional to the NLGN. None of the algorithms previously learned could combine these two advantages, but the quick sort did.

The idea of a fast sort implementation is to divide an array into two arrays, sorting the two parts independently. But this segmentation is not the same as the merge sort, where the segmentation position depends on the contents of the array. The process of slicing needs to meet the following three conditions

    1. For a J, A[j] has been scheduled;
    2. All elements of A[low] to a[j-1] are not much more than a[j];
    3. A[J+1] to A[high] all elements are not less than [j];

The recursive invocation of the Shard can then be sorted, because each shard can have an element scheduled. To accomplish this, we need to implement the segmentation method, the general strategy is to take A[low] as the segmentation element.

The algorithm is as follows

  public class QuickSort {public static void sort (comparable[] a) {if (sort.issorted (a)) {        Return    } sort (A, 0, a.length-1);        } private static void sort (comparable[] A, int low, int.) {if (high <= low) {return;        } int J = partition (A, low, high);        Sort (A, low, j-1);    Sort (A, j + 1, high);        } private static int partition (comparable[] A, int low, int.) {int i = low, j = high + 1;        Comparable v = A[low];            while (true) {while (Sort.less (A[++i], V)) if (i = = high) break;            while (Sort.less (V, a[--j])) if (j = = low) break;            if (i >= j) break;        Sort.exchange (A, I, j);        } Sort.exchange (A, Low, j);    Return J; }}

The main implementation of the partition () function in the algorithm is to schedule the A[low] element to the specified position and return the position as a return value to the sort () function, which is used to split the array, and each element is scheduled to the specified position as a recursive invocation of the sort () function to achieve sorting.

Fast sorting has a number of advantages, but there is a potential drawback that the program can be extremely inefficient in the case of an unbalanced cut. For example, for the first time from the smallest element of the Shard, the second time from the second small element to be sliced, so that each call will only remove an element, this time the performance is very low. So when using a quick sort, the prime minister would shuffle the array randomly, which would minimize the probability.

Comparison of various sorting algorithms

In order to verify the advantages and disadvantages of the algorithm, I carried out the above algorithm 1 0000 orders of magnitude, 10 0000 order of magnitude, 100 0000 order of magnitude of the array was tested, the test results are as follows:

1.1 0000 Order of magnitude

Select Sort: 0.112s
Insertion Sort: 0.16s
Hill Sort: 0.016s
Merge sort: 0.011s
Quick sort: 0.008s

2.10 0000 Order of magnitude

Select Sort: 11.19s
Insertion Sort: 16.521s
Hill Sort: 0.084 s
Merge sort: 0.114s
Quick sort: 0.066s

3.100 0000 Order of magnitude
Select sort: Wait a few minutes for the results
Insert sort: Wait a few minutes for the results
Hill Sort: 2.022s
Merge sort: 0.742s
Quick sort: 0.521s

The data used for testing is generated by the random function and multiplied by the order of magnitude, for example, 10000 order of magnitude is generated using (int) (Math.random () * 10000), because the number is random, so the above time is not a fixed value, but the difference is not too large.

There are some problems reflected in the above experimental results.

    1. Choose sort and insert sort to large arrays is powerless
    2. The larger the scale, the greater the advantages of a quick sort and merge sort, especially the quick sort

Introduction to sorting algorithms

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.