Three comparison-based nlgn sorting algorithms-merge-heap-fast sort-C ++ implementation

Source: Internet
Author: User

Introduction


Note: Because no public editor is enabled, it is convenient: when the following time complexity is involved, its accesskey is replaced by the following symbol:

This article describes three algorithms that can sort n numbers in O (nlgn) Time: Merge Sorting, heap sorting, and quick sorting. Both algorithms are based on comparative sorting. The first two algorithms reach the upper bound in the worst case, and the quick sorting reaches the upper bound on average.

Note: Compared sorting indicates that the order of each element in the sorting result is based on the comparison between input elements. It can be proved that in the worst case, a comparison of $ (nlogn) times is required for any comparative sorting algorithm. Therefore, heap sorting and Merge Sorting are both the comparison sorting algorithms with the optimal solution.

I. Merge Sorting

This algorithm is one of the typical application of the divide and conquer law. To avoid repeated descriptions with the divide and conquer Law Article, This article focuses on describing the basic idea of Merge Sorting and the specific code implementation.

(1) Basic Ideas: According to the sub-governance mode, the algorithm is divided into three steps:

  • Decomposition: Divide n elements into two parts: each part is a subsequence containing n/2 elements;
  • Solution: Use the Merge Sorting method to recursively sort two subsequences;
  • Merge: Merge two sorted subsequences to obtain the sorting result.

Note: Recursion ends when the length of the subsequence is 1. Because a single element is regarded as sorted.

(2) Algorithm Description: In the preceding steps, merging is the most important part. It is described in detail below.

For merging, an auxiliary process is introduced: Merge (A, p, q, r), where A is the input array, and p, q, and r are subscripts, p <= q <r. this step assumes that the sub-array A [p... q] And A [q + 1... r] the order has been sorted. The pseudocode for merging is as follows:

(3) time complexity: Assume that the elements whose sorting length is n are merged, and the running time is T (n ).

[Decomposition] in step, you only need to calculate the middle position of the sub-array, constant time: @ (1); [solution] Step recursively solves two subproblems with a scale of n/2, the time is 2 T (n/2). The worst case in the [merge] step is that the elements in the two parts must be compared once, I .e. @ (n ). Therefore, the recursive equation of run time T (n) in the worst case of Merge Sorting can be expressed:

It can be obtained by the primary theorem: T (n) =@ (Nlgn)Here, lgn represents log2 ^ n.

(4) Algorithm Implementation

#include <stdio.h>const int N = 6;const int INF = 0x7fffffff; //infinite valueint input[N+1] = {-1, 2, 3, 3, 5, 7, 1};int tempL[(N+1)/2+2];int tempR[(N+1)/2+2];void merge(int input[], int p, int q, int r){int n1 = q-p+1;int n2 = r-q;int i, j;for(i = 1; i <=n1; i++){tempL[i] = input[p+i-1];}for(j = 1; j <=n2; j++){tempR[j] = input[q+j];}tempL[n1+1] = INF;tempR[n2+1] = INF;i = 1;j = 1;for(int k = p; k <= r; k++){if(tempL[i] <= tempR[j]){input[k] = tempL[i++];}elseinput[k] = tempR[j++];}}void mergeSort(int input[], int p, int r){if(p < r){int q = (p+r)/2;mergeSort(input,p,q);mergeSort(input,q+1,r);merge(input, p, q, r);}}void print(int array[]){for(int i = 1; i <= N; i++)printf("%d ",array[i]);printf("\n");}int main(){print(input);mergeSort(input, 1, N);print(input);return 0;}
Ii. Heap sorting (0) Concept:
Heap: A data structure called binary heap data structure. It is an array object. Its DefinitionThe former is called a small root heap, and the latter is a large root heap. In the heap sorting algorithm, a large root heap is used. Priority queue). This article mainly introduces the big root stack. It can be seen from its nature that the top-to-top element of a large root heap is the maximum value among n elements. Heap can be regarded as a Complete Binary Tree. each node in the tree corresponds to the element in the array that stores the node value. Each layer of the tree is filled, except for the last layer (the last layer starts from the left subtree of a node ). For example, in sequence: [96, 83, 27, 38, 11, 9], the corresponding form of the large root heap is: Heap sorting: If a new heap is created after the maximum value of the output heap top and the sequence of the remaining n-1 elements is re-built, the secondary operators of n elements are obtained. After repeated execution, an ordered sequence can be obtained. This process is called heap sorting. The above analysis shows that the heap sorting needs to be solved. Two Problems: I. How to Build a heap from an unordered sequence; II. how to adjust the remaining element to a new heap after the top element of the output heap. Note: After the top element of the heap is output, the value is no longer in the heap (although it may still be stored in the heap array, but the heap size will be reduced by one ). For example, assume that after the top element of the output heap is replaced by the last element in the heap (96, the last element of the array is no longer in the heap ), at this time, although the left and right subtree of the root node maintain the heap nature, and then the nature of the Element Heap changes, it needs to be adjusted. First, compare the value of the heap top element with the value of its left and right child root nodes. If the heap top element is still large, no adjustment is required. Otherwise, swap the child root node greater than the heap top element with the heap top element (if the element value of the left and right child root nodes is greater than the heap top element, select a large element exchange with the heap top element ), the heap top Element 9 is exchanged with the left child root node element 83. Because 9 replaces the root node of the Left subtree and destroys the heap nature of the Left subtree, you still need to adjust it down to know the leaf node. The adjustment process is as follows 【 Filter], So you only need to filter the replaced elements down from the latest position to continue to maintain the nature of the large root stack, that is The second problem has been solved.. The first problem is analyzed below: the process of creating a large heap from an unordered sequence is actually Repeated Filtering. If we regard this sequence as a Complete Binary Tree, the last non-terminal node is the floor (n/2) (rounded down ), from this, you only need to start filtering down from the floor (n/2) elements, then the floor (n/2)-1 elements are filtered down ,..., until the first heap top element is filtered down, the initial Heap has been established after floor (n/2) filtering. Hence The first problem has been solved.. (1) Basic Ideas: According to the above analysis, FilterThe key to the algorithm is: to adjust the heap, a filtering is required; to create a heap, floor (n/2) filtering is required. Filtering is a process of repeated comparison and exchange between the root node and the left and right children (it can be seen that heap sorting is an in-situ algorithm ). (2) Algorithm Description: The following describes Filtering AlgorithmFor the complete algorithm, see (4) algorithm implementation section:
  1. Compare the current left and right child nodes and the selected root element with the current root element.
  2. If the value of the current root element is smaller than the value of the greater child node, the root node is switched to the child node, and the child node is used as the current root node to continue filtering. Otherwise, the filtering ends.
  3. If the filtering reaches the leaf node, the filtering ends.
(3) time complexity: First look at the run time used for filtering. Because the heap corresponds to a Complete Binary Tree, the height of the tree is lgn (n is the number of nodes). In the worst case, for one filter, the elements on the top of the heap must be directed to the leaf node, that is, the running time is O (lgn ). On the surface, the heap creation process requires floor (n/2) filtering, that is, the time complexity is: O (nlgn). Although this field is correct, it is not accurate enough. Available Full Binary Tree: On A Complete Binary Tree of any height of h, there are at most floor (n / 2 ^ (h + 1) node. Therefore, it is filtered down from the position where the height is h. In the worst case, the distance from 1 to the leaf node is h. The exact upper bound can be expressed as follows: according to the above formula, it can be calculated. The time complexity is O (n). It takes only linear time to build an unordered array into a large heap. For heap sorting, after an element is output, an adjustment (filter) is made. After n elements are output, an ordered array is obtained, which is filtered down n times, the filtering time is O (lgn), so the total running time is O (n) + O (nlgn) = O (nlgn). (4) Algorithm Implementation
#include <iostream>using namespace std;/* maximum root heap struct */const int N = 5;struct MaxHeap{int heapArr[N+1];int currSize;};MaxHeap maxHeap = {{-1, 3, 4, 2, 1, 5},N};void swap(int& a, int& b){int temp =a;a = b;b = temp;}void siftDown(MaxHeap& maxHeap, int currPos, int lastPos){int temp = maxHeap.heapArr[currPos];for(int j = 2*currPos ; j <= lastPos; j = 2*j)//heap heaps are stored in the form of complete binary tree{//find the right pos for currPosif(j < lastPos && maxHeap.heapArr[j] < maxHeap.heapArr[j+1]) j++; //j denotes the bigger childif(maxHeap.heapArr[j] > temp){maxHeap.heapArr[currPos] = maxHeap.heapArr[j];currPos = j;}elsebreak;}maxHeap.heapArr[currPos] = temp;}void createmaxHeap(MaxHeap& maxHeap){/*time complexity: O(n) */int currPos = (maxHeap.currSize)/2;while(currPos >= 1){siftDown(maxHeap, currPos, maxHeap.currSize);currPos --;}}void heapSort(MaxHeap& maxHeap){createmaxHeap(maxHeap);for(int i = maxHeap.currSize; i >=2; i--){swap(maxHeap.heapArr[1], maxHeap.heapArr[i]);siftDown(maxHeap, 1, i-1);}}void myPrint(){for(int i =1; i <= N; i++){cout<<maxHeap.heapArr[i]<<" ";}cout<<endl;}int main(){myPrint();heapSort(maxHeap);myPrint();return 0;}

Iii. Quick sorting(1) Basic Ideas: An improvement on Bubble Sorting during quick sorting. The basic idea is to split the elements to be sorted into two independent parts by one sort.AverageIt is smaller than the other element, and the two parts can be recursively sorted to achieve the whole sequence order. It can be seen that fast sorting is also based on the sub-governance mode.(2) Algorithm Description: Array to be sorted: A [p... R]. The Splitting Process for sorting is as follows:

  • Decomposition: Array A [p... r] is divided into two (possibly empty) Sub-arrays A [p... q-1] And A [q + 1... r], so that A [p... each element in q-1] is less than or equal to A [q], and A [q + 1... the elements in r] are greater than or equal to A [q]. Here A [q] is called pivot and subscript q. It is calculated in A division. It can be seen that after A division, A [q] is in its final position.
  • Solution: Uses recursive call to quickly sort sub-arrays A [p... q-1] And A [q + 1... r.
  • Merge: Because the two subarrays are sorted in place, merging them requires no operation: the entire A [p... r] is ordered.
The entire process can be described as follows: the intermediate state of partition can be expressed as follows: (3) time complexity: Suppose the Run Time of the Quick Sort is T (n)
  • Worst Case Division: The partition behavior occurs in the worst case. The two regions generated during the division process contain n-1 elements, 0 elements, and pivot elements, respectively. Assume that this asymmetric division occurs in each recursive call. The Division time cost is: @ (n) (because each element must be compared with the pivot element ), furthermore, because T (0) = @ (1) is returned after recursive embedding of an array of 0, the recursive equation of the algorithm Runtime is T (n) = T (n-1) + T (0) + @ (n) = T (n-1) + @ (n), where T (n) =@ (N ^ 2).
  • Best case Division: InPartitionIn the most balanced division possible, the size of the two subproblems cannot exceed n/2, and the size of one side is floor (n/2 ), floor (n/2)-1 on the other side, with Pivot elements in the middle. The recursive equation of the running time is T (n) <= 2 T (n/2) + @ (n), which is obtained by the main theorem: T (n) =O (nlgn).
  • Balanced Division: Because the average running time of quick sorting is very similar to the running time of the best condition, quick sorting generally has good performance. Actually:Any division by constant ratio produces a recursive tree with a depth of @ (lgn ).(Not the worst case: @ (N). These can be considered as a balanced division, and because the cost of each layer is O (n ), therefore, the total running time isO (nlgn)(For detailed analysis, see section 7.2 p88 of Introduction to algorithms ).
Conclusion: Even when the best and worst division are distributed across layers, the running time of the quick sorting is the same as that of the best Division. It is still: O (nlgn ), it is only because the Changshu factor hidden in olog is slightly larger.
(4) Algorithm Implementation
#include <iostream>using namespace std;const int N = 5;int a[N+1] = {-1, 3, 4, 2, 1, 5};void swap(int& a, int& b){if(a != b){int temp =a;a = b;b = temp;}}int Partition(int a[], int low, int high){int pivotValue = a[high];int i = low-1;for(int j = low; j <= high-1; j++){if(a[j] <= pivotValue){i = i+1;swap(a[i], a[j]);}}swap(a[i+1], a[high]);return i+1;}void QuickSort(int a[], int left, int right){if(left < right){int pivotPos = Partition(a, left, right);QuickSort(a, left, pivotPos-1);QuickSort(a, pivotPos+1, right);}}void myPrint(){for(int i =1; i <= N; i++){cout<<a[i]<<" ";}cout<<endl;}int main(){myPrint();QuickSort(a,1,N);myPrint();return 0;}

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.