十大经典排序算法

排序算法平均时间复杂度最好时间复杂度最坏时间复杂度空间复杂度算法分类稳定性
冒泡排序O(n^2)O(n)O(n^2)O(1)比较类稳定
插入排序O(n^2)O(n)O(n^2)O(1)比较类稳定
归并排序O(nlgn)O(nlgn)O(nlgn)O(n)比较类稳定
快速排序O(nlgn)O(nlgn)O(n^2)O(n)比较类不稳定
希尔排序O(n^1.5)O(n)O(n^2)O(1)比较类不稳定
选择排序O(n^2)O(n^2)O(n^2)O(1)比较类不稳定
堆排序O(nlgn)O(nlgn)O(nlgn)O(1)比较类不稳定
计数排序O(n+k)O(n+k)O(n+k)O(n+k)非比较稳定
桶排序O(n+k)O(n)O(n^2)O(n+k)非比较稳定
基数排序O(n*k)O(n*k)O(n*k)O(n+k)非比较稳定

1.冒泡排序

规则:将第一个元素与第二个元素进行比较 ,如果第一个比第二个大则交换位置。继续第二个与第三个比较与之前一样…

第一趟循环确定最后一个位置,第二趟循环确定倒二的位置…

代码示例(JAVA):

        for (int i = 0; i < x.length; i++) {//循环次数
            for (int j = 0; j < x.length-i-1; j++) {//每次交换的次数
                if (x[j]>x[j+1]){
                   int tem = x[j];
                   x[j] = x[j+1];
                   x[j+1] = tem;
                }
            }
        }

2.插入排序

规则:类似于摸牌一样,每次讲新牌插入到对应的位置,直到最后一张

代码示例(JAVA)

        for (int i = 1; i < x.length; i++) {
            int tem  = x[i];//摸起的新牌
            int j = i-1;
            while (j>=0 && x[j]>tem){//如果前面的牌比较大则将位置后移一位 腾出前面的位置
                x[j+1] = x[j];
                j--;
            }
            x[j+1] = tem;//将牌放入位置
        }

3.归并排序

规则:类似于化整为零,将数组对半拆分,拆分到只剩一个就是有序 然后在组合起来

    public void sort(int[] x){
        sort(x,0,x.length-1);
    }
    public void sort(int[] x,int start, int end){
        if (start<end){
            int mid = (start+end)/2;
            sort(x,start,mid);//将数组继续拆分
            sort(x,mid+1,end);//将数组继续拆分
            merge(x,start,mid+1,end);
        }
    }
    public void merge(int[] x,int start, int mid, int end){//合并
        int[] s2 = new int[end-start+1];
        int t = mid;
        int i = start;
        int index = 0;
        while (i<mid && t<=end){
            if (x[i]<=x[t]){
                s2[index++] = x[i];
                i++;
            }else {
                s2[index++] = x[t];
                t++;
            }
        }
        while (i<mid)s2[index++] = x[i++];
        while (t<=end)s2[index++] = x[t++];
        for (int l = 0; l < s2.length; l++) {
            x[start+l] = s2[l];
        }
    }

4.快速排序

规则:选定一个锚点将数组中的数值跟锚点对比左右分组,小的分一组,大的分一组,分组完继续讲左右两堆分组,直至组中只有一个数则为有序

    public void sort(int[] x){
         sort(x,0,x.length-1);
    }
    public void sort(int[] x, int q, int r){
        if (q<r){
            int index = partition(x,q,r);
            sort(x,q,index-1);//左边堆继续分组
            sort(x,index+1,r);//右边堆继续分组
        }
    }
    public int partition(int[] x, int q, int r){//将数组按照锚点左右分组
        int tem  = x[r];
        int index = q-1;
        for (int i = q; i < r; i++) {
            if (tem>=x[i]){
                index++;
                if (i!=index){
                    int t = x[i];
                    x[i] = x[index];
                    x[index] = t;
                }
            }
        }
        x[r] = x[index+1];
        x[index+1] = tem;
        return index+1;
    }

5.希尔排序

规则:插入排序的一种,先让数组中任意间隔为 h 的元素有序,刚开始 h 的大小可以是 h = n / 2,接着让 h = n / 4,让 h 一直缩小,当 h = 1 时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了

    public void sort(int[] x){
         int h = x.length/2;
         if (h<2) return;
        for (int i = h; i > 0; i/=2) {
            for (int j = 0; j < x.length; j++) {
                sort(x,i,j);
            }
        }
    }
    public void sort(int[] x, int h, int r){
        int tem = x[r];
        r = r-h;
        while (r>0 && tem<x[r]){
            x[r+h] = x[r];
            r = r-h;
        }
        x[r+h] = tem;
    }

6.选择排序

规则:顾名思义有选择性的交换位置,第一趟找到最小值然后交换到第一个位置 第二趟找到第二小的值交换到第二个位置…

         for (int i = 0; i < x.length; i++) {
             int min = i;
             for (int j = i; j < x.length; j++) {
                 if (x[min]>x[j]){
                     min = j;
                 }
             }
             int tem = x[min];
             x[min] = x[i];
             x[i] = tem;
         }

7.堆排序

规则:先构建一个完全二叉树,大顶堆是大的在上面 小的在下面,小顶堆相反。构建完堆后 每次将顶部的节点取出放在相应位置 由最后一个叶子结点补上,然后再进行调整,调整完继续上一步步骤 循此往复直至堆的节点被取完则数组也有序了

     public static void sort(int []arr){
         //1.构建大顶堆
         //由于完全二叉树的子节点数是总节点数的一半   所以非叶子节点坐标是从arr.length/2-1开始
         for(int i=arr.length/2-1;i>=0;i--){
             //从第一个非叶子结点从下至上,从右至左调整结构
             adjustHeap(arr,i,arr.length);
         }
         //2.将节点取出 并且调整
         //循环的次数是数组的数量
         for(int j=arr.length-1;j>0;j--){
             swap(arr,0,j);//将堆顶元素与末尾元素进行交换
             adjustHeap(arr,0,j);//重新对堆进行调整
         }
     }
     public void adjustHeap(int []arr,int i,int length){
         int temp = arr[i];//先取出当前元素i
         //完全二叉树的子节点数是总节点数的一半  所以他的子节点是2i+1和2i+2
         for(int k=i*2+1;k<length;k=k*2+1){//从i结点的左子结点开始,也就是2i+1处开始
             if(k+1<length && arr[k]<arr[k+1]){//如果左子结点小于右子结点,k指向右子结点
                 k++;
             }
             if(arr[k] >temp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                 arr[i] = arr[k];
                 i = k;
             }else{
                 break;
             }
         }
         arr[i] = temp;//将temp值放到最终的位置
     }
     public void swap(int []arr,int a ,int b){
         int temp=arr[a];
         arr[a] = arr[b];
         arr[b] = temp;
     }

8.计数排序

规则:利用元素的实际值来确定它们在输出数组中的位置

     public void sort(int []arr){
         if (arr==null || arr.length<2) return;
         int max = arr[0];
         int min = arr[0];
         //找出数组中的最大值与最小值
         for (int i = 0; i < arr.length; i++) {
             if (arr[i]>max){
                 max=arr[i];
             }
             if (arr[i]<min){
                 min=arr[i];
             }
         }
         //根据最大值最小值差建立数组
         int[] count = new int[max-min+1];
         //统计每个位置的参数数量
         for (int i = 0; i < arr.length; i++) {
             count[arr[i]-min] ++;
         }
         int index = 0;
         //将参数放回到数组中
         for (int i = 0; i < count.length; i++) {
             for (int x = 0; x < count[i]; x++) {
                 arr[index++] = i+min;
             }
         }
     }

9.桶排序

规则:创建一些均匀区间桶 将数组按照区间放入桶中 在分散排序 最后将桶中的参数依序输入到原数组就好

     public void sort(int []arr){
         if (arr==null || arr.length<2) return;
         int max = arr[0];
         int min = arr[0];
         //找出数组中的最大值与最小值
         for (int i = 0; i < arr.length; i++) {
             if (arr[i]>max){
                 max=arr[i];
             }
             if (arr[i]<min){
                 min=arr[i];
             }
         }
         //根据最大值最小值差和长度创建桶
         List[] count = new List[(max - min)/arr.length+1];
         //创建桶 并将参数放入桶中
         for (int i = 0; i < arr.length; i++) {
             int num = (arr[i] - min) / (arr.length);
             if (count[num] == null){
                 count[num] = new ArrayList();
             }
             count[num].add(arr[i]);
         }
         // 对每个桶进行排序
         for(int i = 0; i < count.length; i++){
             Collections.sort(count[i]);
         }
         int index = 0;
         //将参数放回到数组中
         for (int i = 0; i < count.length; i++) {
             if (count[i] != null){
                 for (int x = 0; x < count[i].size(); x++) {
                     arr[index++] = (int)count[i].get(x);
                 }
             }
         }
     }

10.基数排序

规则:先按照个位数排序,然后按照十位数排序…直至按照最高位排序

     public void sort(int []arr){
        int[][] count = new int[10][arr.length];//创建十个桶
        int[] order = new int[10];//每个桶里面的个数
        int c = 1;
        boolean flag = true;
        while (flag){
            flag = false;
            //将数组按照位数放到到桶中
            for (int i = 0; i < arr.length; i++) {
                int tem = arr[i]/c;
                if (tem>0){flag=true;}
                int rem = tem%10;
                count[rem][order[rem]++] = arr[i];
            }
            int index = 0;
            //从桶中取出
            for (int i = 0; i < 10; i++) {
                if (order[i] != 0){
                    for (int j = 0; j < order[i]; j++) {
                        arr[index++] = count[i][j];
                    }
                    order[i] = 0;
                }
            }
            c*=10;
        }
     }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值