常见排序算法--Java实现

news2024/11/15 11:08:53

常见排序算法--Java实现

  • 插入排序
      • 直接插入排序
      • 折半插入排序
      • 希尔排序
  • 交换排序
      • 冒泡排序
      • 快速排序
  • 选择排序
      • 直接选择排序
      • 堆排序
  • 归并排序
  • 基数排序
  • 各种排序方法比较

在网上找了些排序算法的资料。此篇笔记本人总结比较,简单注释,觉得比较好理解,且相对简短方便记忆。

插入排序

直接插入排序

  • 默认第0个有序,后面挨个插入前面有序的数中(像打扑克插牌一样)
/**
 *(直接)插入排序
 * 默认第0个有序,后面挨个插入前面有序的数中(像打扑克插牌一样)
 */
public static void ChaRu(int a[], int n){
    int i,j;
    // 第0个有序,从第1个开始
    for(i = 1; i < n; i++){
        int temp = a[i];      // 要插入的元素保存起来
        // 在前面i-1个有序数组中,找插入的下标
        for(j = i - 1; j >= 0 && temp < a[j]; j--){
            a[j + 1] = a[j]; // 移动,覆盖
        }
        a[j + 1] = temp;     // 找到位置了,插入,继续把后面的插入,循环
    }
}

折半插入排序

  • 折半插入排序(增加二分查找)
/**
 * 折半插入排序(增加二分查找)
 */
public static void ZheBanCha(int a[], int n){
    int i, j;
    for(i = 1; i < n; i++){
        int temp = a[i]; 			 // 待插入的元素
        // 二分查找法,找插入的位置
        int left = 0, right = i - 1; // 0开始
        while(left <= right){
            int mid = (left + right) / 2;
            if(temp < a[mid]) right = mid - 1;
            else left = mid + 1;
        } // right + 1 为插入的位置
        // 统一后移元素,空出插入位置
        for(j = i - 1; j >= right + 1; j--){  // >=
            a[j + 1] = a[j];
        }
        a[right + 1] = temp; // right + 1 插入
    }
}

在这里插入图片描述

希尔排序

  • 希尔排序(新增for循环,步长为有序增量表:4,2,1)[把1变成d]
/**
 * 希尔排序(新增for循环,步长为有序增量表:4,2,1)[把1变成d]
 */
public static void shell(int[] a, int n) {
    int d, i, j;
    // 步长变化,每次减半,直到为1
    for(d = n / 2; d >= 1; d = d / 2){ // 新增for步骤
        for(i = d; i < n; i++){        // 1 -> d
            int temp = a[i];
            for(j = i - d; j >= 0 && temp < a[j]; j -= d){
                a[j + d] = a[j];
            }
            a[j + d] = temp;
        }
    }
}

在这里插入图片描述

交换排序

冒泡排序

  • 每一趟都会把最大的数排到最后,然后继续看前面的,不管最后的了(因为后面有序了)
/**
 * 冒泡排序(加了flag优化)
 * 每一趟都会把最大的数排到最后,然后继续看前面的,不管最后的了(因为后面有序了)
 */
public static void MaoPao(int[] a, int n) {
    for(int i = 0; i < n; i++){   // i趟数
        boolean flag = false;     // 提前退出冒泡循环的标志位
        for(int j = 0; j < n - i - 1; j++){
            if(a[j] > a[j+1]){    // 比后面大,就交换
                int temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
                flag = true;      // 表示有数据交换
            }
        }
        if(flag == false) return; // 本趟没有数据交换,提前退出
    }
}

在这里插入图片描述

快速排序

  • 快速排序(递归,轴,划分左右){ 轴元素放到最终位置,[比轴小,轴,比轴大] }
  • 与其他排序算法相反的是:元素越有序,快排时间复杂度越高
/**
 *  快速排序(递归,轴,划分左右){轴元素放到最终位置,[比轴小,轴,比轴大]}
 *  与其他排序算法相反的是:元素越有序,快排时间复杂度越高
 */
public static void QuickSort(int[] a, int low, int high) {
    if(low < high) {                         // 递归跳出的条件
        int pivot = patition(a, low, high);  // 划分函数
        QuickSort(a, low, pivot - 1);    // 划分左子表
        QuickSort(a, pivot + 1, high);   // 划分右子表
    }
}

// 用第一个元素将待排序列划分为左右两个部分(比轴小,比轴大)
public static int patition(int[] a, int low, int high) {
    int pivot = a[low];     // (暂存)第一个元素作为轴
    while(low < high) {     // 用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;             // 返回存放轴的最终位置
}

在这里插入图片描述

选择排序

直接选择排序

  • 简单选择排序(每趟选一个最小的元素,交换到前面)
/**
 * 简单选择排序(每趟选一个最小的元素,交换到前面)
 */
public static void JianDanXuanZe(int[] a, int n) {
    for(int i = 0; i < n -1; i++){        // 总共n-1趟,最后一次就不用了
        int min = i;                      // 记录此趟最小元素位置
        for(int j = i + 1; j < n; j++) {  // 再a[i..n-1]中选择最小元素
            if(a[j] < a[min])  min = j;   // 更新最小元素位置
        }
        if(min != i) {                    // 交换,把最小值放到i的位置
            int temp = a[i];
            a[i] = a[min];
            a[min] = temp;
        }
    }
}

在这里插入图片描述

堆排序

/**
 * 堆排序(从小到大)
 */
public static void heapSortAsc(int[] a, int n) {
    int i,tmp;

    // 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个(最大)二叉堆。
    for (i = n / 2 - 1; i >= 0; i--)
        maxHeapDown(a, i, n-1);

    // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
    for (i = n - 1; i > 0; i--) {
        // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
        tmp = a[0];
        a[0] = a[i];
        a[i] = tmp;
        // 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
        // 即,保证a[i-1]是a[0...i-1]中的最大值。
        maxHeapDown(a, 0, i-1);
    }
}

/**
 * (最大)堆的向下调整算法
 *
 * 注: 数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *     其中,N为数组下标索引值,如数组中第1个数对应的N为0。
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
 *     end   -- 截至范围(一般为数组中最后一个元素的索引)
 */
public static void maxHeapDown(int[] a, int start, int end) {
    int c = start;            // 当前(current)节点的位置
    int l = 2*c + 1;        // 左(left)孩子的位置
    int tmp = a[c];            // 当前(current)节点的大小

    for (; l <= end; c=l,l=2*l+1) {
        // "l"是左孩子,"l+1"是右孩子
        if ( l < end && a[l] < a[l+1])
            l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
        if (tmp >= a[l])
            break;        // 调整结束
        else {            // 交换值
            a[c] = a[l];
            a[l]= tmp;
        }
    }
}

在这里插入图片描述

归并排序

  • 归并排序(辅助数组,递归,分治,合并)
/**
 * 归并排序(辅助数组,递归,分治,合并)
 */
int[] tmp = new int[a.length];    // 新建一个临时数组存放*

public static void mergeSort(int[] a, int low, int high, int[] tmp) {
    if(low < high){
        int mid = (low + high) / 2;            // 从中间划分
        mergeSort(a, low, mid, tmp);           // 对左半部分归并排序
        mergeSort(a, mid + 1, high, tmp);  // 对右边部分归并排序
        // (上面两步递归,一直划分到每个子序列只含有一个元素)
        merge(a, low, mid, high, tmp);          // 合并两个有序序列(归并)
    }
}

// a[low..mid] 和 a[mid+1..high] 将两个部分归并(合并)
public static void merge(int[] a, int low, int mid, int high, int[] tmp) {
    int i, j, k;
    // 将a[] 中所有元素复制到 tmp[]辅助数组
    for(k = low; k <= high; k++) {
        tmp[k] = a[k];
    }
    // 两个区间,两个指针 i,j;比较,将较小值复制到 a[]中
    for(i = low, j = mid + 1, k = i; i <= mid && j <= high; k++){
        if(tmp[i] < tmp[j])
            a[k] = tmp[i++];
        else
            a[k] = tmp[j++];
    }
    // 若左右序列还有剩余,则将其全部拷贝进 a[]中
    while(i <= mid) a[k++] = tmp[i++];
    while(j <= high) a[k++] = tmp[j++];
}

在这里插入图片描述

基数排序

  • 基数排序(分配,收集)
**
 * 基数排序(分配,收集)
 *      个位分配,收集;十位分配,收集;...
 */
public static void radixSort(int[] a){
    int exp; // 指数。当对数组按各位进行排序时,exp=1;按十位进行排序时,exp=10
    // 获取数组a中最大值
    int max = a[0];
    for(int i = 1; i < a.length; i++){
        if(a[i] > max)  max = a[i];
    }
    // 从个位开始,对数组a按"指数"进行排序(个位,十位,百位。。。)
    for(exp = 1; max / exp > 0; exp *= 10){
        int[] output = new int[a.length];    // 存储"被排序数据"的临时数组
        int[] buckets = new int[10];         // 桶 0-9
        // 将数据出现的次数存储在buckets[]中
        for(int i = 0; i < a.length; i++){
            buckets[(a[i] / exp) % 10]++;
        }
        // 更改buckets[i]。目的是让更改后的buckets[i]的值,是该数据在output[]中的位置。
        for(int i = 1; i < 10; i++){
            buckets[i] += buckets[i - 1];
        }
        // 将数据存储到临时数组output[]中
        for(int i = a.length - 1; i  >= 0; i--){
            output[buckets[(a[i] / exp) % 10] - 1] = a[i];
            buckets[(a[i] / exp) % 10]--;
        }
        // 将排序好的数据赋值给a[]
        for (int i = 0; i < a.length; i++) {
            a[i] = output[i];
        }
    }
}

在这里插入图片描述

各种排序方法比较

在这里插入图片描述

引用:
代码后面附的总结PPT为王道数据结构课件截图
排序方法比较图片为青岛大学王卓老师的数据结构课件截图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/356726.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四大步骤,教你彻底关闭Win10自动更新

文章目录一、禁用Windows Update服务二、在组策略里关闭Win10自动更新相关服务三、禁用任务计划里边的Win10自动更新四、在注册表中关闭Win10自动更新参考资料一、禁用Windows Update服务 1、同时按下键盘 Win R&#xff0c;打开运行对话框&#xff0c;然后输入命令 services…

C语言运算符优先级和结合性一览表

所谓优先级就是当一个表达式中有多个运算符时&#xff0c;先计算谁&#xff0c;后计算谁。 运算符的优先级从高到低大致是&#xff1a;单目运算符、算术运算符、关系运算符、逻辑运算符、条件运算符、赋值运算符()和逗号运算符 简单记就是&#xff1a;&#xff01; > 算术运…

一起学 pixijs(1):常见图形的绘制

大家好&#xff0c;我是前端西瓜哥。 pixijs 是一个强大的 Web Canvas 2D 库&#xff0c;以其强大性能而著称。其底层使用了 WebGL 实现了硬件加速&#xff0c;当然如果不支持的话&#xff0c;也能回退为 Canvas。 本文使用的 pixijs 版本为 7.1.2。 Application Applicati…

【LeetCode】剑指 Offer 08. 二叉树的下一个节点 p65 -- Java Version

题目链接&#xff1a;无题目链接&#xff0c;不知道为啥力扣上找不到这一题。 1. 题目介绍&#xff08;08. 二叉树的下一个节点&#xff09; 题目&#xff1a;给定一个二叉树和其中的一个节点&#xff0c;请找出中序遍历顺序的下一个节点并且返回。注意&#xff0c;树中的节点…

linux线程阻塞中CPU的占用率

linux线程阻塞中CPU的占用率 一、简介 总所周知Linux系统下&#xff0c;我们编写的程序进入阻塞后&#xff0c;系统把任务挂起&#xff0c;交给内核进行处理&#xff0c;此时我们的进程CPU占用率不高&#xff0c;可以说是占用率0.0%&#xff0c;让CPU资源交给其他进程处理&am…

【算法】三道算法题目单词拆分,填充每个节点的下一个右侧节点指针以及组合总和

算法第一道算法题&#xff1a;单词拆分java解答参考第二道算法题&#xff1a;填充每个节点的下一个右侧节点指针java 解答参考第三道算法题&#xff1a;组合总和java解答参考大家好&#xff0c;我是小冷。 今天还是继续学习算法技术知识吧 第一道算法题&#xff1a;单词拆分 …

Docker - 镜像操作命令

镜像名称一般分为两部分组成:[repository]:[tag]在没有指定tag时&#xff0c;默认是latest&#xff0c;代表最新版本的镜像1.下载docker镜像 docker pull repository:tag2.查看本地所有镜像 docker images3.创建镜像别名 docker tag repository:tag repository111:tag4.查看镜像…

java面试题-集合篇

Collection1.Collection有哪些类&#xff1f;Java集合框架中的Collection接口是所有集合类的基础接口&#xff0c;定义了一些基本的集合操作&#xff0c;如添加元素、删除元素、判断是否包含某个元素等。常见的集合类包括List、Set和Queue。ListList接口定义了按照索引访问和操…

Module理解及使用

ES6的模块化设计思想是静态化&#xff0c;也就是说&#xff0c;在编译的时候确定模块的依赖关系&#xff0c;以及输出输出入的变量。而CommonJS和AMD模块都是在运行时确定的。ES6的模块不是对象&#xff0c;而是通过export显示指定输出的代码&#xff0c;再通过import命令输入。…

ES6新特性详解

文章目录1. let和const1.1 let声明变量1.2 const声明常量2. 模板字符串3. 解构赋值3.1 数组的解构赋值3.2 对象的解构赋值4. 函数扩展4.1 参数默认值4.2 剩余参数4.3 箭头函数5. 对象扩展5.1 对象简写5.2 属性名表达式5.3 扩展运算符6. Symbol7. Iterator和Generator7.1 Iterat…

k8s自动化安装脚本(kubeadm-1.23.7)

文章目录介绍软件架构版本介绍更新内容2023-02-192023-02-152023-02-142023-02-102022-10-202022-08-06准备部署包操作步骤环境准备结构备注解压部署包修改host文件脚本使用方式初始化环境验证ansible配置安装k8s集群登录master的节点添加node节点master节点状态检查组件安装安…

高精度算法一

目录 1. 基础知识 2. 大整数 大整数 3. 大整数 - 大整数 1. 基础知识 利用计算机进行数值计算&#xff0c;有时会遇到这样的问题&#xff1a;有些计算要求精度高&#xff0c;希望计算的数的位数可达几十位甚至几百位&#xff0c;虽然计算机的计算精度也算较高了&#xff0c…

大数据之---Nifi-处理器类别_详细了解各种处理器的含义用途---大数据之Nifi工作笔记0007

处理器有很多类这里主要分了,数据转换的可以看到上面的这些是数据转换常用的 然后: 这里这个controlrate,用来控制流的速率,来保护作用,防止崩掉 distributeLoad用来负载均衡,减轻压力 这里的路由是,根据是否满足对应的条件,来执行是否把数据路由到某个地方. 然后来看数据库…

数据库技术-函数依赖、键与约束、范式

一、函数依赖 给定一个x&#xff0c;能唯一确定一个Y&#xff0c;就称x确定Y&#xff0c;或者说Y依赖于x&#xff0c;例如YX*X函数。 函数依赖又可扩展以下两种规则: 部分函数依赖:A可确定C&#xff0c;(A,B)也可确定C,(A,B)中的一部分&#xff08;即A&#xff09;可以确定C&a…

Spring Cloud Nacos实战(一)- 下载和安装

Spring Cloud Alibaba Nacos下载和安装 Nacos介绍 ​ Nacos&#xff08;Naming Configuration Service&#xff09; 是一个易于使用的动态服务发现、配置和服务管理平台&#xff0c;用于构建云原生应用程序 ​ 服务发现是微服务架构中的关键组件之一。Nacos 致力于帮助您发现…

使用nginx单独部署Vben应用

前言 本文主要介绍Vben使用nginx单独部署的方式&#xff0c;其实前端发展到现在已经不是当年的jsp&#xff0c;asp必须要和后端一起部署了。单独部署调试的工具也很多&#xff0c;比如vue-cli-service 和 Vben中用到的vite &#xff0c;当然这些我们一般用在开发的工程中。正式…

SpringCloud(三)Hystrix断路器服务降级、服务熔断、服务监控案例详解

七、Hystrix断路器 7.1 简介 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系&#xff0c;每个依赖关系在某些时候将不可避免地失败。 多个微服务之间调用的时候&#xff0c;假设微服务A调用微服务B和微服务C&#xff0c;微服务B和微服务C又调用其它的微…

C# chart绘图 鼠标响应

1、图形自动滚动设置 chart1.ChartAreas[0].AxisX.Maximum 横坐标显示区域最大值 chart1.ChartAreas[0].AxisX.Minimum 横坐标显示区域最小值 显示宽度 chart1.ChartAreas[0].AxisX.Maximum - chart1.ChartAreas[0].AxisX.Minimum chart1.ChartAreas[0].AxisX.Maximum x_d…

ChatGPT从业影响之个人浅见

文章目录前言ChatGPT简介AI简介ChatGPT对从业者的影响参考资料前言 ChatGRT最近很火&#xff0c;网上有一些观点&#xff0c;他会取代很多职业&#xff0c;让产业产生颠覆性的变化。今天聊聊自己的想法&#xff0c;他的出现&#xff0c;是否会让我&#xff08;程序员&#xff…

qmt api 接口文档

http://qmt.ptradeapi.com 用户自行安装 Python 三方库 对于有经验的 Python 开发者来说&#xff0c;平台提供了自行安装第三方库的方式。为了引入额外的第三方库&#xff0c;用户需要做如下一些操作&#xff1a; 安装前注意事项&#xff1a; 三方库的安装有可能会引起系统错误…