常用内部排序算法之四:简单选择排序、直接插入排序和冒泡排序

本文主要是介绍常用内部排序算法之四:简单选择排序、直接插入排序和冒泡排序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

之所以把这三类算法放在一块,是因为除此之外的算法都是在这三类算法的基础上进行优化的。简单选择排序的思想是每一趟 ni+1(i=1,2,...,n1) 个记录中选择最小的记录作为有序序列的第 i 个记录。直接插入排序的思想是将一个记录插入到已经排好序的有序序列中,从而得到一个新的、记录数增加1的有序表。冒泡排序的算法思想是不断在交换,通过交换完成最终的排序,每一趟的交换就会把最大的记录取出来,下一趟则会把第二大的记录取出来,这样每进行一趟交换就把一个记录取出来的过程称为冒泡。

简单选择排序算法

简单选择的排序的算法思想是:通过ni次关键字间的比较,从 ni+1 个记录中选出关键字最小的记录,并和第 i(1in) 个记录交换之。其算法代码如下:

package com.rhwayfun.algorithm.sort;public class SelectSort {public void selectSort(int[] a){int i,j,min;for (i = 0; i < a.length; i++) {//假设第一个位置的值是最小值min = i;for(j = i + 1; j < a.length; j++){if(a[min] > a[j]){min = j;}}//如果min不等于i,说明找到最小值的下标if(min != i){swap(a,i,min);}}for(i = 0; i < a.length; i++){System.out.println(a[i]);}}private void swap(int[] a, int i, int min) {int temp = a[i];a[i] = a[min];a[min] = temp;}public static void main(String[] args) {new SelectSort().selectSort(new int[]{9,1,5,8,3,7,4,6,2});}
}

观察代码可以发现,第 i 趟排序需要比较ni次关键字的比较,所以总共需要比较 n1i=1(ni)=n1+n2+...+1=n(n1)2 次。最好的情况下,交换0次,最差的情况是交换 n1 次,所以最终的时间复杂度是 O(n2)

直接插入排序算法

直接插入排序算法的思想是:将一个记录插入到已经排序的有序表中,从而得到一个新的、记录数增加1的有序表。其处理过程是,在排序刚开始的时候,把第一个元素当做是排序的记录,当依次插入后面的元素的时候,就获得其插入的位置,然后形成一个新的有序表。其算法代码如下:

package com.rhwayfun.algorithm.sort;public class InsertSort2 {public void insertSort(int[] a) {int i,j,temp;for(i = 1; i < a.length; i++){if(a[i] < a[i-1]){temp = a[i];for(j = i - 1; j >= 0 && a[j] > temp; j--){a[j+1] = a[j];}a[j+1] = temp;}}for(i = 0;i < a.length; i++){System.out.println(a[i]);}}public static void main(String[] args) {new InsertSort2().insertSort(new int[]{9,1,5,8,3,7,4,6,2});}
}

从空间上分析,直接插入排序算法只需要一个辅助空间。
从时间复杂度上分析,最好的情况是排序的记录本身是有序的,所以时间复杂度是 O(n) ;在最坏的情况,待排序的记录是逆序的,那么此时的时间复杂度是 O(n24) 。所以虽然量级仍然是 n2 ,但是直接插入排序算法的时间复杂度是优于冒泡排序算法和简单选择排序的。

冒泡排序

冒泡排序的基本思想是两两比较相邻记录的关键字,如果反序就交换,直到没有反序的关键字为止。下面是一种实现思路:

package com.rhwayfun.algorithm.sort;public class BubbleSort3 {public void bubbleSort(int[] a){int i,j;for(i = 0; i < a.length; i++){for(j = i + 1; j < a.length; j++){if(a[i] > a[j]){swap(a,i,j);}}}for(i = 0; i < a.length; i++){System.out.println(a[i]);}}private void swap(int[] a, int i, int j) {int temp = a[i];a[i] = a[j];a[j] = temp;}public static void main(String[] args) {new BubbleSort3().bubbleSort(new int[]{9,1,5,8,3,7,4,6,2});}
}

这种版本也是我第一时间写出来的,但是可以发现一个问题,在排好第一个和第二个为止之后,数字3反而被排到了最后面。下面是针对这种情况的改良版代码:

public void bubbleSort2(int[] a){int i,j;for(i = 0; i < a.length; i++){for(j = a.length - 2; j >= i; j--){if(a[j] > a[j + 1]){swap(a,j,j+1);}}}for(i = 0; i < a.length; i++){System.out.println(a[i]);}}

这里的改进主要把第二个for循环由从前往后比较改成由后往前进行比较了,这样的好处是可以把本来较小的元素放在尽可能前一点的位置,这种差异性在数据量较大的时候能够体现出来。以上改良版的冒泡排序使用于基本无序的序列,如果是基本有序的序列再使用上述的算法进行排序就会出现一个问题:那就是可能在进行完前几次的冒泡之后就已经是有序的了,那么后面的冒泡都是多余的。下面得代码是针对这种情况进行的优化:

public void bubbleSort3(int[] a){int i,j;boolean flag = true;for(i = 0; i < a.length && flag; i++){flag = false;for(j = a.length - 2; j >= i; j--){if(a[j] > a[j + 1]){//如果不进行数据交换,说明是有序的swap(a,j,j+1);flag = true;}}}for(i = 0; i < a.length; i++){System.out.println(a[i]);}}

如果在面试中要求写出冒泡排序算法的代码,写最后一种情况就可以了。

下面分析冒泡排序算法的时间复杂度:在最坏的情况就是待排序的记录是逆序的,此时的时间复杂度是 O(n2) ;最好的情况是,排序表本身就是有序的,那么在这种情况下,时间复杂度是 O(n)

这篇关于常用内部排序算法之四:简单选择排序、直接插入排序和冒泡排序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1016577

相关文章

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

(超详细)YOLOV7改进-Soft-NMS(支持多种IoU变种选择)

1.在until/general.py文件最后加上下面代码 2.在general.py里面找到这代码,修改这两个地方 3.之后直接运行即可

React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录 前言Dropdown组件1. 功能分析2. 代码+详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。 Dropdown组件 1. 功能分析 (1)通过position属性,可以控制下拉选项的位置 (2)通过传入width属性, 可以自定义下拉选项的宽度 (3)通过传入classN

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值  目录 介绍 一、基础概念补充: 1.c++字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::stringstream 3. std::atoi, std

回调的简单理解

之前一直不太明白回调的用法,现在简单的理解下 就按这张slidingmenu来说,主界面为Activity界面,而旁边的菜单为fragment界面。1.现在通过主界面的slidingmenu按钮来点开旁边的菜单功能并且选中”区县“选项(到这里就可以理解为A类调用B类里面的c方法)。2.通过触发“区县”的选项使得主界面跳转到“区县”相关的新闻列表界面中(到这里就可以理解为B类调用A类中的d方法

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用。如果你看不懂,请留言。 完整代码: <!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><ti

python实现最简单循环神经网络(RNNs)

Recurrent Neural Networks(RNNs) 的模型: 上图中红色部分是输入向量。文本、单词、数据都是输入,在网络里都以向量的形式进行表示。 绿色部分是隐藏向量。是加工处理过程。 蓝色部分是输出向量。 python代码表示如下: rnn = RNN()y = rnn.step(x) # x为输入向量,y为输出向量 RNNs神经网络由神经元组成, python

数据结构9——排序

一、冒泡排序 冒泡排序(Bubble Sort),顾名思义,就是指越小的元素会经由交换慢慢“浮”到数列的顶端。 算法原理 从左到右,依次比较相邻的元素大小,更大的元素交换到右边;从第一组相邻元素比较到最后一组相邻元素,这一步结束最后一个元素必然是参与比较的元素中最大的元素;按照大的居右原则,重新从左到后比较,前一轮中得到的最后一个元素不参4与比较,得出新一轮的最大元素;按照上述规则,每一轮结

大林 PID 算法

Dahlin PID算法是一种用于控制和调节系统的比例积分延迟算法。以下是一个简单的C语言实现示例: #include <stdio.h>// DALIN PID 结构体定义typedef struct {float SetPoint; // 设定点float Proportion; // 比例float Integral; // 积分float Derivative; // 微分flo