百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

常见的排序算法 (下)(常见的7种排序算法)

toyiye 2024-07-08 00:31 18 浏览 0 评论

5. 归并排序

两个有序数组合并并不难, 但是归并的思想确实是这个, 但是如何分, 分到何时呢 ?

这个名字含义就是分为归和并 两个阶段执行

先说并吧, 并要求是两个已经排序好了的数组(两个连续数组是位置上也连续) , 比如1,2,3,4 , 连续数组1,23,4 , 不能是1,2,4进行排序 ,

对于两个已经排序好了的数据, 好处是一次遍历便可以将两个数组合并成一个有序的数组

然后再说 归吧, 归的思想就是 ,4,3,2,1 , 先分为4,32,1 , 将4,3继续分4,3,此时这就是两位置有序的数组, 将他俩数组进行并 , 就成了3,4 , 然后2,1分为2,1 , 此时再将这俩数组排序,此时是1,2 , 然后将3,41,2进行排序, 此时就是1,2,3,4 , OK了

/**
 * 归并排序
 *
 * 
 * @author: <a href='mailto:fanhaodong516@qq.com'>Anthony</a>
 */
public class MergeSort {

    public static void main(String[] args) {
        int[] arr_1000 = Common.generate_Arr_1000();
        splitAndMergerSort(arr_1000, 0, arr_1000.length - 1);
        Common.showArr(arr_1000);
    }


    /**
     * 将[1,2,3]数组分割成直到 [1][2][3]这种 ,递归实现
     *
     * @param arr   数组
     * @param start 开始位置 ,索引从0开始
     * @param end   结束位置 , 索引0开始
     */
    private static void splitAndMergerSort(int[] arr, int start, int end) {
        if (start == end) return;

        int middle = (end + start) >> 1;

        splitAndMergerSort(arr, start, middle);

        splitAndMergerSort(arr, middle + 1, end);

        merge(arr, start, end, middle + 1);
    }


    /**
     * @param arr       数据
     * @param start     索引从0开始 , 数组开始位置
     * @param end       索引从0开始 , 数组结束位置
     * @param delimiter 切割位置 : [1,2,4,5]   参数(arr,0 , 3 , 2) , 分隔符是 (star+end)/2+1
     */
    private static void merge(int[] arr, int start, int end, int delimiter) {
        if (start == end) return;

        // 1. 初始化数组
        int llen = delimiter - start;
        int rlen = (end - delimiter) + 1;

        int[] left = new int[llen];
        int[] right = new int[rlen];

        //2. 将分割数组 , 填充数据
        System.arraycopy(arr, start, left, 0, llen);
        System.arraycopy(arr, delimiter, right, 0, rlen);

        // 3.归并步骤
        int l = 0;
        int r = 0;
        int len = end + 1;
        for (int i = start; i < len; ++i) {
            if (l < llen && r < rlen) {
                if (left[l] < right[r]) {
                    arr[i] = left[l];
                    l++;
                } else {
                    arr[i] = right[r];
                    r++;
                }
            } else {
                if (l < llen) {
                    arr[i] = left[l];
                    l++;
                }
                if (r < rlen) {
                    arr[i] = right[r];
                    r++;
                }
            }
        }
    }

    // 第二种合并方式
    private static void merge(int[] left_arr, int[] right_arr) {
        int lL = left_arr.length;
        int rL = right_arr.length;
        int resultL = lL + rL;
        int[] result = new int[resultL];

        int l = 0;
        int r = 0;
        int w = 0;
        while (w < resultL) {
            if (l < lL && r < rL) {
                if (left_arr[l] < right_arr[r]) {
                    result[w] = left_arr[l];
                    l++;
                    w++;
                } else {
                    result[w] = right_arr[r];
                    r++;
                    w++;
                }
            } else {
                if (l < lL) {
                    System.arraycopy(left_arr, l, result, w, lL - l);
                    break;
                }
                if (r < rL) {
                    System.arraycopy(right_arr, r, result, w, rL - r);
                    break;
                }
            }
        }

        Common.showArr(result);
    }
}

6. 堆排序

数组他可以利用索引关系构建出一个完全二叉树 , 所以利用这个特性很好的组成堆,

堆排序 分为两个阶段

一阶段 : 堆化 - > 将数据转换成 大顶堆或者小顶堆 , 就是根节点数据大于子叶数据 , 就是大顶堆.

二阶段 : 利用大顶堆或者小顶堆进行排序 , 就是将堆顶和最后一个数据进行交换, 因为堆顶是最大值或者最小值, 然后堆化, 重复操作 ,

/**
 * 堆排序
 * 
 * @author: <a href='mailto:fanhaodong516@qq.com'>Anthony</a>
 */
public class HeapSort {

    public static void main(String[] args) {
        int[] arr_1000 = Common.generate_Arr_1000();
        heap_sort(arr_1000, arr_1000.length);

        Common.showArr(arr_1000);
    }

    /**
     * 堆排序
     *
     * @param tree
     * @param n
     */
    static void heap_sort(int[] tree, int n) {

        // 1. 构建一个堆
        build_heap(tree, n);

        // 2.
        // 堆顶和最后一个节点做交换 , 但是我们需要在数组上截取 , 所以就是每次
        for (int i = n - 1; i >= 0; i--) {
            // 交换节点
            swap(tree, i, 0);

            // 第0个位置 开始堆重新排序
            heapify(tree, i, 0);
        }
    }

    /**
     * 构建一个 大顶堆
     *
     * @param tree
     * @param n
     */
    static void build_heap(int[] tree, int n) {

        // 最后一个节点
        int last_node = n - 1;

        // 开始遍历的位置是 : 最后一个堆的堆顶 , 意思就是 , 整个树中最小的一个堆 , 其实就是最后一个节点的父节点
        int parent = (last_node - 1) / 2;

        // 递减向上遍历
        for (int i = parent; i >= 0; i--) {
            heapify(tree, n, i);
        }
    }




    /**
     * @param tree 代表一棵树
     * @param n    代表多少个节点
     * @param i    对哪个节点进行 heapify
     */
    static void heapify(int[] tree, int n, int i) {

        // 如果当前值 大于 n 直接返回了 ,一般不会出现这种问题 .....
        if (i >= n) {
            return;
        }

        // 子节点
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;

        // 假设最大的节点 为 i (父节点)
        int max = i;

        // 如果大于  赋值给 max
        if (c1 < n && tree[c1] > tree[max]) {
            max = c1;
        }

        // 如果大于  赋值给 max
        if (c2 < n && tree[c2] > tree[max]) {
            max = c2;
        }

        // 如果i所在的就是最大值我们没必要去做交换
        if (max != i) {

            // 交换最大值 和 父节点 的位置
            swap(tree, max, i);

            // 交换完以后 , 此时的max其实就是 i原来的数 ,就是最小的数字 ,所以需要递归遍历
            heapify(tree, n, max);
        }

    }


    static void swap(int[] tree, int max, int i) {
        int temp = tree[max];
        tree[max] = tree[i];
        tree[i] = temp;
    }

}

7. 桶排序

其实我认为他是 区间排序, 举个例子[1,2,3,4,5,6] , 将他放入6个区间内 , (0,1] ,(1,2] , 依次到最后 , 那么这个放置过程完全是可以通过计算得到的. 所以一次遍历便可以完成排序 , 如果区间内部排序, 可以选择其他排序方式.

package com.sort;

import java.util.Arrays;

/**
 * 桶排序  ,其实就是区间排序  1,2,3,4,5,6  ,我们分成 0-3, 3-6的区间(首先区间是有顺序的)
 * , 1,2,3 进去区间一, 4,5,6进去区间二 , 然后区间内排序, 此时就构建了新的数组
 *
 *
 * @author: <a href='mailto:fanhaodong516@qq.com'>Anthony</a>
 */
public class BucketSort {

    public static void main(String[] args) {

        int[] arr_1000 = Common.generate_Arr_1000();

        bucketSort(arr_1000, 10);

        Common.showArr(arr_1000);
    }

    /**
     * @param arr         数组
     * @param bucketCount 桶的个数
     */
    public static void bucketSort(int[] arr, int bucketCount) {
        int len = arr.length;
        if (len <= 1 || bucketCount <= 0) {
            return;
        }

        // 遍历一次找到最大值 最小值
        int max = arr[0], min = arr[0];
        for (int i : arr) {
            if (i > max) {
                max = i;
            }
            if (i < min) {
                min = i;
            }
        }

        /**
         * 划分区间 , 比如  5 - 11 ,此时我们需要 / 桶数量 (假如 是 2), 如果我们不+1 , 6 / 2 = 3 ,那么 (11-5)/3=2 , 此时坐标2这个桶
         *
         * 所以区间需要+1 操作 , 所以上面就是 7/2=3.5=4 , (11-5)/4=1
         */
        int range = ((max - min + 1) % bucketCount) == 0 ? (max - min + 1) / bucketCount : (max - min + 1) / bucketCount + 1;


        // 创建桶 ,是一个二维数组
        int[][] bucket = new int[bucketCount][];

        for (int i : arr) {
            bucket[(i - min) / range] = arrAppend(bucket[(i - min) / range], i);
        }


        for (int[] ints : bucket) {
            sort(ints);
        }

        int count = 0;
        for (int[] ints : bucket) {
            if (ints != null) {
                for (int anInt : ints) {
                    arr[count++] = anInt;
                }
            }
        }


    }

    /**
     * 数组拷贝
     *
     * @param arr
     * @param value
     * @return
     */
    private static int[] arrAppend(int[] arr, int value) {
        //数组如果为空, 新建一个数组,
        if (arr == null) {
            arr = new int[0];
        }
        // 数组拷贝 , 其实就是长度+1
        arr = Arrays.copyOf(arr, arr.length + 1);
        // 将值复制
        arr[arr.length - 1] = value;

        //返回
        return arr;
    }


    private static void sort(int[] arr) {

        /**
         * 空 或者  0 / 1 都直接返回
         */
        if (null == arr || arr.length <= 1) {
            return;
        }

        // 2 3 1
        for (int index = 1; index < arr.length; index++) {

            // 当前位置 , 开始必须从第二个开始
            int temp = arr[index];

            // 左边位置
            int left = index - 1;

            // 移动坐标其实就是 ...
            while (left >= 0 && arr[left] > temp) {

                // 互换位置
                arr[left + 1] = arr[left];

                // 向前移动
                left--;
            }

            // 最后保存数据
            arr[left + 1] = temp;
        }
    }

}

8. 基数排序

我没有写, 他和桶排序类似 , 一次比较个位数 , 十位数 , 百位数数据, 分成10个桶 , 对号入座, 第一遍比较个位数, 第二遍比较十位数, 第三遍比较百位数 .

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码