【算法拾遗(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("\n********排序后********");
        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("\n********排序后********");
        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语言描写叙述》、《大话数据结构》

时间: 2024-08-10 02:09:42

【算法拾遗(java描写叙述)】--- 选择排序(直接选择排序、堆排序)的相关文章

【算法拾遗(java描写叙述)】--- 插入排序(直接插入排序、希尔排序)

插入排序基本思想 每次将一个待排序的记录按其keyword大小插入到前面已经拍好序的子文件的适当位置,直到全部记录插入完毕为止. 直接插入排序 基本思想 直接插入排序的基本操作是将一个记录插入到已排好序的有序表中.从而得到一个新的有序表.即如果待排序的记录存放在数组R[1······n]中,排序过程中,R被分成两个子区间R[1······i]和R[i+1······n],当中.R[1······i]是已经排好序的有序区:R[i+1······n]是当前未排序的部分. 将当前无序区的第一个记录R[

必须知道的八大种排序算法【java实现】(二) 选择排序,插入排序,希尔算法【详解】

一.选择排序 1.基本思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换:然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止. 2.实例 3.算法实现 /** * 选择排序算法 * 在未排序序列中找到最小元素,存放到排序序列的起始位置 * 再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾. * 以此类推,直到所有元素均排序完毕. * @param numbers */ public static void selectSort(in

【OpenCV新手教程之十八】OpenCV仿射变换 &amp;amp; SURF特征点描写叙述合辑

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/33320997 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 知乎:http://www.zhihu.com/people/mao-xing-yun 邮箱: [email protected] 写作当前博文时配套使用的OpenCV版本号: 2.4.9 本篇文章中.我们一起探讨了OpenCV

简单排序之选择排序算法JAVA实现

选择排序原理 选择排序是一种简单排序算法.这是一个基于位置比较的算法,通常实现是左边是已经排好序的元素列表,右边是待排序的元素.当然,一开始的时候,我们认为都是未经排序的. 选择排序的精髓:与冒泡排序不同,选择排序是第N趟排序先确定最小元素的位置,然后和第N个元素交换位置.主要特点是每一趟选择一个最小值的索引作为梅一堂最后交换的位置.以一个元素个数为N的整形数组arr为例: 第一趟 以第一个元素arr[0]为基准,准备好一个中间变量temp用来记录该趟最小元素的位置,一开始,temp=0,比较a

7种基本排序算法的Java实现

7种基本排序算法的Java实现 转自我的Github 以下为7种基本排序算法的Java实现,以及复杂度和稳定性的相关信息. 以下为代码片段,完整的代码见Sort.java 插入排序 1 /** 2 * 直接插入排序 3 * 不稳定 4 * 时间复杂度:O(n^2) 5 * 最差时间复杂度:O(n^2) 6 * 空间复杂度:O(1) 7 * 使用场景:大部分元素有序 8 * @param elements 9 * @param comparator 10 * @param <T> 11 */ 1

常用排序算法的Java实现 - 1

学习编程语言时, 我们会接触到许多排序算法, 这里总结了一下常见的排序算法. 不定期更新. * 其实在Java中存在如Collections.sort()这样的方法来自动为我们排序, 不过学习排序算法能让我们更好的理解一门编程语言. 1. 冒泡排序: 该算法是最基本也是最有名的算法之一了. 1 public static void bubbleSort(int[] arr) { 2 for(int i = 0; i < arr.length - 1; i++) { 3 for(j = 0; j

[转]各种排序算法及其java程序实现

原文:http://blog.csdn.net/t12x3456/article/details/7430700 各种排序算法:冒择路(入)兮(稀)快归堆,桶式排序,基数排序 冒泡排序,选择排序,插入排序,稀尔排序,快速排序,归并排序,堆排序,桶式排序,基数排序 一.冒泡排序(BubbleSort)1. 基本思想: 两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止.2. 排序过程: 设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的

常见排序算法总结(java实现)

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.常见的排序算法有选择排序,插入排序,希尔排序,归并排序和快速排序 由于在排序的过程中不可避免的要涉及到比较和交换,所以将他们抽取为两个单独的函数,如下所示 //为了排序代码的通用性,这里假定待排序的元素实现了Comparable接口 private static boolean less(Comparable v ,Comparable w){ return v.compareTo(w)<0; } priva

排序算法6--选择排序--简单选择排序

简单选择排序 简单选择排序属于选择排序, 选择排序的思想是:每一趟从待排序的记录中选出关键字最小的记录,按顺序放在以排序的记录序列的后面,知道全部排完为止. 1.简单选择排序法是每次循环找出最值,循环结束后将最值调整到合适位置,交换的次数少. 每次找出当前无序队列中的最小的元素与第一个交换位置,再选择第二小的与第二个交换位置 原始队列:   3 5 6 2 4 1(最小元素1与3交换) 第一步: 1 5 6 2 4 3 (当前最小元素2与5交换) 第二步: 1 2 6 5 4 3 (当前最小元素