Knowing & Doing 2022-08-06 18:15:05 阅读数:595
排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.
稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的.例如:
内部排序:数据元素全部放在内存中的排序.
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序.
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 .实际中我们玩扑克牌时,就用了插入排序的思想.
Direct insertion sort is similar to the code card when we play poker,如上面左图所示.
At that time came again a red peach9,After I compare in turn.红桃A比9大,The red peachA就往后移动一位;Then compare the red peachK,比9大,红桃K也向后移动一位…依次类推,The red peach until10,红桃10也比9大,红桃10向后移动一位,把红桃9Inserted into the front of the.这就是插入排序.
步骤如下:
插入排序,Like a code card;从后往前,依次比较;
The head back,Those who stay;找准位置,插入其中.
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 直接插入排序 * @param array */
public static void insertSort(int[] array) {
for(int i = 1;i < array.length;i++) {
int tmp = array[i];
int j = i-1;
for (; j >= 0 ; j--) {
if(array[j] > tmp) {
array[j+1] = array[j];
}else {
//array[j+1] = tmp;
break;
}
}
array[j+1] = tmp;
}
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
insertSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
- 时间复杂度:O(N^2),最坏情况下,Array is completely reverse the situation,Its time complexity is an arithmetic progression.
- 空间复杂度:O(1),Do not create additional space.
- 稳定性:稳定
- 适用场景:当数据量小,并且已经趋于有序的时候,使用直接插入排序.
希尔排序是希尔(Donald Shell) 于1959年提出的一种排序算法.希尔排序也是一种插入排序,It is a direct insertion sort after the improved version of a more efficient,也称为缩小增量排序,同时该算法是冲破O(N^2)的第一批算法之一.
我们可以发现,In the process of hill sort,With the continuous decrease of number of clusters,The overall data more and tend to order.当gap=1时,Is equivalent to the overall carried out a direct insertion sort,At this point we need to grasp two:
The discussion about how to group:
In hill sorting exactly how the group is the most efficient,众说纷纭,Also presents different views in different books.But as we previously mentioned,No matter which kind of points method,最后一个增量值必须等于1.
步骤如下:
希尔排序,分而治之;分成多组,Each order;
增量序列,In the end is a;提高效率,希尔排序.
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 希尔排序 */
public static void shellSort(int[] array){
int gap = array.length;
while (gap > 1){
shell(array,gap);
gap /= 2;
}
shell(array,1);
}
private static void shell(int[] array, int gap) {
for(int i = gap;i < array.length;i++) {
int tmp = array[i];
int j = i-gap;
for (; j >= 0 ; j -= gap) {
if(array[j] > tmp) {
array[j+gap] = array[j];
}else {
break;
}
}
array[j+gap] = tmp;
}
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
shellSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
- 时间复杂度:与增量有关,Is by taking incremental(gap)的一个函数.According to the YanWeiMin versions,为O(N1.3)~O(N1.5).
- 空间复杂度:O(1),Do not create additional space.
- 稳定性:不稳定
- 适用场景:当数据量较大时,Hill sorting can be used,降低时间复杂度,对直接插入排序进行优化.
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 .
步骤如下:
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 选择排序 * @param */
public static void selectSort(int[] array) {
for (int i = 0; i < array.length; i++) {
int minIndex = i;
for (int j = i+1; j < array.length; j++) {
if(array[j] < array[minIndex]) {
minIndex = j;
}
}
swap(array,minIndex,i);
}
}
private static void swap(int[] array,int i,int j) {
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
selectSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
- 时间复杂度:O(N*N).
- 空间复杂度:O(1),Do not create additional space.
- 稳定性:不稳定
- 适用场景:Usually not how with.
堆排序(Heapsort) 是指利用堆这种数据结构所设计的一种排序算法.堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点.需要注意的是排升序要建大堆,排降序建小堆.
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 堆排序 * @param array */
public static void heapSort(int[] array){
createHeap(array); //建立大根堆
int end = array.length - 1;
while (end >= 0){
swap(array,0,end);
shiftDown(array,0,end);
end--;
}
}
private static void createHeap(int[] array) {
for(int p = (array.length-1-1)/2; p >= 0;p--){
shiftDown(array,p,array.length);
}
}
private static void shiftDown(int[] array, int root, int len) {
int parent = root;
int child = (2*parent) + 1;
while(child < len){
if (child + 1 < len && array[child] < array[child+1]) {
child++;
}
if(array[child] > array[parent]){
swap(array,child,parent);
parent = child;
child = 2*parent + 1;
} else {
break;
}
}
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
heapSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
- 时间复杂度:O(N*logN).
- 空间复杂度:O(1),Do not create additional space.
- 稳定性:不稳定
冒泡排序 是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误,就把它们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端.
对于冒泡排序,After each round of sorts,The last element of the wheels will be ordered.也就是说,Bubble sort is a constant element will be the biggest"冒泡"At the end of the order.
具体步骤如下:
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 冒泡排序 * @param array */
public static void bubbleSort(int[] array){
for (int i = 0; i < array.length-1; i++) {
boolean flag = false;
for (int j = 0; j < array.length-1-i; j++) {
if(array[j] > array[j+1]){
flag = true;
int tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
}
if(!flag){
break;
}
}
}
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
bubbleSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
- 时间复杂度:O(N^2).
- 空间复杂度:O(1),Do not create additional space.
- 稳定性:稳定
4.使用场景:If the array is tend to be more orderly,使用冒泡[]Sorting is very good.在进行优化后,如果数组有序,So the time complexity of the bubble sort will reachO(N).
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序.
具体步骤如下:
步骤1:从数列中挑出一个元素,称为 “基准”(pivot );
步骤2:重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边).在这个分区退出之后,该基准就处于数列的中间位置.这个称为分区(partition)操作;
步骤3:递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序.
我们要知道,Could be divided into both the left and right sides of the interval according to the basic value method there are many kinds of,Here I will introduce:Hoare法,挖坑法,And both before and after the pointer method.这三种方法,To dig a hole method is the most common again.
特别注意:
- If it is on the left side of elements as the basic value,那么右边的high先移动;If it is left and right boundary element as the basic value,那么左边的low先移动.
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 快速排序 * @param array */
public static void quickSort(int[] array) {
quick(array,0,array.length-1);
}
private static void quick(int[] array, int left, int right) {
if(left >= right) return;
int pivot = partitionHoare(array,left,right);
quick(array,left,pivot-1);
quick(array,pivot+1,right);
}
private static int partitionHoare(int[] array, int low, int high) {
//To select the first element in the array as a benchmark for example
//首先,Need to save the first element of the array
int i = low;
int tmp = array[low];
while(low < high){
//1.如果low与highNo cross andhigh下标元素>=基准值,high--继续找
while(low < high && array[high] >= tmp){
high--;
}
//出循环,说明此时highIs the number of you are looking for
//2.如果low与highNo cross andlow下标元素<=基准值,low++继续找
while(low < high && array[high] <= tmp){
low++;
}
//出循环,说明此时lowIs the number of you are looking for
swap(array,low,high);
}
//出循环,此时low与high相遇,Will meet again in the value of the basic value and exchange
swap(array,low,i);
return low;
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
quickSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 快速排序 * @param array */
public static void quickSort(int[] array) {
quick(array,0,array.length-1);
}
private static void quick(int[] array, int left, int right) {
if(left >= right) return;
int pivot = partitionHole(array,left,right);
quick(array,left,pivot-1);
quick(array,pivot+1,right);
}
/* 这是Hole法 */
private static int partitionHole(int[] array, int low, int high) {
int tmp = array[low];
while(low < high){
while(low < high && array[high] >= tmp){
high--;
}
array[low] = array[high];
while(low < high && array[low] <= tmp){
low++;
}
array[high] = array[low];
}
array[low] = tmp;
return low;
}
// private static void insertSortRange(int[] array, int left, int right) {
// }
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
quickSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 快速排序 * @param array */
public static void quickSort(int[] array) {
quick(array,0,array.length-1);
}
private static void quick(int[] array, int left, int right) {
if(left >= right) return;
int pivot = partitionPoint(array,left,right);
quick(array,left,pivot-1);
quick(array,pivot+1,right);
}
/* 前后指针法 */
private static int partitionPoint(int[] array, int left, int right) {
int d = left + 1;
int pivot = array[left];
for (int i = left + 1; i <= right; i++) {
if (array[i] < pivot) {
swap(array, i, d);
d++;
}
}
swap(array, d - 1, left);
return d - 1;
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
quickSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
1.时间复杂度:O(N*logN).
但是,当数组有序时,At this time will be a single branch of the binary tree is constructed,Its time complexity toO(N2).Some people talk,Quick sort degradation has become a bubble sort at this time,Because of their time complexity is the same,But that's not serious,Quick sort and sort bubble sort is two completely different,The thought of quick sort bubble sort does not meet the.
2.空间复杂度: 最好情况下:O(logN);最坏情况下,O(N),Is a single branch tree.
3.稳定性:不稳定
When you want to use quick sort,Preferred method of digging holes,Hoare次之,The last is pointer method before and after.
其次,In the light of the quick sort space complexity is higher,Need to open up a lot of memory space on the stack,So we need to optimize the quick sort of,Can use.Optimization method basically has the following several kinds of:
每次递归的时候,The data are in slowly weave and orderly!!当数据量少且趋于有序的时候,我们可以使用直接插入排序进行优化.
package Sort;
import java.util.Arrays;
public class TestSort {
/** * 快速排序 * @param array */
public static void quickSort(int[] array) {
quick(array,0,array.length-1);
}
private static void quick(int[] array, int left, int right) {
if(left >= right) return;
//在某个区间的时候,使用直接插入排序{The comparison of optimal range}
if(right-left+1 <= 5){
//进行插入排序
insertSortRange(array,left,right);
return;
}
int pivot = partitionHole(array,left,right);
quick(array,left,pivot-1);
quick(array,pivot+1,right);
}
private static void insertSortRange(int[] array, int left, int right) {
for(int i = left+1;i <= right;i++) {
int tmp = array[i];
int j = i-1;
for (; j >= left ; j--) {
if(array[j] > tmp) {
array[j+1] = array[j];
}else {
//array[j+1] = tmp;
break;
}
}
array[j+1] = tmp;
}
}
/* 这是Hole法 */
private static int partitionHole(int[] array, int low, int high) {
int tmp = array[low];
while(low < high){
while(low < high && array[high] >= tmp){
high--;
}
array[low] = array[high];
while(low < high && array[low] <= tmp){
low++;
}
array[high] = array[low];
}
array[low] = tmp;
return low;
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
quickSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
需要注意的是,This method has not been fundamentally achieve optimization.
快速排序的运行时间与划分是否对称有关.最坏情况下,每次划分过程产生两个区域分别包含n-1个元素和1个元素,其时间复杂度会达到O(N^2).在最好的情况下,每次划分所取的基准都恰好是中值,即每次划分都产生两个大小为n/2的区域.此时,快排的时间复杂度为O(NlogN).So it is very important to the choice of benchmark for fast row.
在前面的文章中,Use array the leftmost element as the basic value.随机选取基准,Is in all elements of the rest of the elements in addition to the left,Randomly selected to an element as the basic value,This value with the leftmost element exchange.其余步骤,With the above mentioned the quick sort method is the same.
Although using basic random benchmarks can solve to row array orderly situation,But because of this randomness,Array will have impact on other cases(If the array elements are random,Using a fixed benchmark often better than random benchmark).随机数算法随机选择一个元素作为划分基准,算法的平均性能较好,从而避免了最坏情况的多次发生.However, random algorithm, after all, is a test of character learning,Selection is also difficult to guarantee the basic value to a more appropriate.
Such as shown below to sort an array,If we are in addition to the first element6All elements of the rest of the outside in,Select an element in the method of randomly selected benchmark,If you choose to just1,那么恭喜你,Successfully improved the sort of time,Reduce the efficiency of sorting.所以可见,Randomly selected is not a satisfactory way.
package Sort;
import java.sql.SQLOutput;
import java.util.Arrays;
import java.util.Random;
public class TestSort {
/** * 快速排序 * @param array */
public static void quickSort(int[] array) {
quick(array,0,array.length-1);
}
private static void quick(int[] array, int left, int right) {
if(left >= right) return;
// 1.在某个区间的时候,使用直接插入排序{The comparison of optimal range}
if(right-left+1 <= 5){
//进行插入排序
insertSortRange(array,left,right);
return;
}
// 2.随机选取基准法
int index = RandomIndex(array,left,right);
swap(array,left,index);
//int pivot = partitionHoare(array,left,right);
int pivot = partitionHole(array,left,right);
//int pivot = partitionPoint(array,left,right);
quick(array,left,pivot-1);
quick(array,pivot+1,right);
}
private static int RandomIndex(int[] array, int left, int right) {
Random random = new Random();
int index = random.nextInt(right);
return index;
}
private static void insertSortRange(int[] array, int left, int right) {
for(int i = left+1;i <= right;i++) {
int tmp = array[i];
int j = i-1;
for (; j >= left ; j--) {
if(array[j] > tmp) {
array[j+1] = array[j];
}else {
//array[j+1] = tmp;
break;
}
}
array[j+1] = tmp;
}
}
/* 这是Hole法 */
private static int partitionHole(int[] array, int low, int high) {
int tmp = array[low];
while(low < high){
while(low < high && array[high] >= tmp){
high--;
}
array[low] = array[high];
while(low < high && array[low] <= tmp){
low++;
}
array[high] = array[low];
}
array[low] = tmp;
return low;
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
quickSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
The above code USES a randomly selected benchmark method.因为数据量很少,Also it will be difficult to demonstrate its efficiency of.We will in this,A simple test on the efficiency of various sorting.
Because of the random selected benchmark method"随机性"过高,Difficult to ensure proper benchmark to.A more commonly used algorithm is"三数取中法". As shown in the following figure arrays, for example,三数取中,指的是left,right,mid三数,其中mid = left+(right-left)>>>1;
As shown in the figure below array,在第一轮排序中,我们会在4,6,8Select the middle number and the size of the current benchmark4交换,也就是选择6与4交换.This is sorted in each,Can be as much as possible, ensure uniform group,避免出现"单分支"的情况,To improve the efficiency of algorithm.
package Sort;
import java.sql.SQLOutput;
import java.util.Arrays;
import java.util.Random;
public class TestSort {
/** * 快速排序 * @param array */
public static void quickSort(int[] array) {
quick(array,0,array.length-1);
}
private static void quick(int[] array, int left, int right) {
if(left >= right) return;
// 1.在某个区间的时候,使用直接插入排序{The comparison of optimal range}
if(right-left+1 <= 5){
//进行插入排序
insertSortRange(array,left,right);
return;
}
// 三数取中法
int index = medianOfThreeIndex(array,left,right);
swap(array,left,index);
int pivot = partitionHole(array,left,right);
quick(array,left,pivot-1);
quick(array,pivot+1,right);
}
private static int medianOfThreeIndex(int[] array, int left, int right) {
int mid = left + ((right-left)>>>1);
//int mid = (left + right) / 2;
if(array[left] < array[right]) {
if(array[mid] < array[left]) {
return left;
}else if( array[mid] > array[right]) {
return right;
}else {
return mid;
}
}else {
if(array[mid] < array[right]) {
return right;
}else if(array[mid] > array[left]) {
return left;
}else {
return mid;
}
}
}
private static void insertSortRange(int[] array, int left, int right) {
for(int i = left+1;i <= right;i++) {
int tmp = array[i];
int j = i-1;
for (; j >= left ; j--) {
if(array[j] > tmp) {
array[j+1] = array[j];
}else {
//array[j+1] = tmp;
break;
}
}
array[j+1] = tmp;
}
}
/* 这是Hole法 */
private static int partitionHole(int[] array, int low, int high) {
int tmp = array[low];
while(low < high){
while(low < high && array[high] >= tmp){
high--;
}
array[low] = array[high];
while(low < high && array[low] <= tmp){
low++;
}
array[high] = array[low];
}
array[low] = tmp;
return low;
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
quickSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
对于"快排"的优化,可以参考这篇文章:
Quick sort of optimizing operation
非递归实现快速排序,Need to use the stack this data structure.需要注意的是,To realize non-recursive quick sort,Must be on the basis of sorting in the round.
package Sort;
import java.sql.SQLOutput;
import java.util.Arrays;
import java.util.Random;
import java.util.Stack;
public class TestSort {
/* 这是Hoare法 */
private static int partitionHoare(int[] array, int low, int high) {
//To select the first element in the array as a benchmark for example
//首先,Need to save the first element of the array
int i = low;
int tmp = array[low];
while(low < high){
//1.如果low与highNo cross andhigh下标元素>=基准值,high--继续找
while(low < high && array[high] >= tmp){
high--;
}
//出循环,说明此时highIs the number of you are looking for
//2.如果low与highNo cross andlow下标元素<=基准值,low++继续找
while(low < high && array[high] <= tmp){
low++;
}
//出循环,说明此时lowIs the number of you are looking for
swap(array,low,high);
}
//出循环,此时low与high相遇,Will meet again in the value of the basic value and exchange
swap(array,low,i);
return low;
}
/** * 非递归实现快速排序 * @param array */
public static void quickSortNor(int[] array){
Stack <Integer> stack = new Stack<>();
int left = 0;
int right = array.length - 1;
//Must be established on the basis of a sort of
int pivot = partitionHoare(array,left,right);
//On the left more than two data,需要入栈
if(pivot > left+1){
stack.push(left);
stack.push(pivot-1);
}
if(pivot < right-1){
stack.push(pivot+1);
stack.push(right);
}
while(!stack.isEmpty()){
right = stack.pop();
left = stack.pop();
pivot = partitionHoare(array,left,right);
//On the left more than two data
if(pivot > left+1){
stack.push(left);
stack.push(pivot-1);
}
if(pivot < right-1){
stack.push(pivot+1);
stack.push(right);
}
}
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
quickSortNor(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并.
Merge sort is divided into two parts:分解+合并.
具体步骤如下:
package Sort;
import java.sql.SQLOutput;
import java.util.Arrays;
import java.util.Random;
import java.util.Stack;
public class TestSort {
/** * 归并排序 * @param array */
private static void merge(int[] array,int low,int mid,int high) {
int s1 = low;
int e1 = mid;
int s2 = mid+1;
int e2 = high;
int[] tmpArr = new int[high-low+1];
int k = 0;//代表tmpArr的下标
//证明两个段都有数据
while (s1 <= e1 && s2 <= e2) {
if(array[s1] <= array[s2]) {
tmpArr[k++] = array[s1++];
}else {
tmpArr[k++] = array[s2++];
}
}
//剩余元素,全部挪过来
while (s1 <= e1) {
tmpArr[k++] = array[s1++];
}
//剩余元素,全部挪过来
while (s2 <= e2) {
tmpArr[k++] = array[s2++];
}
for (int i = 0; i < tmpArr.length; i++) {
array[i+low] = tmpArr[i];
}
}
private static void mergeSortInternal(int[] array,int low,int high) {
if(low >= high) return;
int mid = low+((high-low)>>>1);
mergeSortInternal(array,low,mid);
mergeSortInternal(array,mid+1,high);
merge(array,low,mid,high);
}
public static void mergeSort(int[] array) {
mergeSortInternal(array,0,array.length-1);
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
mergeSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
package Sort;
import java.sql.SQLOutput;
import java.util.Arrays;
import java.util.Random;
import java.util.Stack;
public class TestSort {
private static void merge(int[] array,int low,int mid,int high) {
int s1 = low;
int e1 = mid;
int s2 = mid+1;
int e2 = high;
int[] tmpArr = new int[high-low+1];
int k = 0;//代表tmpArr的下标
//证明两个段都有数据
while (s1 <= e1 && s2 <= e2) {
if(array[s1] <= array[s2]) {
tmpArr[k++] = array[s1++];
}else {
tmpArr[k++] = array[s2++];
}
}
//剩余元素,全部挪过来
while (s1 <= e1) {
tmpArr[k++] = array[s1++];
}
//剩余元素,全部挪过来
while (s2 <= e2) {
tmpArr[k++] = array[s2++];
}
for (int i = 0; i < tmpArr.length; i++) {
array[i+low] = tmpArr[i];
}
}
/** * \非递归的归并排序 * @param array */
public static void mergeSortNor(int [] array){
int gap = 1;
while(gap < array.length){
for (int i = 0; i < array.length; i+= 2*gap) {
int left = i;
int mid = left+gap-1;
if(mid >= array.length){
mid = array.length-1;
}
int right = mid+gap;
if(right >= array.length){
right = array.length-1;
}
merge(array,left,mid,right);
}
gap *= 2;
}
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
mergeSortNor(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
外部排序:排序过程需要在磁盘等外部存储进行的排序
前提:内存只有 1G,需要排序的数据有 100G
因为内存中因为无法把所有数据全部放下,所以需要外部排序,归并排序是最常用的外部排序.
具体步骤:
图解:
The above order is based on the comparison of sorts.接下来,I will introduce three kind of based on the comparison of sequence.
计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用.
What is the principle of dove nest?简单来说就是,桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面放不少于两个苹果.这一现象就是我们所说的“抽屉原理”. 抽屉原理的一般含义为:“如果每个抽屉代表一个集合,每一个苹果就可以代表一个元素,假如有n+1个元素放到n个集合中去,其中必定有一个集合里至少有两个元素.” 抽屉原理有时也被称为鸽巢原理.它是组合数学中一个重要的原理.
基本步骤是:
注意
- 在实际排序中,Don't always to meet like0~9So reveals the human nature brilliant subject.一种情况是,We need to count90-99之间的数据,Currently we will not apply to the array size for100的空间,而是将90This element is the number of occurrences of record in0下标位置,91This element is the number of occurrences of record in1下标位置,依次类推即可.Only when the print will need to the corresponding subscript plus the offset can be.
- Another situation is more common,Such as we need to count the data is not closely aligned,But there is no rule,如下图所示:
This kind of situation will need to first calculate the data of the maximum and the minimum,But the amount of the array size is[最大值-最小值+1].不难发现,There are a lot of space will be wasted at this time,这也说明,计数排序的时间复杂度andSpace complexity is closely related to the scope of data sorting,I will be in the back of the summary about this problem.
package Sort;
import java.sql.SQLOutput;
import java.util.Arrays;
import java.util.Random;
import java.util.Stack;
public class TestSort {
/** * 计数排序 * @param array */
public static void countSort(int [] array) {
int min = array[0];
int max = array[0];
for (int i = 1; i < array.length; i++) {
if(min > array[i]){
min = array[i];
}
if(max < array[i]){
max = array[i];
}
}
//此时min和maxRespectively is the maximum and the minimum of data
int[] arr = new int[max-min+1];
for (int i = 0; i < array.length; i++) {
arr[array[i]-min]++;
}
int k = 0;
for (int i = 0; i < arr.length; i++) {
int count = arr[i];
while(count-- != 0){
array[k++] = (i+min);
}
}
}
public static void main(String[] args) {
int[] array = {
2,1,53,4,5,10,9,36,23,6,19};
System.out.println("排序前:"+ Arrays.toString(array));
countSort(array);
System.out.println("排序后:"+ Arrays.toString(array));
}
}
注意
Although I have written you code is can guarantee the stability of,但是我们可以通过一些方法,The result of quick sort is stable.具体操作如下:
Radix sort in count sorting is improved on the basis of,将排序工作拆分为多个阶段,Sort the integer data, for example,Every stage only according to a digital sorting,一共排序K轮(K为数据位数).
Bucket sort is similar to radix sort,,不同之处在于,When the bucket sort is could be divided into different interval data,在每个区间(桶)After the data sorted,Again, in turn, out of the barrel,Back in the original sequence.
步骤:
Above is all the sorting algorithm!
We must master7More sort of idea and code,For three of comparative sequence,Only need to master the basic idea can be.重在理解,及时复盘,才能事半功倍!!
copyright:author[Knowing & Doing],Please bring the original link to reprint, thank you. https://en.javamana.com/2022/218/202208061752468121.html