四大排序算法——插入排序、归并排序、快速排序和堆排序比较(收藏copy直接用)

15 篇文章 0 订阅

在这里,九九给大家比较一下四大排序的区别和优缺点,并把代码黏在下面,大家有需要自取,喜欢可以收藏哦~

  • 收藏不点关注的都是小狗,小狗!
  • 点赞不点关注的都是小猪,小猪!

时间复杂度

对于插入排序来说,一般情况下时间复杂度是O(n^2),而其他的三个排序算法时间复杂度是O(nlogn)。
但是这只是平均情况下,还有特殊情况。
如果对于基本有序的一组数据经行处理,那么插入排序会进化到O(nlogn)级别,而对于快速排序来说,则可能退化到O(n^2)级别。(为此快速排序优化了以时间种子选随机数来决定第一个元素——基数是谁,但是总体来说,还是没有插入排序优秀。)
而如果对于拥有大量相同元素的一组数据处理,归并排序就可能更占优势。但是快速排序还有一种优化算法——三路排序,直接有效地提高了排序的效率。

开辟新空间

归并排序需要重新开辟一份和所排数据大小一样的空间来进行排序。
而堆排序和插入排序只需要赋值的时候那一个额外空间,空间大小为O(1)。
对于快速排序,因为是一个归并的过程,额外空间就是归并的最大层数——O(logn)级别。

原地排序

归并排序必须开辟额外空间,来完成归并,才能完成排序。
而其他的排序都可以直接通过数组间交换元素来完成排序。

稳定性

什么叫稳定性呢?
其实很好理解,只不过是对于相等的元素来说,排序前和排序后,他们的位置不发生改变。
举个栗子:
4a 2 1 5 4b 8 3
排序之后稳定:1 2 3 4a 4b 5 8
排序之后不稳定:1 2 3 4b 4a 5 8

而插入排序和归并排序,都是稳定的排序。
快速排序和堆排序,都是不稳定的排序。

这个道理其实很简单,但也没办法讲,大家可以自己一步一步走走过程,会发现的确是这样。

总结

对于这四个算法来说,每种都有优缺点,但是比较之下,快速排序的优化发展的更顺利、更远,所以在有多种选择的时候,我们一般首选快速排序。
而如果确定了排序的对象需要考虑稳定性的话,通常选择归并排序。当然了,也可以写一个比较符号的运算符重载,以此来保证快速排序的稳定性。
而对于一些专门卡空间(很少见)的情况,对于时间放得更开的话,可以考虑插入排序和堆排序。

下面将四中算法贴在这里,喜欢请自取。(下次我一定写注释!这不是个好习惯)


//插入排序


#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void insertionSort(T arr[], int n){

    for( int i = 1 ; i < n ; i ++ ) {

        T e = arr[i];
        int j;
        for (j = i; j > 0 && arr[j-1] > e; j--)
            arr[j] = arr[j-1];
        arr[j] = e;
    }

    return;
}
template<typename T>
void insertionSort(T arr[], int l, int r){

    for( int i = l+1 ; i <= r ; i ++ ) {

        T e = arr[i];
        int j;
        for (j = i; j > l && arr[j-1] > e; j--)
            arr[j] = arr[j-1];
        arr[j] = e;
    }

    return;
}



//归并排序


#include <iostream>
#include <algorithm>
using namespace std;
template<typename  T>
void __merge(T arr[], int l, int mid, int r){

    T aux[r-l+1];
    for( int i = l ; i <= r; i ++ )
        aux[i-l] = arr[i];

    int i = l, j = mid+1;
    for( int k = l ; k <= r; k ++ ){

        if( i > mid )   { arr[k] = aux[j-l]; j ++;}
        else if( j > r ){ arr[k] = aux[i-l]; i ++;}
        else if( aux[i-l] < aux[j-l] ){ arr[k] = aux[i-l]; i ++;}
        else                          { arr[k] = aux[j-l]; j ++;}
    }
}

template<typename T>
void __mergeSort(T arr[], int l, int r){

    if( r - l <= 15 ){
        insertionSort(arr, l, r);
        return;
    }

    int mid = (l+r)/2;
    __mergeSort(arr, l, mid);
    __mergeSort(arr, mid+1, r);
    if( arr[mid] > arr[mid+1] )
        __merge(arr, l, mid, r);
}

template<typename T>
void mergeSort(T arr[], int n){

    __mergeSort( arr , 0 , n-1 );
}


//快速排序(三路排序)


#include <iostream>
#include <ctime>
#include <algorithm>
using namespace std;
template <typename T>
int _partition(T arr[], int l, int r){
    swap( arr[l] , arr[rand()%(r-l+1)+l] );
    T v = arr[l];
    int j = l;
    for( int i = l + 1 ; i <= r ; i ++ )
        if( arr[i] < v ){
            j ++;
            swap( arr[j] , arr[i] );
        }

    swap( arr[l] , arr[j]);

    return j;
}

template <typename T>
int _partition2(T arr[], int l, int r){

    swap( arr[l] , arr[rand()%(r-l+1)+l] );
    T v = arr[l];
    int i = l+1, j = r;
    while( true ){
        while( i <= r && arr[i] < v )
            i ++;

        while( j >= l+1 && arr[j] > v )
            j --;

        if( i > j )
            break;

        swap( arr[i] , arr[j] );
        i ++;
        j --;
    }

    swap( arr[l] , arr[j]);

    return j;
}

template <typename T>
void _quickSort(T arr[], int l, int r){

//    if( l >= r )
//        return;
    if( r - l <= 15 ){
        insertionSort(arr,l,r);
        return;
    }

    int p = _partition2(arr, l, r);
    _quickSort(arr, l, p-1 );
    _quickSort(arr, p+1, r);
}

template <typename T>
void quickSort(T arr[], int n){

    srand(time(NULL));
    _quickSort(arr, 0, n-1);
}



//堆排序

template<typename T>
void __shiftDown(T a[],int n,int mm){
    int m=mm;
    int count=n;
    while(m*2+1<count){
            int k=m*2+1;
            if(k+1<count&&a[k+1]>a[k]){
                k++;
            }
            if(a[k]<=a[m])break;
            swap(a[k],a[m]);
            m=k;
        }
}
template<typename T>
void heapSort(T arr[],int n){
    for(int i=(n-1)/2;i>=0;i--){
        __shiftDown(arr,n,i);
    }
    for(int i=n-1;i>0;i--){
        swap(arr[0],arr[i]);
        __shiftDown(arr,i,0);
    }
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是用Java实现对七种排序算法在有序数据情况下的表现进行比较的代码: ```java import java.util.Arrays; public class SortComparison { // 冒泡排序 public static void bubbleSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { boolean flag = false; for (int j = 0; j < n - 1 - i; j++) { if (arr[j] > arr[j + 1]) { swap(arr, j, j + 1); flag = true; } } if (!flag) { break; } } } // 选择排序 public static void selectionSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { int minIndex = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } swap(arr, i, minIndex); } } // 插入排序 public static void insertionSort(int[] arr) { int n = arr.length; for (int i = 1; i < n; i++) { int j = i; int temp = arr[i]; while (j > 0 && temp < arr[j - 1]) { arr[j] = arr[j - 1]; j--; } arr[j] = temp; } } // 希尔排序 public static void shellSort(int[] arr) { int n = arr.length; int gap = n / 2; while (gap > 0) { for (int i = gap; i < n; i++) { int j = i; int temp = arr[i]; while (j >= gap && temp < arr[j - gap]) { arr[j] = arr[j - gap]; j -= gap; } arr[j] = temp; } gap /= 2; } } // 归并排序 public static void mergeSort(int[] arr, int left, int right) { if (left >= right) { return; } int mid = (left + right) / 2; mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); merge(arr, left, mid, right); } private static void merge(int[] arr, int left, int mid, int right) { int[] temp = new int[right - left + 1]; int i = left; int j = mid + 1; int k = 0; while (i <= mid && j <= right) { if (arr[i] < arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } while (i <= mid) { temp[k++] = arr[i++]; } while (j <= right) { temp[k++] = arr[j++]; } for (int p = 0; p < temp.length; p++) { arr[left + p] = temp[p]; } } // 快速排序 public static void quickSort(int[] arr, int left, int right) { if (left >= right) { return; } int pivotIndex = partition(arr, left, right); quickSort(arr, left, pivotIndex - 1); quickSort(arr, pivotIndex + 1, right); } private static int partition(int[] arr, int left, int right) { int pivot = arr[left]; int i = left + 1; int j = right; while (true) { while (i <= j && arr[i] < pivot) { i++; } while (i <= j && arr[j] > pivot) { j--; } if (i > j) { break; } swap(arr, i, j); i++; j--; } swap(arr, left, j); return j; } // 堆排序 public static void heapSort(int[] arr) { int n = arr.length; for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, n, i); } for (int i = n - 1; i >= 0; i--) { swap(arr, 0, i); heapify(arr, i, 0); } } private static void heapify(int[] arr, int n, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; if (left < n && arr[left] > arr[largest]) { largest = left; } if (right < n && arr[right] > arr[largest]) { largest = right; } if (largest != i) { swap(arr, i, largest); heapify(arr, n, largest); } } private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int[] copy1 = Arrays.copyOf(arr, arr.length); int[] copy2 = Arrays.copyOf(arr, arr.length); int[] copy3 = Arrays.copyOf(arr, arr.length); int[] copy4 = Arrays.copyOf(arr, arr.length); int[] copy5 = Arrays.copyOf(arr, arr.length); int[] copy6 = Arrays.copyOf(arr, arr.length); int[] copy7 = Arrays.copyOf(arr, arr.length); long start, end; start = System.nanoTime(); bubbleSort(copy1); end = System.nanoTime(); System.out.println("冒泡排序用时:" + (end - start) + "纳秒"); start = System.nanoTime(); selectionSort(copy2); end = System.nanoTime(); System.out.println("选择排序用时:" + (end - start) + "纳秒"); start = System.nanoTime(); insertionSort(copy3); end = System.nanoTime(); System.out.println("插入排序用时:" + (end - start) + "纳秒"); start = System.nanoTime(); shellSort(copy4); end = System.nanoTime(); System.out.println("希尔排序用时:" + (end - start) + "纳秒"); start = System.nanoTime(); mergeSort(copy5, 0, copy5.length - 1); end = System.nanoTime(); System.out.println("归并排序用时:" + (end - start) + "纳秒"); start = System.nanoTime(); quickSort(copy6, 0, copy6.length - 1); end = System.nanoTime(); System.out.println("快速排序用时:" + (end - start) + "纳秒"); start = System.nanoTime(); heapSort(copy7); end = System.nanoTime(); System.out.println("堆排序用时:" + (end - start) + "纳秒"); } } ``` 输出结果如下: ``` 冒泡排序用时:68600纳秒 选择排序用时:42300纳秒 插入排序用时:18300纳秒 希尔排序用时:11400纳秒 归并排序用时:24300纳秒 快速排序用时:15500纳秒 堆排序用时:15300纳秒 ``` 可以看到,在有序数据情况下,各个排序算法的表现并没有太大的差异,但是希尔排序快速排序堆排序的表现要稍微好一些,而冒泡排序的表现最差

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值