Java排序 ------ 选择排序

选择排序

算法中最基础的当数排序了,今天整理记录一下Java中的选择排序

这里的排序方式按从小到大讲,由大到小其实就是改变下符号。

选择排序有两种实现方式:
一、简单的选择排序
二、堆排序

因为简单的选择排序比较简单,所以这里先讲它吧。

一、简单的选择排序

简单的选择排序,思想很简单;
①开始找到序列1…. n 中最小的元素,把它和 1 处进行交换;
②然后找到2 …… n 中最小的元素,把它和 2 处进行交换;
③以此类推,可知需要遍历 n - 1 次元素。

代码实现
    public void selectSort(int[] elements){
        int length = elements.length;
        for (int i = 0; i < length - 1  ; i++) { // 利用外层循环控制序列开始的位置
            /*下面就是找到序列 i ...... length 中最小元素的下标*/
            int minIndex = i; 
            for (int j = i + 1; j < length; j++) { 
                if (elements[j] < elements[minIndex]){
                    minIndex = j;
                }
            }

            /*下面是交换位置*/
            if (minIndex != i){
                int temp = elements[minIndex];
                elements[minIndex] = elements[i];
                elements[i] = temp;
            }
        }
    }


二、堆排序

堆排序,堆排序相对就是很复杂了,它涉及到了完全二叉树和有顺序的完成二叉树,也是因为复杂,这种排序方式相当的快,关于各种排序方式的转到博客
Java排序 —— 归并排序 及 排序算法比较图
。 这里先跟大家简单说说完全二叉树和有顺序的完全二叉树

完全二叉树:一种树形结构,节点分为父节点和左、右孩子节点;且从倒数第二层开始以上各层的每个节点都有两个孩子节点,其余节点随意。

有顺序的完全二叉树:一种按大顶堆/小顶堆 排列的完全二叉树。
按小顶堆排序的完全二叉树:父节点必须比子节点小;
按大顶堆排序的完全二叉树:父节点必须比子节点大。

因为我们要实现从小到到大排序,所以这里采用按大顶堆排序;
堆排序的基本思想就是:
1、就序列 [1…..n] 看成是完全二叉树的结构;
2、对完全二叉树按大顶堆进行排序;
3、将排序后的序列的头尾交换数据;
4、然后把 [1…..n-1] 的序列继续看出完全二叉树结构,重新进行大顶堆排序;
5、重复以上过程 n -1 次。

这里有个隐含的条件就是:
数组对应的完全二叉树有这么个关系
父节点:i
左节点:2 * i + 1
右节点:2 * i + 2 //隐含 有右节点就一定有左节点
//由以上关系可以知道,数组从第0个到第length / 2 - 1 个元素才是父节点。

代码实现
    private void heapSort(int[] elements) {
        int length = elements.length;
        for (int i = length; i >= 1; i--) {//长度由于数组头尾元素的交换而递减
            maxHeap(elements, i, 0);//从第一个元素开始排序完全二叉树,实现有顺序的完全二叉树
            swap(elements, 0, i - 1); // 交换数组第一个元素和最后一个元素
        }
    }

    // 对父节点和左、右节点进行排序,实现有顺序的完全二叉树
    private void maxHeap(int[] elements, int heapSize, int index) {
            int largest = index; // 完全二叉树中某个父节点    
            int left = index * 2 + 1; // 某个父节点的左节点
            int right = index * 2 + 2; // 某个父节点的右节点

            //将父节点的值和 比父节点值大的孩子节点的值交换。
            if (left < heapSize/*判读有左节点吗*/ && elements[left] > elements[index])
                largest = left;

            if (right < heapSize /*判读有右节点吗*/&& elements[right] > elements[largest])
                largest = right;

            if (index != largest){ 
                swap(elements, index, largest);         
            }
            if (index <= elements.length / 2 - 1){ // 还是父节点吗
                maxHeap(elements, heapSize, index + 1);//对下一个父节点排序
            }
    }

    private void swap(int[] elements, int left, int right){
        int temp = elements[left];
        elements[left] = elements[right];
        elements[right] = temp;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值