【算法】常见的排序算法(插入排序、希尔排序、选择排序、冒泡排序、快速排序、归并排序)

news2024/9/22 13:28:38

目录

  • 一.常见排序类型
  • 二.排序详解
    • 1.冒泡排序
    • 2.选择排序
    • 3.插入排序
    • 4.希尔排序
    • 5.快速排序
    • 6.归并排序

一.常见排序类型

  • 插入排序:插入排序、希尔排序
  • 选择排序:简单选择排序、堆排序
  • 交换排序:冒泡排序、快速排序
  • 归并排序
  • 基数排序(又叫桶排序)
  • 八万个数字进行排序 选择排序速度 > 插入排序> 冒泡排序

二.排序详解

1.冒泡排序

(1)思路图解

从头开始比较相邻元素的值(就是从下标较小的元素开始),使值较大的元素逐渐从前移向后部,就像水里的气泡一样,越来越大,向上冒。最终得到从小到大的一个序列。

在这里插入图片描述

(2)算法实现(java)

/**
 * 冒泡排序
 * author:xinxin
 * 时间复杂度是(n*n)
 */
public class GuLouSort {
    public static void main(String[] args) {
        int[] arr = {16,28,5,66,88}; //初始化数组
        int temp = 0; //临时变量
        for (int i = 0; i < arr.length-1; i++){ //代表大循环  第几趟
            for (int j = 0; j < arr.length-1-i; j++){ //代表小循环
                if (arr[j] > arr[j+1]){ //如果前面的值大于前面的值,那就交换位置
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
            System.out.println("第"+(i+1)+"趟,排序后的结果");
            System.out.println(Arrays.toString(arr));
        }
    }
}

运行结果
在这里插入图片描述

2.选择排序

(1)思路图解

先从arr[0] ~ arr[n-1]找到一个最小值,和arr[0]交换,在从arr[1] ~ arr[n-1]中找到最小值,和arr[1]交换,以此类推,最终得到一个从小到大排列的序列。

在这里插入图片描述

(2)算法实现(java)

/**
 * 选择排序
 * author:xinxin
 * 时间复杂度是(n*n)
 */
public class SelectSort {
    public static void main(String[] args) {
        int[] arr = {16,6,88,2}; //初始化数组
        for (int i = 0; i < arr.length-1; i++) { //代表第几轮循环
            int minIndex = i; //假定最小下标
            int minArr = arr[i]; //假定最小的值
            for (int j = i+1; j < arr.length; j++) { //代表每轮循环中去查找最小的值
                if (minArr > arr[j]){ //如果假定的最小值比他后面的值要大,记录下标和值(这个地方控制是从大到小排序还是从小到大排序)
                    minIndex = j;    //记录下标
                    minArr = arr[j]; //记录值
                }
            }
            //交换值
            if (minIndex != i){
                arr[minIndex] = arr[i];
                arr[i] = minArr;
            }
            System.out.println("第"+(i+1)+"轮结果为");
            System.out.println(Arrays.toString(arr));
        }
    }
}

运行结果
在这里插入图片描述

3.插入排序

(1)思路图解

n个元素,分成一个有序序列和无序序列,开始有序序列只有一个元素,无序序列包含n-1个元素,排序时每次从无序序列取出第一个元素,和有序序列的元素的排序码进行比较,然后放到合适的位置,最后形成新的有序序列。

在这里插入图片描述
(2)算法实现(java)

/**
 * 插入排序
 * author:xinxin
 */
public class InsertSort {
    public static void main(String[] args) {
        int[] arr = {18, 6, 26, 15,  21,10};//初始化数组
        for (int i = 1; i < arr.length; i++) {
            int currValue = arr[i]; //要插入的元素,从arr[1]开始,因为arr[0]是有序序列第一个元素
            int beforeIndex = i-1; //要插入元素前面的元素的下标
            while(beforeIndex >= 0 && currValue < arr[beforeIndex]){ //判断要插入元素的位置,并且没有找到插入位置(从这里可以改变从大到小排序还是从小到大)
                arr[beforeIndex + 1] = arr[beforeIndex]; //arr[beforeIndex]后移
                beforeIndex--;
            }

            //当退出while循环,找到插入位置
            arr[beforeIndex + 1] = currValue;
            System.out.println("第"+i+"次插入结果");
            System.out.println(Arrays.toString(arr));
        }

    }
}

运行结果
在这里插入图片描述

4.希尔排序

(1)思路图解

希尔排序也是一种插入排序,但是更加高效,也称为速效增量排序。
按照一定的增量(步长)进行分组,然后对每组进行插入排序,随着增量减少,每组的元素就越多,当增量减至1时,元素被分为一组,算法结束。

在这里插入图片描述

(2)算法实现(交换法)

/**
 * 希尔排序(交换法)
 * author:xinxin
 */
public class ShellSort {
    public static void main(String[] args) {
        int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};//初始数组
        int temp = 0;
        int count = 0;
        //增量
        for (int gap = arr.length/2; gap > 0; gap=gap/2){
            //遍历组中所有元素,gap为步长
            for (int i = gap; i < arr.length; i++){
                for (int j = i - gap; j >= 0; j = j-gap){
                    //如果当前元素大于加上步长的元素,那就交换位置
                    if (arr[j] > arr[j+gap]){
                        temp = arr[j];
                        arr[j] = arr[j+gap];
                        arr[j+gap] = temp;
                    }
                }
            }
            System.out.println("希尔排序(交换法)第"+(++count)+"轮的结果");
            System.out.println(Arrays.toString(arr));
        }
    }
}

运行结果(交换法)
在这里插入图片描述

(3)算法实现(移动法)

/**
 * 希尔排序(移动法)
 * author:xinxin
 */
public class ShellSort2 {
    public static void main(String[] args) {
        int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};//初始数组
        int count = 0;
        for (int gap = arr.length/2; gap > 0; gap = gap/2){
            //从第gap元素开始进行插入排序
            for (int i = gap; i<arr.length; i++){
                int j = i;
                int temp = arr[j];
                if (arr[i] < arr[j - gap]){
                    while(j - gap >= 0 && temp < arr[j - gap]){
                        //移动
                        arr[j] = arr[j - gap];
                        j = j - gap;
                    }
                    arr[j] = temp;
                }
            }
            System.out.println("希尔排序(移动法)第"+(++count)+"轮的结果");
            System.out.println(Arrays.toString(arr));
        }
    }
}

运行结果(移动法)
在这里插入图片描述

5.快速排序

(1)思路图解

快速排序是对冒泡排序的一种改进。
基本思想是:把需要排序的元素分成两部分,一部分比另一部分都要小,然后进行快速排序,然后递归,最终得到有序序列。

在这里插入图片描述

(2)算法实现(java)

/**
 * 快速排序
 * author:xinxin
 */
public class QuikeSort {
    public static void main(String[] args) {
        int[] arr = {1, 66, 2, 28, 0, 18};
        quickeSotr(arr,0,arr.length-1);
        System.out.println("快速排序结果为"+ Arrays.toString(arr));
    }

    public static void quickeSotr(int arr[],int left,int right){
        int l = left;//左下标
        int r = right;//右下标
        int center = arr[(l + r)/2];//中间值
        int temp = 0;//临时变量

        //找到比center值小的放左边,比center值大的放右边
        while(l < r){
        
            //找到比center小的值,才退出
            while (arr[l] < center){
                l = l + 1;
            }
            //找到比center大的值,才退出
            while (arr[r] > center){
                r = r - 1;
            }

            //证明左边都是小于center的数,右边都是大于center的数
            if (l >= r){
                break;
            }
            //交换变量
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            //前移
            if (arr[l] == center){
                r = r - 1;
            }

            //后移
            if (arr[r] == center){
                l = l + 1;
            }
        }

        //如果相等必须进行下面操作,不然会栈溢出
        if (l == r){
            l = l + 1;
            r = r - 1;
        }

        //向左递归
        if (left < r){
            quickeSotr(arr,left,r);
        }

        //向右递归
        if (right > l){
            quickeSotr(arr,l,right);
        }
    }
}

运行结果
在这里插入图片描述

6.归并排序

(1)思路图解

利用归并的思想实现排序,采用分治策略:将问题分成小的问题然后递归求解,而治的阶段将分的阶段得到的结果放一起组合,即分而治之。

下面治的阶段相当于 [4,5,7,8]和[1,2,3,6]各有指针去移动比较两个数组元素大小(和快速排序移动指针一样),然后放入新的数组。

在这里插入图片描述
(2)算法实现(java)

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
        int[] temp = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        System.out.println("归并排序结果为"+ Arrays.toString(arr));
    }

    /**
     * 分 + 合
     * @param arr
     * @param left
     * @param right
     * @param temp
     */
    public static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if (left < right){
            int center = (left + right)/2;//中间索引
            mergeSort(arr,left,center,temp);//左递归
            mergeSort(arr,center + 1,right,temp);//右递归
            merge(arr,left,center,right,temp);//合并(治)
        }
    }
        /**
         * 合并的方法
         * 
         * @param arr 原数组
         * @param left 左下标
         * @param center 中间值
         * @param right 右下标
         * @param temp 中转数组
         */
    public static void merge(int[] arr, int left, int center, int right, int[] temp){
        int i = left;//左边序列初始索引
        int j = center + 1;//右边序列初始索引
        int t = 0;//temp数组初始下标

        //把左右两边的有序序列按规则填充到temp中
        while(i <= center && j <= right){
            //当左边序列元素小于右边序列元素,把左边序列元素放进temp数组中
            if (arr[i] < arr[j]){
                temp[t] = arr[i];
                i = i + 1;
                t = t + 1;
            }else{//反之,将右边序列元素放进temp数组中
                temp[t] = arr[j];
                j = j + 1;
                t = t + 1;
            }
        }
        //左边序列剩余元素放进temp数组
        while(i <= center){
            temp[t] = arr[i];
            i = i + 1;
            t = t + 1;
        }

        //右边序列剩余元素放进temp数组
        while(j <= right){
            temp[t] = arr[j];
            j = j + 1;
            t = t + 1;
        }
        
        //将temp拷贝到arr,有可能不是全部拷贝
        t = 0;
        int tempLeft = left;
        System.out.println(" ");
        System.out.println("tempLeft="+tempLeft+" right="+right);
        while (tempLeft < right){
            arr[tempLeft] = temp[t];
            tempLeft = tempLeft + 1;
            t = t + 1;
        }
    }
}

运行结果
在这里插入图片描述

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

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

相关文章

Java项目:新闻推荐管理系统(java+SSM+JavaScript+Ajax+Mysql)

源码获取&#xff1a;俺的博客首页 "资源" 里下载&#xff01; 项目介绍 本项目新闻推荐管理系统&#xff1b; 前台: 登录、首页、全部新闻、系统特色、猜你喜欢、分类、评论 后台&#xff1a; &#xff08;1&#xff09;文件管理&#xff1a;文件列表。 &#x…

3.无重复字符的最长子串

原题&#xff1a;https://leetcode.cn/problems/longest-substring-without-repeating-characters/ 目录 题目描述 题解 代码实现 题目描述 给定一个字符串s&#xff0c;请你找出其中不含有重复字符的最长子串的长度。 示例 1&#xff1a; 输入&#xff1a;s "…

微型计算机技术及应用笔记

微型计算机概述 主机系统包括&#xff1a; CPU存储器输入输出接口总线CPU包括&#xff1a; 运算器&#xff08;ALU&#xff09;控制器&#xff08;CU&#xff09;寄存器组&#xff08;Register&#xff09;寄存器&#xff1a;通用寄存器、专用寄存器 控制器由指令寄存器、指令…

攻防世界——Web新手练习区

目录 view_source get_post robots ​backup cookie disabled_button simple_js xff_referer weak_auth command_execution simple_php view_source 知识点&#xff1a; 查看网页源代码的几种方式&#xff1a; 按F12键&#xff0c;点击elements可以查看源代码快捷…

《图解TCP/IP》阅读笔记(第六章 6.1、6.2)—— 传输层的作用、端口号

第六章 TCP与UDP TCP与UDP和赫赫威名&#xff0c;在此前几章已略有耳闻。 TCP提供可靠的通信传输&#xff0c;而UDP则常被用于让广播和细节控制交给应用的通信传输。 首先&#xff0c;我们先来回顾一下传输层的定义。 上一章中提到过&#xff0c;IP中有一个协议字段&#x…

猿如意|程序员的如意神器之【chat GPT】测评。

chat GPT测评1、使用感受2、功能展示3、期待优化地方3.1 猿如意网页版搜索功能3.2 chat GPT3.2.1 测试抢券才能体验3.2.2 聊天体验1、使用感受 首先&#xff0c;需要对猿如意进行点赞。 正如宣传语所说&#xff0c;猿如意&#xff0c;程序员的的如意兵器&#xff0c;这句话&am…

[附源码]Node.js计算机毕业设计个性化旅游线路推荐系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

WordCloud库简介与使用示例

今天继续给大家介绍Python相关知识&#xff0c;本文主要内容是WordCloud库简介与使用示例。 一、WordCloud库简介与安装 WordCloud是一款Python的第三方库&#xff0c;可以用于生成词云。词云可以以词语为基本单位&#xff0c;然后根据词语的出现频率确定词语的大小&#xff…

linux red hat 8.0 root密码破解

简介&#xff1a; root用户是linux用户最大权限的用户&#xff0c;如果不慎将其密码忘记是不可直接更改的&#xff0c;只能通过破解的方式来重置root密码。 linux系统的启动过程&#xff1a; 1 开机自检&#xff08;POST&#xff09;&#xff0c;初始化部分硬件 2 搜素可用…

嵌入式从业者应知应会知识点 - 索引

大家好&#xff0c;我是痞子衡&#xff0c;是正经搞技术的痞子。本系列痞子衡给大家介绍的是嵌入式从业者应知应会知识点。 嵌入式开发需要掌握的知识点非常多&#xff0c;不同的技术方向有不同的知识侧重点&#xff0c;本系列试图整理总结嵌入式开发&#xff08;尤其是软件&a…

毕业设计 stm32车牌识别 - 单片机 嵌入式 物联网 机器视觉

文章目录0 前言1 简介2 主要器件3 实现效果4 设计原理5 部分核心代码5 最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长…

juc-3-volatile

目录 1 多线程下变量的不可见性及解决方案 2 不可见性解决方案 2.1 加锁方式解决 2.2 使用volatile关键字 2.3 while(true)速度快调用本地线程内存&#xff0c;加延时即可访问主内存的共享变量 3 volatile不保证原子性以及解决方案 3.1 案例 volatile 验证不是原子性 3.…

详细解析预处理

预处理一.总体概述1.注释去除2.宏替换二.宏定义1.数值宏常量2.字符串宏常量3.用宏定义注释符号4.用宏定义表达式&#xff08;难点&#xff09;1.第一种情况2.第二种情况5.#undef&#xff08;宏的有效范围&#xff09;1.两个问题2.#undef的使用3.一段代码的理解三.条件编译1.#if…

基于nodejs商城系统开发与设计(项目源码+论文设计+ppt答辩+视频录制)

网上购物商城系统以弥补传统购物方式的弊端。在目前的商城里&#xff0c;如果采用网上商城方式&#xff0c;用户购物时就不需要到店里面排队&#xff0c;这样不仅能实时地了解商品的特色&#xff0c;而且方便了顾客&#xff0c;同时也减轻了商城的服务压力。随着WLAN技术的普及…

计算机毕设Python+Vue新文道考研机构在线教学辅导系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

python的panda库读写文件

目录 1.读取excel文件 &#xff08;1&#xff09;语法 &#xff08;2&#xff09;实例 2.读取cvs文件 &#xff08;1&#xff09;语法 &#xff08;2&#xff09;实例 3.读取txt文件 &#xff08;1&#xff09;语法 &#xff08;2&#xff09;实例 4.写入文件 &…

【driver.js】基础使用

介绍 driver.js: 轻量级、无依赖性、普通的 JavaScript 引擎&#xff0c;可在整个页面上推动用户的注意力; &#x1f506;突出显示页面上的任何&#xff08;字面上的任何&#xff09;项目✋阻止用户交互&#x1f4e3; 创建功能介绍&#x1f453;为用户添加焦点转移器&#x1f6…

【Flask框架】——21 Flask上下文

上下文&#xff1a;即语境&#xff0c;语意&#xff0c;在程序中可以理解为在代码执行到某一时刻时&#xff0c;根据之前代码所做的操作以及下文即将要执行的逻辑&#xff0c;可以决定在当前时刻下可以使用到的变量&#xff0c;或者可以完成的事情。 Flask中有两种上下文&…

UDP的报文结构和注意事项

UDP的报文结构和注意事项一、传输层协议二、UDP报文结构一、传输层协议 传输层实现了端到端之间的传输&#xff0c;重点关注的是起点和终点。 核心的协议有两个&#xff1a; 二、UDP报文结构 大部分教科书给出的报文结构都是这样的&#xff1a; 其实只是为了排版方便~~ 实…

关于进程的几个问题

作者&#xff1a;~小明学编程 文章专栏&#xff1a;JavaEE 格言&#xff1a;热爱编程的&#xff0c;终将被编程所厚爱。 今天给大家分享几个关于进程的小问题 1.什么是进程&#xff1f; 2.进程是怎么管理的&#xff1f; 3.进程里面的PCB里都有啥&#xff1f; 4.进程的调度是怎…