排序算法

    技术2022-07-12  80

     

    目录

    一.直接插入排序

    二.希尔排序

    三.冒泡排序

    四.快速排序


    一.直接插入排序

    1.算法思路:

    顾名思义,就是将一个新的元素插入已经排好的序列中。

    比如一个待排的序列:49,38,65,97,76,13,27,49,用数组a[1…n]表示,升序排序如图所示,其中()表示已经排好的元素。

    为了在查找插入位置的过程中避免数组下标出界,在a[0]处设置一个哨兵。比如在插入a[i]的过程中,如果a[i]小于a[i-1],先将a[i]放在哨兵a[0]的位置,在从后往前比较的过程中,如果a[0]<a[j]就就将a[j]后移一个单位,直到找到插入的位置,再将a[0]还原到正确的插入位置。直接插入排序算法的时间复杂度为O(n^2),并且是一种稳定的排序方法。

    2代码:

    for (int i = 1; i <= n; i++) { if(a[i] < a[i-1]){ //如果a[i] < a[i-1]就进行插入,否则不管 a[0] = a[i]; //把待插入的元素放入哨兵 a[i] = a[i-1]; //a[i-1]后移 int j = i-2; while(a[j] > a[0]){ a[j+1] = a[j]; //逐个后移,直到找到插入的位置 j--; } a[j+1] = a[0]; //把a[0]还原到插入的位置 } }

     

    二.希尔排序

    1.算法思路:

    希尔排序是插入排序的一种,是采用了分组插入的方式,先将整个带排序的数组分割成几组,减少排序的数量,对每组进行直接插入排序。然后增加每组的数据量,重新分组。当几次分组排序过后,整个序列已基本有序,再进行一次全体的直接插入排序。希尔对记录的分组,不是简单地 逐段分割, 而是将相隔某个 增量的记录分成一组。

    1.第一趟取增量 d1 (d1<n) 把全部记录分成小个组,所有间隔为 di 的记录分在同组,在各个组中进行直接插入排序。

    2.第二趟取增量 d2 (d2<d1), 重复上述的分组和排序。

    3.依次类推, 直到所取的增量 d1 = 1 (d1 <dt-1 << d2 < d,), 所有记录在同一组中进行直接插入排序为止。

    2.代码:

    int[] a = {49,38,65,97,76,13,27,49,55,4}; int n = a.length; int key; //临时存储,类似于直接插入的哨兵 for (int d = n/2;d > 0;d/=2) { //增量,从n/2开始每次除2,直到d=1 for (int i = d; i < n; i++) { //i从d开始,因为第一个只有一个元素不用管。 key = a[i]; int j = i-d; while(j>=0 && key < a[j]){ a[j+d] = a[j]; //后移 j-=d; } a[j+d] = key; } }

    三.冒泡排序

    1.算法思路:

    冒泡排序比较简单。冒泡排序是每次比较相邻的两个元素,把较大移到后面,经过一轮交换后,前n个元素的最大值就到了最后,再对前n-1个元素进行同样的办法,就可以把前n-1个中最大的元素移到倒数第二的位置上。重复以上步骤就可以完成排序。

    2.代码:

    for (int i = 0; i < a.length-1; i++) { //i表示比较的数趟 for (int j = 0; j < a.length-i-1; j++) { //第0趟比较n个元素,第1趟比较n-1个元素··· if(a[j] > a[j+1]){ //把较大的,移到后面 int t = a[j]; a[j] = a[j+1]; a[j+1] = t; } } }

    四.快速排序

    1.算法思路:

    快速排序和冒泡排序都属于交换排序。快速排序的基本思想是分治排序,先随便找一个基准值,把数组中所有小于它的值放到基准值的左边,把大于它的值放到基准值的右边。然后左右两边的数组再进行独立的排序,对于左边的数组也同样随便找一个基准值,重复上面的步骤,右边也一样。可以看出这是一个递归的调用。时间复杂度为O(nlgn),是不稳定的排序算法。

    图解:

    一般选第一个元素作为基准值,然后用两个指针i,j分别指向数组的头和尾部

    首先移动j,找到一个比基准值小的元素之后,不动,然后移动i,找到比基准值大的元素后,交换两个指针指向的值

    当i和j指向同一个位置的适合,就找到了基准值的位置,就把基准值和这个位置得到元素交换。

    最后再分别对左右两边重复上面的步骤,直到 j<i 终止。

    2.代码:

    void QuickSort( int i, int j) { if(j<i) return;//结束条件 int key = a[i];//基准值 int e = i;//记录最前面位置 int l = j;//记录最后面位置 while(i!=j){ while(a[j] >= key && i < j) j--; while(a[i] <= key && i < j) i++; //找到了两个待交换的值,并且i和j不重合 if(i < j){ int t = a[i]; a[i] = a[j]; a[j] = t; } } //基准值和中间那个数交换 a[e] = a[i]; a[i] = key; QuickSort(e,i-1);//递归基准值左边部分 QuickSort(i+1,l);//递归基准值右边边部分 }

     

    Processed: 0.011, SQL: 9