常见排序算法——七大比较类排序算法

算法 最坏复杂度 平均复杂度 最好复杂度 空间复杂度
选择排序 O($n^2$) O($n^2$) O($n^2$) O(1)
插入排序 O($n^2$) O($n^2$) O($n$) O(1)
希尔排序 O($nlog(n))$~O($n^2$) O($n^{1.3}$) O($n^2$) O(1)
冒泡排序 O($n^2$) O($n^2$) O(n)(用交换flag改进) O(1)
快速排序 O($n^2$) O($nlog(n)$) O($nlog(n)$) O(log(n))~O(n)
堆排序 O($nlog(n)$) O($nlog(n)$) O($nlog(n)$) O(1)
归并排序 O($nlog(n)$) O($nlog(n)$) O($nlog(n)$) O(n)

Java实现

选择排序

//选择排序:每次遍历找到数组中的最小值,放到剩余数组最前面,以此类推,直到所有元素被排好
    public static void select_sort(int[] arr){
        int len=arr.length;
        long start=System.currentTimeMillis();
        for(int i=0;i<len;i++){
            for(int j=i+1;j<len;j++){
                if(arr[i]>arr[j]){
                    swap(arr,i,j);
                }
            }
        }
        long end=System.currentTimeMillis();
        System.out.println("选择排序耗时(秒):"+(end-start));
        //toPrint(arr);

    }

插入排序

//插入排序:用新的元素去与已经排序好的元素数组从尾部开始比较,若比对应元素小,则下标继续往前走,直到找到比新元素小的元素,然后将比新元素小的元素后面的全部元素后移,插入新元素。
public static int[] insert_sort(int[] arr){
        long start=System.currentTimeMillis();
        for(int i=0;i<arr.length;i++){
            int temp=arr[i];
            for(int j=i;j>0 && arr[j-1]>arr[j];j--){
                arr[j]=arr[j-1];
                arr[j-1]=temp;
            }
        }
        long end=System.currentTimeMillis();
        System.out.println("插入排序耗时(秒):"+(end-start));
        return arr;
        //toPrint(temparr);
    }

希尔排序

//希尔排序:以arr.length/2为开始间隔,并不断/2缩小间隔的插入排序,最后一次的循环比较e就是插入排序,但是数组的绝大部分元素已经处于相对有序状态。
public static int[] shell_sort(int arr[]){
        for(int gap=arr.length; gap>0 ; gap/=2){
            for(int i=gap;i<arr.length;i++){
                int temp=arr[i];
                for(int j=i;j>=gap && arr[j-gap]>arr[j];j-=gap){
                    arr[j]=arr[j-gap];
                    arr[j-gap]=temp;
                }
            }
        }
        return arr;
    }

冒泡排序

//冒泡排序:比较相邻两个元素的大小,决定是否交换位置,每次循环可将一个最大值元素一直交换到最后面(或者将最小值一直交换到最前面),以此类推。用一个交换flag作优化可以将最优情况时间复杂度降到O(n),即只比较一轮。
public static void bubble_sort(int[] arr){
    int len=arr.length;
    long start=System.currentTimeMillis();
    boolean swapFlag=true;
    for(int i=0;i<len;i++){
        if(swapFlag==false)
            break;
        swapFlag=false;
        for(int j=1;j<len-i;j++){
            if(arr[j-1]>arr[j]){
                swap(arr,j-1,j);
                swapFlag=true;
            }
        }
    }
    

快速排序

//思路:每一次排序,将首元素(arr[0])交换到这样的位置,即它所在位置往右的所有元素都不小于它,且它所在位置往左的所有元素都不大于它。完成这一步,只需要将首元素不断地从右往左遍历找比它小的,然后从左往右找比它大的,找到即交换位置,一直到从两个方向都再也找不到一个可以交换的元素,一轮排序结束。接着用递归的方式排序剩下的两半。
public static void quickSort(int[] arr,int start,int end){
        if(start>=end)
            return;

        boolean leftFlag=false,rightFlag=false;

        int pivot=start;
        System.out.println("hehe");
        while(!(leftFlag && rightFlag)){
            leftFlag=true;rightFlag=true;
            //第一轮:第一个元素从右边开始找第一个比它小的元素,与之交换位置
            for(int i=end;i>=start;i--){
                if(arr[pivot]<arr[i]){
                    exchange(arr, pivot, i);
                    pivot=i;
                    leftFlag=false;
                }
            }
            System.out.println("循环");
            for(int i=start;i<=end;i++){
                if(arr[pivot]<arr[i]){
                    exchange(arr, pivot, i);
                    pivot=i;
                    rightFlag=false;
                }
            }
        }

        quickSort(arr, start, pivot-1);
        quickSort(arr, pivot+1,end);

    }

堆排序

归并排序

//思路:将数组不断划分为更小的两个数组的组合(递归),当划分到最小的粒度时,即两个数之间的比较与位置交换,然后不断将两个小的数组融合成大的数组(merge方法)。
public static void merge_sort(int[] arr,int low,int high){
        if(high>low){
            int pivot=(high+low)/2;
            merge_sort(arr,low,pivot);
            merge_sort(arr,pivot+1,high);
            merge(arr,low,pivot,high);
        }
    }

    private static void merge(int[] arr,int low,int pivot,int high){
        int[] temp=new int[high-low+1];
        int i=low,j=pivot+1;
        int count=0;
        while(i<=pivot && j<=high){
            if(arr[i]>arr[j]){
                temp[count++]=arr[j];
                j++;
            }
            else{
                temp[count++]=arr[i];
                i++;
            }
        }

        while(i<=pivot){
            temp[count++]=arr[i];
            i++;
        }

        while(j<=high){
            temp[count++]=arr[j];
            j++;
        }
        for(int x=0;x<temp.length;x++){
            arr[low+x]=temp[x];
        }
    }

原文地址:https://www.cnblogs.com/bluemapleman/p/9276779.html

时间: 2024-07-28 22:41:42

常见排序算法——七大比较类排序算法的相关文章

排序算法总结----比较类排序

概述:排序算法可分为比较性的排序,以及运算性的排序:这里详细介绍这些排序的原理,性能,实现,以及应用场合. 前面是维基百科的介绍,这里介绍几个比较典型的算法. 理论 计算复杂性理论 大O符号 全序关系 列表 稳定性 比较排序 自适应排序 排序网络 整数排序 交换排序 冒泡排序 鸡尾酒排序 奇偶排序 梳排序 侏儒排序 快速排序 臭皮匠排序 Bogo排序 选择排序 选择排序 堆排序 Smooth排序 笛卡尔树排序 锦标赛排序 循环排序 插入排序 插入排序 希尔排序 二叉查找树排序 图书馆排序 Pat

排序算法总结----运算类排序

运算排序 第一:计数排序 1:原理 对于每个输入数,确定小于该数的个数.这样可以直接把数放在输出数组的位置. 2:性能 最差时间复杂度 最优时间复杂度 平均时间复杂度 最差空间复杂度 注:稳定算法 3:应用 适合0~100的范围的数,当然可以和基排序结合而扩展数的范围. 4:实现 void CountingSort(int *A, int *B, int array_size, int k) { int i, value, pos; int * C=new int[k+1]; for(i=0;

详谈排序算法之选择类排序(两种方法实现堆排序)

   今天我们再来讨论一下选择类排序,选择类排序分为:简单排序,树形选择排序和堆排序.但我们主要说的是简单和堆排序两个,因为树形选择排序使用了较多的辅助空间,以及和∞进行多余比较,为弥补树型选择排序的这些缺点, J.W.J.Williams 在 1964 年提出了进一步的改进方法,即堆排序.对于我个人而言..一开始并不是很理解它的算法思想,纠结了许久.在网上查找资料的时候发现这位大神的文章思路十分清晰,而且把创建堆以及堆化数组的算法讲解的十分详细.如果有不明白堆排序思路的,可以先看看这篇文章~堆

详谈排序算法之插入类排序(两种思路实现希尔排序)

1. 排序( sorting) 的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.其确切的定义为: 假设有n个数据元素的序列{R1 , R2 , - , Rn},其相应关键字的序列是{K1 , K2 , - , Kn} ,通过排序要求找出下标 1 , 2 , - , n的一种排列p1 , p2 , - , pn,使得相应关键字满足如下的非递减(或非递增)关系Kp1 ≤ Kp2 ≤ - ≤ Kpn这样,就得到一个按关键字有序的纪录序列{ Rp1 , Rp2 , - , Rpn }

详谈排序算法之交换类排序(两种方法实现快速排序【思路一致】)

1.冒泡排序    起泡排序的思想非常简单.首先,将 n 个元素中的第一个和第二个进行比较,如果两个元素的位置为逆序,则交换两个元素的位置:进而比较第二个和第三个元素关键字,如此类推,直到比较第 n-1 个元素和第 n 个元素为止:上述过程描述了起泡排序的第一趟排序过程,在第一趟排序过程中,我们将关键字最大的元素通过交换操作放到了具有 n 个元素的序列的最一个位置上.然后进行第二趟排序,在第二趟排序过程中对元素序列的前 n-1 个元素进行相同操作,其结果是将关键字次大的元素通过交换放到第 n-1

选择类排序总结

选择类排序总结 所谓选择类排序的思想就是:从数组的中选出最大或最小的,通过多次选择最后达到排序的目的 首先是简单选择排序 思想:每趟扫描中,选出最小的数字放在最前面,然后从第二个数字开始扫描,直到只剩下最后一个数不需要扫描 void EasySelect_Sort(int a[],int n) { int k; for(int i=1;i<n;i++) { k=i-1; for(int j=i;j<n;j++) { if(a[j]<a[k]) { k=j; } } if(k!=(i-1)

Dijkstra算法详细(单源最短路径算法)

介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或许,你曾经感觉它很难,那么,这个时候正适合你重新认识它. Dijkstra能是干啥的? Dijkstra是用来求单源最短路径的 就拿上图来说,假如直到的路径和长度已知,那么可以使用dijkstra算法计算南京到图中所有节点的最短距离. 单源什么意思? 从一个顶点出发,Dijkstra算法只能求一个顶

常见的五类排序算法图解和实现(多关键字排序:基数排序以及各个排序算法的总结)

基数排序思想 完全不同于以前的排序算法,可以说,基数排序也叫做多关键字排序,基数排序是一种借助“多关键字排序”的思想来实现“单关键字排序”的内部排序算法. 两种方式: 1.最高位优先,先按照最高位排成若干子序列,再对子序列按照次高位排序 2.最低位优先:不必分子序列,每次排序全体元素都参与,不比较,而是通过分配+收集的方式. 多关键字排序 例:将下表所示的学生成绩单按数学成绩的等级由高到低排序,数学成绩相同的学生再按英语成绩的高低等级排序.        第一个关键字是数学成绩,第二个关键字是英

各种排序算法的一个类

#include<iostream> #define MAX 100 using namespace std; class Sample { int a[MAX]; int b[MAX]; int n; friend class Process; public: Sample(){n=0;} }; class Process { private: int s_psort(Sample &s,int first,int end); void sift(int k,int m,Sample