• 【算法拾遗(java描写叙述)】--- 选择排序(直接选择排序、堆排序)


    选择排序的基本思想

    每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子文件的最后,知道所有记录排序完毕。主要有两种选择排序方法:直接选择排序(或称简单选择排序)和堆排序。

    直接选择排序

    基本思想

    第i趟排序開始时,当前有序区和无序区分别为R[1 …… i-1]和R[i …… n](1 <= i <= n-1),该趟排序则是从当前无序区中选出关键字最小的记录R[k],将它与无序区的第一个记录R[i]交换,使R[1 …… i]和R[i+1 …… n]分别变为新的有序区和新的无序区。

    由于每趟排序均使有序区中添加了一个记录,且有序区中的记录关键字均不大于无序区中记录的关键字,即第i趟排序之后R[1 …… i].keys <= R[i+1 …… n].keys,所以进行n-1趟排序之后有R[1 …… n-1].keys <= R[n].key,即经过n-1趟排序之后,整个文件R[1 …… n]递增有序。注意,第一趟排序開始时。无序区为R[1 …… n],有序区为空。

    java程序

    /*************************
     * 
     * 直接选择排序(简单选择排序)
     *
     *************************/
    public class SelectSort {
    
        private void selectSort(int[] datas) {
            if (datas == null || datas.length < 2)
                return;
            int minValue;// 无序区最小值变量
            for (int i = 0; i < datas.length - 1; i++) {
                minValue = datas[i];// 将最小值变量初始化为无序区第一个位置上的值
                for (int j = i + 1; j < datas.length; j++) {
                    if (datas[j] < minValue) {
                        minValue = datas[j];
                        // 交换两数值
                        int temp = datas[i];
                        datas[i] = minValue;
                        datas[j] = temp;
                    }
                }
            }
    
        }
    
        public static void main(String[] args) {
            int[] datas = new int[] { 8, 5, 2, 6, 9, 3, 1, 4, 0, 7 };
            System.out.println("********排序前********");
            for (int i = 0; i < datas.length; i++) {
                System.out.print(datas[i] + ",");
            }
            SelectSort selectSort = new SelectSort();
            selectSort.selectSort(datas);
            System.out.println("
    ********排序后********");
            for (int i = 0; i < datas.length; i++) {
                System.out.print(datas[i] + ",");
            }
        }
    
    }
    

    性能分析

    1. 平均时间复杂度为O(n2
    2. 直接选择排序属于就地排序
    3. 直接选择排序是不稳定的

    堆排序

    基本思想

    堆排序是利用全然二叉树进行排序的方法

    堆首先是一棵全然二叉树

    然后满足一下条件之中的一个:

    (1) Ki <= K2i 而且Ki <= K2i+1

    (2) Ki >= K2i 而且Ki >= K2i+1

    堆有大根堆(或根结点关键字值最大的堆)和小根堆(根结点关键字最小)之分。

    大根堆排序算法的基本操作:初始化操作是将R[1 …… n]构造为初始堆;每一趟排序的基本操作是将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换。然后将新的无序区调整为堆(亦称为重建堆)。

    显然仅仅须要做n-1趟排序。选出较大的n-1个关键字就可以使文件递增有序。用小根堆排序全然与此类同,仅仅只是其排序结果是递减有序的。

    java程序

    
    public class HeapSort {
    
        /**
         * 建立大根堆
         * 
         * @param datas
         *            待排数组
         * @param s
         *            父节点
         * @param length
         *            无序项的个数
         */
        private void creatHeap(int[] datas, int s, int length) {
            int temp = datas[s];
            for (int j = 2 * s; j <= length; j *= 2) {
                if (j < length && datas[j] < datas[j + 1])
                    ++j;// j是关键字中较大的记录的下标
                if (temp >= datas[j])
                    break;
                datas[s] = datas[j];// 将最大值赋予父节点
                s = j;
            }
            datas[s] = temp;// 将原父节点的值赋予拥有最大值的子节点。完毕终于的交换
        }
    
        /**
         * 堆排序
         * 
         * @param datas
         *            待排序的数组
         * @param index
         *            待排序数组中待排项的个数
         */
        private void heapSort(int[] datas, int index) {
            if (datas == null || index < 2)
                return;
            for (int i = index / 2; i > 0; i--) {
                creatHeap(datas, i, index);
            }
            for (int i = index; i > 1; i--) {
                int temp = datas[i];
                datas[i] = datas[1];
                datas[1] = temp;
                // 对其余数值进行重建堆操作
                creatHeap(datas, 1, i - 1);
            }
        }
    
        public static void main(String[] args) {
            int[] datas = new int[10];
            datas[1] = 6;
            datas[2] = 5;
            datas[3] = 3;
            datas[4] = 1;
            datas[5] = 8;
            datas[6] = 7;
            datas[7] = 2;
            datas[8] = 4;
            datas[9] = 9;
            int index = 9;
            System.out.println("********排序前********");
            for (int i = 1; i < index + 1; i++) {
                System.out.print(datas[i] + ",");
            }
    
            HeapSort heapSort = new HeapSort();
            heapSort.heapSort(datas, index);
    
            System.out.println("
    ********排序后********");
            for (int i = 1; i < index + 1; i++) {
                System.out.print(datas[i] + ",");
            }
        }
    
    }
    

    性能分析

    堆排序的时间主要是由建立初始堆和重复重建堆这两部分的时间开销构成,它们均是通过调用HeapSort实现的。

    1. 堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均时间性能较接近于最坏性能
    2. 由于建初始堆所需的比較次数较多,所以堆排序不适宜于记录数比較少的文件
    3. 堆排序是就低排序,辅助空间为O(1)
    4. 堆排序的时间复杂度为O(nlgn),是一种不稳定的排序方法

    參考资料:《数据结构与算法分析——java语言描写叙述》、《大话数据结构》

  • 相关阅读:
    HDU-6534-Chika and Friendly Pairs (莫队算法,树状数组,离散化)
    SPOJ-DQUERY-D-query
    视频上云/网络穿透/拉转推工具EasyNTS设备IP地址返回数据与实际IP匹配的筛选机制优化
    视频上云/网络穿透/拉转推工具EasyNTS新增获取windows所有盘符信息功能的实现
    【解决方案】热门景区实现智慧旅游,城市道路/风景区视频公众号分享该如何实现?
    TSINGSEE青犀视频开发webrtc使用ffmpeg编译报ffmpeg version: N-94448-G3CEA9CD219提示是什么原因
    TSINGSEE青犀视频开发webrtc浏览器使用video标签播放webrtc本地录音音频实现过程
    【解决方案】智慧农业自动化的浪潮下,大棚实时视频监控系统应该如何搭建?
    【解决方案】房地产行业施工现场搭建视频4G无线远程视频监管信息化行业应用方案建议书
    【解决方案】国标GB28181协议视频智能分析平台EasyCVR搭建智慧养殖平台,让畜牧业实现“万物互联”
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7089153.html
Copyright © 2020-2023  润新知