数据结构和算法(Golang实现)(21)排序算法-插入排序
插入排序
插入排序,一般我们指的是简单插入排序,也可以叫直接插入排序。就是说,每次把一个数插到已经排好序的数列里面形成新的排好序的数列,以此反复。
插入排序属于插入类排序算法。
除了我以外,有些人打扑克时习惯从第二张牌开始,和第一张牌比较,第二张牌如果比第一张牌小那么插入到第一张牌前面,这样前两张牌都排好序了,接着从第三张牌开始,将它插入到已排好序的前两张牌里,形成三张排好序的牌,后面第四张牌继续插入到前面已排好序的三张牌里,直至排序完。
一、算法介绍
举个简单例子,插入排序一个 4 个元素的数列:4 2 9 1
:
[]表示排好序
第一轮: [4] 2 9 1 拿待排序的第二个数 2,插入到排好序的数列 [4]
与排好序的数列 [4] 比较
第一轮进行中:2 比 4 小,插入到 4 前
第二轮: [2 4] 9 1 拿待排序的第三个数 9,插入到排好序的数列 [2 4]
与排好序的数列 [2 4] 比较
第二轮进行中: 9 比 4 大,不变化
第三轮: [2 4 9] 1 拿待排序的第四个数 1,插入到排好序的数列 [2 4 9]
与排好序的数列 [2 4 9] 比较
第三轮进行中: 1 比 9 小,插入到 9 前
第三轮进行中: 1 比 4 小,插入到 4 前
第三轮进行中: 1 比 2 小,插入到 2 前
结果: [1 2 4 9]
最好情况下,对一个已经排好序的数列进行插入排序,那么需要迭代N-1
轮,并且因为每轮第一次比较,待排序的数就比它左边的数大,那么这一轮就结束了,不需要再比较了,也不需要交换,这样时间复杂度为:O(n)
。
最坏情况下,每一轮比较,待排序的数都比左边排好序的所有数小,那么需要交换N-1
次,第一轮需要比较和交换一次,第二轮需要比较和交换两次,第三轮要三次,第四轮要四次,这样次数是:1 + 2 + 3 + 4 + ... + N-1
,时间复杂度和冒泡排序、选择排序一样,都是:O(n^2)
。
因为是从右到左,将一个个未排序的数,插入到左边已排好序的队列中,所以插入排序,相同的数在排序后顺序不会变化,这个排序算法是稳定的。
二、算法实现
package main
import "fmt"
func InsertSort(list []int) {
n := len(list)
// 进行 N-1 轮迭代
for i := 1; i <= n-1; i++ {
deal := list[i] // 待排序的数
j := i - 1 // 待排序的数左边的第一个数的位置
// 如果第一次比较,比左边的已排好序的第一个数小,那么进入处理
if deal < list[j] {
// 一直往左边找,比待排序大的数都往后挪,腾空位给待排序插入
for ; j >= 0 && deal < list[j]; j-- {
list[j+1] = list[j] // 某数后移,给待排序留空位
}
list[j+1] = deal // 结束了,待排序的数插入空位
}
}
}
func main() {
list := []int{5}
InsertSort(list)
fmt.Println(list)
list1 := []int{5, 9}
InsertSort(list1)
fmt.Println(list1)
list2 := []int{5, 9, 1, 6, 8, 14, 6, 49, 25, 4, 6, 3}
InsertSort(list2)
fmt.Println(list2)
}
输出:
[5]
[5 9]
[1 3 4 5 6 6 6 8 9 14 25 49]
数组规模n
较小的大多数情况下,我们可以使用插入排序,它比冒泡排序,选择排序都快,甚至比任何的排序算法都快。
数列中的有序性越高,插入排序的性能越高,因为待排序数组有序性越高,插入排序比较的次数越少。
大家都很少使用冒泡、直接选择,直接插入排序算法,因为在有大量元素的无序数列下,这些算法的效率都很低。
系列文章入口
我是陈星星,欢迎阅读我亲自写的 数据结构和算法(Golang实现),文章首发于 阅读更友好的GitBook。
- 数据结构和算法(Golang实现)(1)简单入门Golang-前言
- 数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数
- 数据结构和算法(Golang实现)(3)简单入门Golang-流程控制语句
- 数据结构和算法(Golang实现)(4)简单入门Golang-结构体和方法
- 数据结构和算法(Golang实现)(5)简单入门Golang-接口
- 数据结构和算法(Golang实现)(6)简单入门Golang-并发、协程和信道
- 数据结构和算法(Golang实现)(7)简单入门Golang-标准库
- 数据结构和算法(Golang实现)(8.1)基础知识-前言
- 数据结构和算法(Golang实现)(8.2)基础知识-分治法和递归
- 数据结构和算法(Golang实现)(9)基础知识-算法复杂度及渐进符号
- 数据结构和算法(Golang实现)(10)基础知识-算法复杂度主方法
- 数据结构和算法(Golang实现)(11)常见数据结构-前言
- 数据结构和算法(Golang实现)(12)常见数据结构-链表
- 数据结构和算法(Golang实现)(13)常见数据结构-可变长数组
- 数据结构和算法(Golang实现)(14)常见数据结构-栈和队列
- 数据结构和算法(Golang实现)(15)常见数据结构-列表
- 数据结构和算法(Golang实现)(16)常见数据结构-字典
- 数据结构和算法(Golang实现)(17)常见数据结构-树
- 数据结构和算法(Golang实现)(18)排序算法-前言
- 数据结构和算法(Golang实现)(19)排序算法-冒泡排序
- 数据结构和算法(Golang实现)(20)排序算法-选择排序
- 数据结构和算法(Golang实现)(21)排序算法-插入排序
- 数据结构和算法(Golang实现)(22)排序算法-希尔排序
- 数据结构和算法(Golang实现)(23)排序算法-归并排序
- 数据结构和算法(Golang实现)(24)排序算法-优先队列及堆排序
- 数据结构和算法(Golang实现)(25)排序算法-快速排序
- 数据结构和算法(Golang实现)(26)查找算法-哈希表
- 数据结构和算法(Golang实现)(27)查找算法-二叉查找树
- 数据结构和算法(Golang实现)(28)查找算法-AVL树
- 数据结构和算法(Golang实现)(29)查找算法-2-3树和左倾红黑树
- 数据结构和算法(Golang实现)(30)查找算法-2-3-4树和普通红黑树
数据结构和算法(Golang实现)(21)排序算法-插入排序的更多相关文章
- 数据结构和算法(Golang实现)(25)排序算法-快速排序
快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...
- 数据结构和算法(Golang实现)(18)排序算法-前言
排序算法 人类的发展中,我们学会了计数,比如知道小明今天打猎的兔子的数量是多少.另外一方面,我们也需要判断,今天哪个人打猎打得多,我们需要比较. 所以,排序这个很自然的需求就出来了.比如小明打了5只兔 ...
- 数据结构和算法(Golang实现)(19)排序算法-冒泡排序
冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...
- 数据结构和算法(Golang实现)(20)排序算法-选择排序
选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...
- 数据结构和算法(Golang实现)(22)排序算法-希尔排序
希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...
- 数据结构和算法(Golang实现)(23)排序算法-归并排序
归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...
- 数据结构和算法(Golang实现)(24)排序算法-优先队列及堆排序
优先队列及堆排序 堆排序(Heap Sort)由威尔士-加拿大计算机科学家J. W. J. Williams在1964年发明,它利用了二叉堆(A binary heap)的性质实现了排序,并证明了二叉 ...
- 数据结构和算法(Golang实现)(26)查找算法-哈希表
哈希表:散列查找 一.线性查找 我们要通过一个键key来查找相应的值value.有一种最简单的方式,就是将键值对存放在链表里,然后遍历链表来查找是否存在key,存在则更新键对应的值,不存在则将键值对链 ...
- 数据结构和算法(Golang实现)(27)查找算法-二叉查找树
二叉查找树 二叉查找树,又叫二叉排序树,二叉搜索树,是一种有特定规则的二叉树,定义如下: 它是一颗二叉树,或者是空树. 左子树所有节点的值都小于它的根节点,右子树所有节点的值都大于它的根节点. 左右子 ...
随机推荐
- 【开发工具 docker】值得学习的应用容器引擎docker安装
概述: Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何 ...
- Redis 的键命令、HyperLogLog 命令、脚本命令、连接命令、服务器命令
Redis 的键命令.HyperLogLog 命令.脚本命令.连接命令.服务器命令 Redis 的键命令 Redis 的键命令主要用于管理 Redis 的键,如删除键.查询键.修改键及设置某个键等. ...
- Python-时间戳、元组时间的格式、自定义时间格式之间的转换
一.时间戳.元组时间的格式.自定义时间格式之间的转换 1.下面是三者之间的转换关系: 2.代码如下: import time import datetime print(time.time()) #获 ...
- Python之操作文件和目录
Python内置的os模块可以直接调用操作系统提供的接口函数. # coding=utf-8 # 在指定目录以及指定目录的所有子目录下查找文件名包含指定字符串的文件,并打印出相对路径 import o ...
- demo26-路径
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem
链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...
- Mysql常用sql语句(二)- 操作数据表
21篇测试必备的Mysql常用sql语句,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1683347.html ...
- python接口调用把执行结果追加到测试用例中
python操作excel的三个工具包如下,注意,只能操作.xls,不能操作.xlsx. xlrd: 对excel进行读相关操作 xlwt: 对excel进行写相关操作 xlutils: 对excel ...
- ORA-01017的一种情况:sysdba可以登录,normal不可登录
在arcCatalog中创建完sde数据库之后,用PLSQL登录提示只能用SYSDBA登录. 用户名:sde 密码:123456 数据库:ORCLZLL 连接为:Normal 点击登录 ...
- linux 中的页缓存和文件 IO
本文所述是针对 linux 引入了虚拟内存管理机制以后所涉及的知识点.linux 中页缓存的本质就是对于磁盘中的部分数据在内存中保留一定的副本,使得应用程序能够快速的读取到磁盘中相应的数据,并实现不同 ...