Algorithm - Quick Sort

Quicksort is probably the most widely used sorting algorithm. The reason is that it is simple to implement, works with a wide variety of input data, and is much faster than other sorting algorithms in general applications.

Features : ① It is in-situ sorting (only a small auxiliary stack is required); ② and the time required to sort an array of length N is proportional to NlgN.

The connection and difference with merge sort :

The same point: both are a divide-and-conquer sorting algorithm, which divides an array into two sub-arrays.

Differences: ①Merge sort is divided into two sub-arrays and sorted separately, and the ordered sub-arrays are merged to sort the entire array; while quick sort is that when both sub-arrays are in order, the entire array is naturally ordered. (the split position depends on the contents of the array).

The quicksort function is implemented as follows:

public class Quick{
	public static void sort(Comparable [] a) {
		StdRandom.shuffle(a);//消除对数组的依赖
		sort(a,0,a.length-1);
	}
	private static void sort(Comparable[] a,int lo,int hi) {
		if(hi<=lo)return;
		int j=partition(a,lo,hi);//切分
		sort(a,lo,j-1);//将左半部分排序
		sort(a,j+1,hi);//将右半部分排序
	}
}

Quick sort division

	public static int partition(Comparable [] a,int lo,int hi) {
		//将数组切分
		int i=lo,j=hi+1;//设置左右扫描指针
		Comparable v=a[lo];//将数组第一个数a[lo]设置为切分元素v
		while(true) {
			//扫描左右,检查扫描是否结束并交换元素
			while(less(a[++i],v))if(i==hi)break;//左侧从第二个数开始遍历,直到找到大于切分元素的值
			while(less(v,a[--j]))if(j==lo)break;//右侧从最后一个元素开始遍历,直到找到小于切分元素的值
			if(i>=j)break;
			each(a,i,j);//交换i和j指向的元素
		}
		each(a,lo,j);//将a[lo]和j最后指向的元素交换位置,已知j指向的元素都是小于切分元素,即a[lo]的。
		return j;//达成a[lo...j-1]<=a[j]<=a[j+1..hi]
	}

Analysis : Set the first value of the array as the segmented element, scan from left to right with the i pointer, and scan from right to left with the j pointer. When i scans to a value greater than the split element, stop moving and point to it; when j scans to a value less than the split element, stop moving and point to it. Swap the elements pointed to by i and j. Stop when i>=j or when i and j are out of bounds, and finally exchange the segmented element and the element pointed to by the j pointer. In reality, the left side of the segmented element is smaller than it, and the right side is larger than it.

Note : 1. Don't cross the boundary: If the segmented element is the smallest or largest element in the array, we must prevent the pointer from running out of the array boundary. Can be improved with sentinels.

            ②Maintain randomness: The selection of segmentation elements has a great impact on the performance of the algorithm. Maintaining randomness can select the appropriate segmentation elements as much as possible.

            ③ Terminate the loop: A common mistake is not to consider that the array may contain other elements with the same value as the split element.

            ④ To deal with the situation where the value of the segmented element is repeated: the left scan is changed to less than or equal to, and the right scan is changed to greater than or equal. Although this may unnecessarily swap some elements of equal value, it can avoid the algorithm running time to become square.

Performance : The inner loop of the quicksort split method compares the array element with a constant value using an increasing index. This brevity is also an advantage of quicksort. For example, merge sort and hill sort are generally slower than quicksort because they also move data in the inner loop.

Sorting a duplicate-free array of length N, quicksort requires on average 2NlnN comparisons (and 1/6 swaps).

Quicksort requires at most about N²/2 comparisons, but shuffling the array prevents this.

Algorithm improvements :

①Switch to insertion sort: Improve to use insertion sort when encountering small arrays, replace if(hi<=lo)return; with if(hi<=lo+M){Insertion,sort(a,lo,hi); return;}. The optimal value of the conversion parameter is suitable for system dependence, but any value between 5 and 15 is satisfactory in most cases.

②Three sampling and cutting

③Entropy-optimized sorting: quick sorting of three-way segmentation. We already know that merge sort is optimal, how to break through its lower bound? The answer to this question talks about worst-case performance for arbitrary inputs, and we already know something about the input array at the time of the discussion. Merge sort does not guarantee optimal performance for inputs with repeated elements distributed with arbitrary probability.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325315405&siteId=291194637