Animation | must be thorough before the end of four years of college sorting algorithm

Now students learning sorting algorithms, in addition to learning its principles algorithm, code implementation outside, as a college student is often more important to learn how to evaluate, analyze a sorting algorithm. For any sort programmer, probably not unfamiliar. Most programming languages. They also have a sort function. In the usual projects, we also often used to sort. Sorting is very important! This chapter starts with a start how to analyze algorithms to analyze the sorting algorithm must master before the end of those four years of college into the evolutionary cycle!
@

Of course, you can start thinking a minute or two with this issue, we begin the following content! Also note that I marked red font, often the focus from the eyes or humble .

How to analyze a "sorting algorithm"?

1, the sorting algorithm efficiency

For the analysis of the efficiency of sorting algorithms, we generally will be measured from the three aspects:

1.1. The best, the worst, the average time complexity

When we analyze the time complexity of sorting algorithms, respectively, to give the best case, worst case time complexity of the average case. In addition, you have to say the best, original data to be sorted worst time complexity corresponds to what.

Why should we distinguish between these three time complexity of it? First, some sort algorithm will differentiate, to contrast good, so we had better do it distinction. Second, for data to be sorted, some close to the orderly, and some completely disordered. Different degree of order data for ordering the execution time is certainly influential, we need to know sort algorithm performance under different data.

1.2. Time complexity coefficient, a constant, low-level

We know that the reaction time complexity is a growing trend of large-scale data n the time, so when it represents ignores coefficient, a constant, low-level. But the actual software development, we sort of could be 10, 100, 1000 such a small scale data, so, at the same time performance of the algorithm sort order time complexity contrast, we want coefficient, constant, low-level is also taken into account.

1.3. Comparison of the number and exchange (or mobile) number

This section and the next are telling the sorting algorithm based on the comparison. Sorting algorithm based on the implementation of the comparison involves two operations, one is to compare the size of the element, the other element is moved or exchanged. So, if when we analyze the efficiency of sorting algorithms, it should be the number of comparisons and exchange (or mobile) number is also taken into account.

2, sorting algorithm memory consumption

We have said before, memory consumption algorithm can be measured by the spatial complexity, sorting algorithm is no exception. However, the spatial complexity of sorting algorithms, we also introduced a new concept, in situ sequencing (Sorted in place). Situ sorting algorithm, which refer to the spatial complexity is O (1) sorting algorithm .

3, the sorting algorithm stability

Do not ignore the stability, only with efficiency and memory consumption to measure the quality of the sorting algorithm is not enough. For sorting algorithms, we have an important metric stability. The concept is that there is an element of equal value if the sequence to be sorted, after sorting, the original order of equal elements between unchanged.

Let me explain with an example. For example, we have a set of data 2,9,3,4,8,3, in accordance with the following descending order is 2,3,3,4,8,9.
Here Insert Picture Description
This data set has two 3. After sorting algorithm of some sort, if two 3 before and after the order has not changed, then we put this sorting algorithm is called stable sorting algorithm ; if changes occur before and after the order, and that the corresponding sorting algorithm is called unstable sorting algorithm .

You may want to ask, which the former two 3, which have anything to do after ah, stable unstable what does it matter? Why should we investigate the stability of the algorithm to sort it?

Many data structures and algorithms course, talking about the sort of time, are exemplified by an integer, but in real software development, we want to sort often not a simple integer, but a set of objects, we need to follow an object key to sort.

For example, we now "order" sort to give electricity suppliers trading system. Order has two properties, one single time, the other is the order amount. If we now have 100,000 orders, we hope that in accordance with the amount of orders from small to large order data. For the same amount of orders, we hope to follow orders from morning to night time ordered. For such a sort needs, how do we do it?

The method was first thought was: Let's sort the data according to the amount of the order, and then, again traversing orders data after sorting, and then sorted according to the time between orders the same amount each cell. This ordering is not difficult to understand the idea, but the implementation will be very complicated.

With stable sorting algorithm, this problem can be very simple to solve. Solutions like this: Let's give orders sorted by order time, note that in accordance with the order of time, not money. After sequencing is complete, we use the stable sort algorithm, re-sorted according to the order amount. After twice ordering, order data is in accordance with the amount we get from small to large, the same amount of orders in accordance with orders from morning to night time sort of. why?

Stable sorting algorithm can maintain the same amount of two objects, unchanged before and after the order after sorting . After the first order, all orders in accordance with orders from morning to night ordered a time. In the second sort, we use the sorting algorithm is stable, so the second time after sorting, the same amount of orders remained at a single time from morning to night and orderly.
Here Insert Picture Description

Here, the analysis a "sorting algorithm" to the end, you get to it? Next, we enter the actual algorithm analysis.

Begin to analyze bubble "sort algorithm"

1. bubble sort described

Description bubble sort: Bubble sort operation only two adjacent data. Every bubble will operate on two adjacent elements are compared to see if it meets the size requirements of the relationship. If not, let Talia interchangeable. A bubbling make at least one element is moved to its position should be repeated n times, to complete the work of the n sorted data.

2. graphic bubble sort

Here Insert Picture Description
如果还是不能一眼看出其灵魂,没事,我还有一招:
Here Insert Picture Description
怎么样,够不够直观,就是有点慢,哈哈~

3.代码实现冒泡排序
package BubbleSort;
import java.util.Arrays;

public class generalBubble {
   public static void main(String[] args) {
        int[] arr=new int[] {5,7,2,9,4,1,0,5,8,7};
        System.out.println(Arrays.toString(arr));
        bubbleSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    //冒泡排序
    public static void bubbleSort(int[]  arr) {
        //控制共比较多少轮
        for(int i=0;i<arr.length-1;i++) {
            //控制比较的次数
            for(int j=0;j<arr.length-1-i;j++) {
                if(arr[j]>arr[j+1]) {
                    int temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }

    }
}

测试效果:
Here Insert Picture Description

4.代码优化冒泡排序

实际上,刚讲的冒泡过程还可以优化。当某次冒泡操作已经没有数据交换时,说明已经达到完全有序,不用再继续执行后续的冒泡操作。我这里还有另外一个例子,这里面给6个元素排序,只需要4次冒泡操作就可以了。

// 冒泡排序,a表示数组,n表示数组大小
public void bubbleSort(int[] a, int n) {
  if (n <= 1) return;
 
 for (int i = 0; i < n; ++i) {
    // 提前退出冒泡循环的标志位
    boolean flag = false;
    for (int j = 0; j < n - i - 1; ++j) {
      if (a[j] > a[j+1]) { // 交换
        int tmp = a[j];
        a[j] = a[j+1];
        a[j+1] = tmp;
        flag = true;  // 表示有数据交换      
      }
    }
    if (!flag) break;  // 没有数据交换,提前退出
  }
}

现在,结合刚才我分析排序算法的三个方面,开始分析冒泡排序算法。

第一:冒泡排序是原地排序算法吗?

首先,原地排序算法就是特指空间复杂度是O(1)的排序算法,我在上文提及过的,再提一遍(我猜你们肯定没仔细看文章。。。)

冒泡的过程只涉及相邻数据的交换操作,只需要常量级的临时空间,所以它的空间复杂度为O(1),是一个原地排序算法。

第二:冒泡排序是稳定的排序算法吗?

在冒泡排序中,只有交换才可以改变两个元素的前后顺序。为了保证冒泡排序算法的稳定性,当有相邻的两个元素大小相等的时候,我们不做交换,相同大小的数据在排序前后不会改变顺序,所以冒泡排序是稳定的排序算法。

第三:冒泡排序的时间复杂度是多少?

最好情况下,要排序的数据已经是有序的了,我们只需要进行一次冒泡操作,就可以结束了,所以最好情况时间复杂度是O(n)。而最坏的情况是,要排序的数据刚好是倒序排列的,我们需要进行n次冒泡操作,所以最坏情况时间复杂度为O(n2),平均情况下的时间复杂度就是O(n2)。

开始分析“插入排序算法”

1.插入排序描述

插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

2.图解插入排序

Here Insert Picture Description
同样,我也准备了数字版的,是不是很贴心?
Here Insert Picture Description

3.代码实现插入排序
public class InsertSort {
    
    public static void main(String[] args) {
        int[] arr = new int[] {5,3,2,8,5,9,1,0};
        insertSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    //插入排序
    public static void insertSort(int[] arr) {
        //遍历所有的数字
        for(int i=1;i<arr.length;i++) {
            //如果当前数字比前一个数字小
            if(arr[i]<arr[i-1]) {
                //把当前遍历数字存起来
                int temp=arr[i];
                int j;
                //遍历当前数字前面所有的数字
                for(j=i-1;j>=0&&temp<arr[j];j--) {
                    //把前一个数字赋给后一个数字
                    arr[j+1]=arr[j];
                }
                //把临时变量(外层for循环的当前元素)赋给不满足条件的后一个元素
                arr[j+1]=temp;
            }
        }
    }
    
}

现在,结合刚才我分析排序算法的三个方面,开始分析插入排序算法。

第一:插入排序是原地排序算法吗?

从实现过程可以很明显地看出,插入排序算法的运行并不需要额外的存储空间,所以空间复杂度是O(1),也就是说,这是一个原地排序算法。

第二:插入排序是稳定的排序算法吗?

在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。

第三:插入排序的时间复杂度是多少?

如果要排序的数据已经是有序的,我们并不需要搬移任何数据。如果我们从尾到头在有序数据组里面查找插入位置,每次只需要比较一个数据就能确定插入的位置。所以这种情况下,最好是时间复杂度为O(n)。注意,这里是从尾到头遍历已经有序的数据。

如果数组是倒序的,每次插入都相当于在数组的第一个位置插入新的数据,所以需要移动大量的数据,所以最坏情况时间复杂度为O(n2)。

还记得我们在数组中插入一个数据的平均时间复杂度是多少吗?没错,是O(n)。所以,对于插入排序来说,每次插入操作都相当于在数组中插入一个数据,循环执行n次插入操作,所以平均时间复杂度为O(n2)。

开始分析“选择排序算法”

1.选择排序描述

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。

2.图解选择排序

Here Insert Picture Description

3.代码实现选择排序
public class SelectSort {

    public static void main(String[] args) {
        int[] arr = new int[] {3,4,5,7,1,2,0,3,6,8};
        selectSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    //选择排序
    public static void selectSort(int[] arr) {
        //遍历所有的数
        for(int i=0;i<arr.length;i++) {
            int minIndex=i;
            //把当前遍历的数和后面所有的数依次进行比较,并记录下最小的数的下标
            for(int j=i+1;j<arr.length;j++) {
                //如果后面比较的数比记录的最小的数小。
                if(arr[minIndex]>arr[j]) {
                    //记录下最小的那个数的下标
                    minIndex=j;
                }
            }
            //如果最小的数和当前遍历数的下标不一致,说明下标为minIndex的数比当前遍历的数更小。
            if(i!=minIndex) {
                int temp=arr[i];
                arr[i]=arr[minIndex];
                arr[minIndex]=temp;
            }
        }
    }

}
4.分析选择排序算法

选择排序算法是一种原地、不稳定的排序算法,最好时间复杂度情况:T(n) = O(n2) 最差时间复杂度情况:T(n) = O(n2) 平均时间复杂度情况:T(n) = O(n2)

开始分析“希尔排序算法”

1.希尔排序描述

希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。希尔排序是把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
希尔排序常规步骤:
1、选择增量gap=length/2
2、缩小增量继续以gap = gap/2的方式,n/2,(n/2)/2...1 ,有点晕了对吧,还是看图解吧哈哈~

Here Insert Picture Description
同样是二图(捂脸)
Here Insert Picture Description

3.代码实现希尔排序
public class ShellSort {

    public static void main(String[] args) {
        int[] arr = new int[] { 3, 5, 2, 7, 8, 1, 2, 0, 4, 7, 4, 3, 8 };
        System.out.println(Arrays.toString(arr));
        shellSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    public static void shellSort(int[] arr) {
        int k = 1;
        // 遍历所有的步长
        for (int d = arr.length / 2; d > 0; d /= 2) {
            // 遍历所有有元素
            for (int i = d; i < arr.length; i++) {
                // 遍历本组中所有的元素
                for (int j = i - d; j >= 0; j -= d) {
                    // 如果当前元素大于加上步长后的那个元素
                    if (arr[j] > arr[j + d]) {
                        int temp = arr[j];
                        arr[j] = arr[j + d];
                        arr[j + d] = temp;
                    }
                }
            }
            System.out.println("第" + k + "次排序结果:" + Arrays.toString(arr));
            k++;
        }
    }

}
4.分析希尔排序算法

希尔排序算法是一种原地、不稳定的排序算法,最好时间复杂度情况:T(n) = O(nlog2 n) 最差时间复杂度情况:T(n) = O(nlog2 n) 平均时间复杂度情况:T(n) =O(nlog2n) 

开始分析“快速排序算法”

1.快速排序描述

我们习惯性把它简称为“快排”。快排利用的也是分治思想。乍看起来,它有点像归并排序,但是思路其实完全不一样。通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
快速排序常规步骤:
1、从数列中挑出一个元素,称为 “基准”(pivot),一般第一个基数取第一个数;
2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3、递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

2.图解快速排序

Here Insert Picture Description
貌似上图太过于抽象,还是看下图吧,哈哈~
Here Insert Picture Description

3.代码实现快速排序
public class QuickSort {

    public static void main(String[] args) {
        int[] arr = new int[] {3,4,6,7,2,7,2,8,0,9,1};
        quickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    
    public static void quickSort(int[] arr,int start,int end) {
        if(start<end) {
            //把数组中的第0个数字做为标准数
            int stard=arr[start];
            //记录需要排序的下标
            int low=start;
            int high=end;
            //循环找比标准数大的数和比标准数小的数
            while(low<high) {
                //右边的数字比标准数大
                while(low<high&&stard<=arr[high]) {
                    high--;
                }
                //使用右边的数字替换左边的数
                arr[low]=arr[high];
                //如果左边的数字比标准数小
                while(low<high&&arr[low]<=stard) {
                    low++;
                }
                arr[high]=arr[low];
            }
            //把标准数赋给低所在的位置的元素
            arr[low]=stard;
            //处理所有的小的数字
            quickSort(arr, start, low);
            //处理所有的大的数字
            quickSort(arr, low+1, end);
        }
    }

}
4.分析快速排序算法

快速排序算法是一种原地、不稳定的排序算法,最好时间复杂度情况:T(n) = O(nlogn) 最差时间复杂度情况:T(n) = O(n2) 平均时间复杂度情况:T(n) = O(nlogn) 

开始分析“并归排序算法”

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

1.并归排序描述

归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾

2.图解并归排序

Here Insert Picture Description

3.代码实现并归排序
public class MergeSort {

    public static void main(String[] args) {
        int[] arr = new int[] {1,3,5,2,4,6,8,10};
        System.out.println(Arrays.toString(arr));
        mergeSort(arr, 0, arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    
    //归并排序
    public static void mergeSort(int[] arr,int low,int high) {
        int middle=(high+low)/2;
        if(low<high) {
            //处理左边
            mergeSort(arr, low, middle);
            //处理右边
            mergeSort(arr, middle+1, high);
            //归并
            merge(arr,low,middle,high);
        }
    }
    
    public static void merge(int[] arr,int low,int middle, int high) {
        //用于存储归并后的临时数组
        int[] temp = new int[high-low+1];
        //记录第一个数组中需要遍历的下标
        int i=low;
        //记录第二个数组中需要遍历的下标
        int j=middle+1;
        //用于记录在临时数组中存放的下标
        int index=0;
        //遍历两个数组取出小的数字,放入临时数组中
        while(i<=middle&&j<=high) {
            //第一个数组的数据更小
            if(arr[i]<=arr[j]) {
                //把小的数据放入临时数组中
                temp[index]=arr[i];
                //让下标向后移一位;
                i++;
            }else {
                temp[index]=arr[j];
                j++;
            }
            index++;
        }
        //处理多余的数据
        while(j<=high) {
            temp[index]=arr[j];
            j++;
            index++;
        }
        while(i<=middle) {
            temp[index]=arr[i];
            i++;
            index++;
        }
        //把临时数组中的数据重新存入原数组
        for(int k=0;k<temp.length;k++) {
            arr[k+low]=temp[k];
        }
    }

}
4.分析并归排序算法

并归排序算法是一种稳定的排序算法,最好时间复杂度情况:T(n) = O(n) 最差时间复杂度情况:T(n) = O(nlogn) 平均时间复杂度情况:T(n) = O(nlogn) 

开始分析“基数排序算法”

基数排序也是非比较的排序算法,对每一位进行排序,从最低位开始排序,复杂度为O(kn),为数组长度,k为数组中的数的最大的位数;基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。

2.图解基数排序

小提示:注意进度条挡住的0~9的数字归类
Here Insert Picture Description

3.代码实现基数排序
public class RadixSort {

    public static void main(String[] args) {
        int[] arr = new int[] {23,6,189,45,9,287,56,1,798,34,65,652,5};
        radixSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    public static void  radixSort(int[] arr) {
        //存最数组中最大的数字
        int max=Integer.MIN_VALUE;
        for(int i=0;i<arr.length;i++) {
            if(arr[i]>max) {
                max=arr[i];
            }
        }
        //计算最大数字是几位数
        int maxLength = (max+"").length();
        //用于临时存储数据的数组
        int[][] temp = new int[10][arr.length];
        //用于记录在temp中相应的数组中存放的数字的数量
        int[] counts = new int[10];
        //根据最大长度的数决定比较的次数
        for(int i=0,n=1;i<maxLength;i++,n*=10) {
            //把每一个数字分别计算余数
            for(int j=0;j<arr.length;j++) {
                //计算余数
                int ys = arr[j]/n%10;
                //把当前遍历的数据放入指定的数组中
                temp[ys][counts[ys]] = arr[j];
                //记录数量
                counts[ys]++;
            }
            //记录取的元素需要放的位置
            int index=0;
            //把数字取出来
            for(int k=0;k<counts.length;k++) {
                //记录数量的数组中当前余数记录的数量不为0
                if(counts[k]!=0) {
                    //循环取出元素
                    for(int l=0;l<counts[k];l++) {
                        //取出元素
                        arr[index] = temp[k][l];
                        //记录下一个位置
                        index++;
                    }
                    //把数量置为0
                    counts[k]=0;
                }
            }
        }
    }
    
}
4.分析基数排序算法

基数排序算法是一种稳定的排序算法,最好时间复杂度情况:T(n) = O(n * k) 最差时间复杂度情况:T(n) = O(n * k) 平均时间复杂度情况:T(n) = O(n * k)。

开始分析“堆排序算法”

1.堆排序描述

堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:
最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
创建最大堆(Build Max Heap):将堆中的所有数据重新排序
堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

2.图解堆排序

Here Insert Picture Description

3.代码实现堆排序
public class HeapSort {
    
    public static void main(String[] args) {
        int[] arr = new int[] {9,6,8,7,0,1,10,4,2};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    public static void heapSort(int[] arr) {
        //开始位置是最后一个非叶子节点,即最后一个节点的父节点
        int start = (arr.length-1)/2;
        //调整为大顶堆
        for(int i=start;i>=0;i--) {
            maxHeap(arr, arr.length, i);
        }
        //先把数组中的第0个和堆中的最后一个数交换位置,再把前面的处理为大顶堆
        for(int i=arr.length-1;i>0;i--) {
            int temp = arr[0];
            arr[0]=arr[i];
            arr[i]=temp;
            maxHeap(arr, i, 0);
        }
    }
    
    public static void maxHeap(int[] arr,int size,int index) {
        //左子节点
        int leftNode = 2*index+1;
        //右子节点
        int rightNode = 2*index+2;
        int max = index;
        //和两个子节点分别对比,找出最大的节点
        if(leftNode<size&&arr[leftNode]>arr[max]) {
            max=leftNode;
        }
        if(rightNode<size&&arr[rightNode]>arr[max]) {
            max=rightNode;
        }
        //交换位置
        if(max!=index) {
            int temp=arr[index];
            arr[index]=arr[max];
            arr[max]=temp;
            //交换位置以后,可能会破坏之前排好的堆,所以,之前的排好的堆需要重新调整
            maxHeap(arr, size, max);
        }
    }

}
4.分析堆排序算法

基数排序算法是一种原地、不稳定的排序算法,最好时间复杂度情况:T(n) = O(nlogn) 最差时间复杂度情况:T(n) = O(nlogn) 平均时间复杂度情况::T(n) = O(nlogn)

为什么插入排序要比冒泡排序更受欢迎?

基本的知识都讲完了,不知道各位有木有想过这样一个问题:冒泡排序和插入排序的时间复杂度都是O(n2),都是原地排序算法,为什么插入排序要比冒泡排序更受欢迎呢?

我们前面分析冒泡排序和插入排序的时候讲到,冒泡排序不管怎么优化,元素交换的次数是一个固定值,是原始数据的逆序度。插入排序是同样的,不管怎么优化,元素移动的次数也等于原始数据的逆序度。

但是,从代码实现上来看,冒泡排序的数据交换要比插入排序的数据移动要复杂,冒泡排序需要3个赋值操作,而插入排序只需要1个。我们来看这段操作:

冒泡排序中数据的交换操作:
if (a[j] > a[j+1]) { // 交换
   int tmp = a[j];
   a[j] = a[j+1];
   a[j+1] = tmp;
   flag = true;
}

插入排序中数据的移动操作:
if (a[j] > value) {
  a[j+1] = a[j];  // 数据移动
} else {
  break;
}

我们把执行一个赋值语句的时间粗略地计为单位时间(unit_time),然后分别用冒泡排序和插入排序对同一个逆序度是K的数组进行排序。用冒泡排序,需要K次交换操作,每次需要3个赋值语句,所以交换操作总耗时就是3*K单位时间。而插入排序中数据移动操作只需要K个单位时间。

This is only our very theoretical analysis, in order to test for the above bubble sort and insertion sort Java code, I wrote a performance comparison test procedures, randomly generated 10,000 array, each array contains 200 data, then on my machine were used and inserted into the bubble sort algorithm to sort, bubble sort algorithm to perform complete about 700ms, and insertion sort requires only about 100ms can get!

So, while the bubble sort and insertion sort on the time complexity is the same, are O (n2), but if we want to achieve the ultimate performance optimization, it is certainly the preferred insertion sort. Insertion sort algorithm is also a great idea to optimize space, we just talked about one of the most basic. If you are interested in optimizing insertion sort, you can brush up on their own and then shell sort.

The following is an analysis diagram of the eight classical algorithm:
Here Insert Picture Description

Here, more than eight classical algorithm analysis, are based on an array of implementation. If the data is stored in a linked list, the ranking algorithm can work it? If so, then the appropriate time and space complexity is how much? Look out - Daniel Comments

If this article helpful, even a little bit, please choose a chant praise to you, thank you ~

I welcome you to focus on the public number, to explore technology, yearning technology, the pursuit of technology ... is coming to say good pots Friends Oh ...

Here Insert Picture Description

Guess you like

Origin www.cnblogs.com/yichunguo/p/11839611.html