ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

九种内部排序算法的Java实现及其性能测试_一点课堂(多岸学院)

2019-09-12 11:40:45  阅读:279  来源: 互联网

标签:Java temp int 复杂度 high length 多岸 low 九种


九种内部排序算法的Java实现及其性能测试

9种内部排序算法性能比较

第九种为java.util.Arrays.sort(改进的快速排序方法)

  1. 100000的随机数据集
  2. 200000的随机数据集
  3. 500000的随机数据集

结论:归并排序和堆排序维持O(nlgn)的复杂度,速率差不多,表现优异。固定基准的快排表现很是优秀。而通过使用一个循环完成按增量分组后的直接插入的希尔排序,测试效果显著。冒泡,选择,直接插入都很慢,而冒泡效率是最低。

1.插入排序[稳定]

适用于小数组,数组已排好序或接近于排好序速度将会非常快

复杂度:O(n^2) - O(n) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

public void insertionSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
        for (int i = 1; i < a.length; i  ) {
            // 暂存当前值
            int temp = a[i];
            int j = i - 1;
            while (j >= 0 && temp < a[j]) {
                // 后移
                a[j   1] = a[j];
                j--;
            }
            // 当前值归位
            a[j   1] = temp;
        }
    }

2.希尔排序(缩小增量排序)[不稳定]

复杂度 平均 O(n^1.3) 最好O(n) 最差O(n^s)[1

内循环通过模拟并行的方式完成分组的内部直接插入排序,而不是一个一个分组分组的排,在10w的随机数据20w的随机数据均表现优异。

public void shellSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
        for (int d = a.length/2; d > 0; d/=2) {
            // 从1B开始先和1A比较 然后2A与2B...然后再1C向前与同组的比较
            for (int i = d; i < a.length; i  ) {
                // 内部直接插入
                int temp = a[i];
                int j = i - d;
                while (j >=0 && temp < a[j]) {
                    a[j d] = a[j];
                    j -= d;
                }
                a[j d] = temp;
            }
        }
    }

3.冒泡排序[稳定]

复杂度:O(n^2) - O(n) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

public void bubbleSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
        boolean flag;
        for (int i = 0; i < a.length-1; i  ) {
            flag = false;
            for (int j = 0; j < a.length-1-i; j  ) {
                if (a[j] > a[j 1]) {
                    int temp = a[j];
                    a[j] = a[j 1];
                    a[j 1] = temp;
                    flag = true;
                }
            }
            if (false == flag) {
                return;
            }
        }
    }

4.选择排序[不稳定]

原理:每次从无序序列选取最小的

复杂度:O(n^2) - O(n^2) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

public void selectSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
        for (int i = 0; i < a.length; i  ) {
            int k = i;
            for (int j = i   1; j < a.length; j  ) {
                if (a[j] < a[k]) {
                    k = j;
                }
            }
            if (k!=i) {
                int temp = a[k];
                a[k] = a[i];
                a[i] = temp;
            }
        }
    }

5.归并排序[稳定]

原理:采用分治法

复杂度:O(nlogn) - O(nlgn) - O(nlgn) - O(n)[平均 - 最好 - 最坏 - 空间复杂度]

// 排序
    public void mergeSort(int[] a, int low, int high) {

        int mid = (low   high) / 2;
        if (low < high) {
            // 左边排序
            mergeSort(a, low, mid);
            // 右边排序
            mergeSort(a, mid   1, high);
            // 有序序列合并
            merge(a, low, mid, high);
        }
    }
    
    // 合并
    private void merge(int a[], int low, int mid, int high) {
        // 临时数组
        int[] temp = new int[high - low   1];
        // 左指针
        int i = low;
        // 右指针
        int j = mid   1;
        // 临时数组索引
        int k = 0;
        
        while (i <= mid && j <= high) {
            if (a[i] < a[j]) {
                temp[k  ] = a[i  ];
            } else {
                temp[k  ] = a[j  ];
            }
        }
        
        // 把左边剩余的数移入数组  
        while (i <= mid) {
            temp[k  ] = a[i  ];
        }
        
        // 把右边剩余的数移入数组  
        while (j <= high) {
            temp[k  ] = a[j  ];
        }
        
        // 注意这里是low   t
        for (int t = 0; t < temp.length; t  ) {
            a[low   t] = temp[t];
        }
    }

6.快速排序[不稳定]

原理:分治 递归

复杂度:O(nlgn) - O(nlgn) - O(n^2) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

栈空间0(lgn) - O(n)

// 固定基准
public void quickSort(int[] a, int low, int high) {
        if (null == a || a.length < 2) {
            return;
        }
        if (low < high) {
            int mid = partition(a, low, high);
            quickSort(a, low, mid-1);
            quickSort(a, mid 1, high);
        }
    }

    private int partition(int[] a, int low, int high) {
        int pivot = a[low];

        while (low < high) {
            // 注意等于,否则死循环
            while (low < high && a[high] >= pivot) {
                high--;
            }
            a[low] = a[high];
            // 注意等于,否则死循环
            while (low < high && a[low] <= pivot) {
                low  ;
            }
            a[high] = a[low];
        }
        a[low] = pivot;
        
        return low;
    }

7.堆排序[不稳定]

堆一般指二叉堆。

复杂度:O(nlogn) - O(nlgn) - O(nlgn) - O(1)[平均 - 最好 - 最坏 - 空间复杂度]

大顶堆实现从小到大的升序排列,小顶堆一般用于构造优先队列

    public void heapSort(int[] a) {
        if (null == a || a.length < 2) {
            return;
        }
        
        buildMaxHeap(a);
        
        for (int i = a.length - 1; i >= 0; i--) {
            int temp = a[0];
            a[0] = a[i];
            a[i] = temp;
            
            adjustHeap(a, i, 0);
        }
    }

    // 建堆
    private void buildMaxHeap(int[] a) {
        int mid = a.length / 2;
        for (int i = mid; i >= 0; i--) {
            adjustHeap(a, a.length, i);
        }
    }
    
    // 递归调整堆
    private void adjustHeap(int[] a, int size, int parent) {
        int left = 2 * parent   1;
        int right = 2 * parent   2;
        
        int largest = parent;
        if (left < size && a[left] > a[parent]) {
            largest = left;
        }
        
        if (right < size && a[right] > a[largest]) {
            largest = right;
        }
        
        if (parent != largest) {
            int temp = a[parent];
            a[parent] = a[largest];
            a[largest] = temp;
            adjustHeap(a, size, largest);
        }
    }

8.基数排序[稳定]

原理:分配加收集

复杂度: O(d(n r)) r为基数d为位数 空间复杂度O(n r)

// 基数排序
    public void radixSort(int[] a, int begin, int end, int digit) {
        // 基数
        final int radix = 10;
        // 桶中的数据统计
        int[] count = new int[radix];
        int[] bucket = new int[end-begin 1];
        
        // 按照从低位到高位的顺序执行排序过程
        for (int i = 1; i <= digit; i  ) {
            // 清空桶中的数据统计
            for (int j = 0; j < radix; j  ) {
                count[j] = 0;
            }
            
            // 统计各个桶将要装入的数据个数
            for (int j = begin; j <= end; j  ) {
                int index = getDigit(a[j], i);
                count[index]  ;
            }
            
            // count[i]表示第i个桶的右边界索引
            for (int j = 1; j < radix; j  ) {
                count[j] = count[j]   count[j - 1]; 
            }
            
            // 将数据依次装入桶中
            // 这里要从右向左扫描,保证排序稳定性 
            for (int j = end; j >= begin; j--) {
                int index = getDigit(a[j], i);
                bucket[count[index] - 1] = a[j];
                count[index]--;
            }
            
            // 取出,此时已是对应当前位数有序的表
            for (int j = 0; j < bucket.length; j  ) {
                a[j] = bucket[j];
            }
        }
    }
    
    // 获取x的第d位的数字,其中最低位d=1
    private int getDigit(int x, int d) {
        String div = "1";
        while (d >= 2) {
            div  = "0";
            d--;
        }
        return x/Integer.parseInt(div) % 10;
    }
}

排序代码地址 https://github.com/Lemonjing/TinyCoding/tree/master/src/main/java/com/ryan/sort

性能测试代码地址 https://github.com/Lemonjing/TinyCoding/tree/master/src/test/java/com/ryan/sort

【感谢您能看完,如果能够帮到您,麻烦点个赞~】

更多经验技术欢迎前来共同学习交流:一点课堂-为梦想而奋斗的在线学习平台 http://www.yidiankt.com/

![关注公众号,回复“1”免费领取-【java核心知识点】]file

QQ讨论群:616683098

QQ:3184402434

想要深入学习的同学们可以加我QQ一起学习讨论~还有全套资源分享,经验探讨,等你哦!在这里插入图片描述

标签:Java,temp,int,复杂度,high,length,多岸,low,九种
来源: https://blog.csdn.net/chengweixin/article/details/100766400

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有