- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565170 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174774
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
动画:面试官问我插入排序和冒泡排序哪个更牛逼?
: E, M6 N3 I& v/ Z* k# }8 S; j; B( G% L! h
, B, ]# c- B) S写在前边
8 Q: G; |/ w, p4 S+ k3 ~5 M" H! }' v) n& @6 ~7 |9 {3 z
" @. T. s! K: M: A- t
排序对于每个开发者来讲,都多多少少知道几个经典的排序算法,比如我们之前以动画形式分享的冒泡排序,也包括今天要分享的插入排序。还有一些其他经典的排序,小鹿整理的共有十种是面试常问到的,冒泡排序、插入排序、希尔排序、选择排序、归并排序、快速排序、堆排序、桶排序、计数排序、基数排序。
* Q9 n: w9 m u y8 X% y" b
5 [, v, H4 n# {7 f2 l' I" n8 e H7 `虽然我们基本知道了这些排序算法,但是在实际项目开发以及面试中往往出乎我们所料。在面试中,经常会被问到各种排序之间的比较;在实际项目中,往往排序的数据不是我们所练习的整数。' \4 k5 r- S9 K4 Q3 E; y! Q* x) d
1 ~$ x( w. t# S2 E! A9 M
那么今天我们来学习一下,插入排序比我们之前讲的冒泡排序有什么区别呢?面试官问我们,我们如何回答完整呢?
3 F; K ]/ `0 ?. L8 l0 w, T7 y- {
- B; X2 J2 t; r# }$ q. }思维导图; N+ s P5 q' R% b
& W: _1 X7 v- @5 z
! P7 a5 T6 Y& L) |: ^
, X _9 `* ^2 p: | Y
" A5 F9 h7 T9 P8 Y18 f5 E2 b3 _, I' u- c2 v
N* Q8 f& x c. u. I- a& V如何分析一个排序算法?4 J/ Z. z6 q, K, b
# m/ h: o1 ` y' A* b) ~
之前写的一篇很详细的文章。
+ p9 [& D3 F, a2 h; i$ n% [4 W' M" L& ?8 n
佩奇学编程 | 复杂度分析原来这么简单7 }9 d! X4 Z& _9 U
/ S; j+ n* _$ E! ]$ U
分析排序算法已经成为我们衡量一个算法优良的重要标准,从以下三个方面入手。
2 H2 F% L) S" r
9 L' p4 i Z) u& r1.1 时间效率* m: b) z; F4 I8 k8 K
; F! G* A' ]6 A: T. }9 U
这里所谓的实践效率就是时间复杂度,相信大家对于时间复杂度并不陌生。
7 f9 I+ @8 M/ }, s6 T3 _8 g, O* T4 ?% k# W
复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系。# H! x, _+ M, e3 Z6 K
: g$ }: ]$ h6 i5 w( I对于时间复杂度的分析,要把最好时间复杂度、最坏时间复杂度、平均时间复杂度分析出来,分别对应了排序算法的最好排序情况、最坏排序情况以及平均排序效率。: C$ I, U& X W3 Y) s7 G. A
+ V4 ^' [. s. d( l+ |* N$ T# g7 e8 S
1.2 空间消耗. D4 X6 j3 T% ]* l* K5 M
, o3 h7 }5 _7 q$ m* c. ?所谓的空间消耗对应的是空间复杂度,在排序算法中需要开辟的额外内存空间是多少。如果空间复杂度为 O(1),此时该排序叫做原地排序。* b9 X w* H7 g0 O+ p4 P8 x
# ^1 `/ k1 l5 q3 Z3 ]! P. t( ^注意:是额外的内存空间,存储排序数据消耗的空间不计。, _$ e; Q. D4 B0 d
0 U2 d7 H1 L' v: q& [
1.3 稳定性& m9 a- }9 P$ o) s; F2 b a3 P, q
6 R) J$ P, X y8 s. {; ?- u算法的稳定性虽然我们之前接触的很少,但是稳定性也是衡量一个排序算法的重要标准。什么是稳定排序呢?比如有一组有重复待排序的数据,排序前后,重复的数据顺序不变,此时该排序为稳定排序。否则,叫做不稳定排序。它在实际应用中非常重要的,今天我们就不多说,以后会慢慢分享到。0 g' T$ K& u# L' B2 w; ^
. b9 q# z( [ O5 z6 l7 b25 c: ?) j: U u" p+ [
6 P6 N2 ~" l- q: @. |& b6 s5 e2 e0 g! c+ r
什么是插入排序?0 B& \: l1 n) Z1 _: t# T
2 {; \. [/ d( R o0 a5 E4 ~
顾名思义,插入排序就是通过插入的方式来排序呗,最经典的就是打斗地主,可以将打乱的扑克牌作为未排序区间,手中已经排好序的作为排序区间。每次我们摸牌的过程,就是从未排序区间,通过插入的方式,插入到已排序区间。那么这个过程就称为插入排序。
0 A+ c/ i8 N0 E* w1 T
7 i3 j% r' Y: W0 v9 y& j% s; e C7 v
8 k) z, {, u7 n/ _* {( X) v
3, P2 g* }; [! c$ y+ g c
$ U; V2 h5 }. ]8 G- Y. c1 M
如何实现插入排序?8 S: H! F+ F% G& t* o
3 ^# ]8 x6 }0 R$ o: L& @
上述插入排序的概念我们已经理解了,那么给你一组数据,如何来进行插入排序呢?
" ~ K3 g( @8 B# k+ u; f: Q& T
, y( }+ m! @. |' [
. U5 p* K- I: h- V0 D' z, ]: O" Q9 I' m. ^; u3 ]+ O3 g
首先我们要将数据划分为两个区间,已排序区间和未排序区间。5 q! \7 K6 L+ B# K0 B' {1 v
% e7 w. g" r, o0 }3 U7 s
) B6 R9 E8 t8 E4 {! q
- W: E- I ]9 G5 e; x) W( @* T
) z1 c4 V$ q. }; |1 J! ?: t8 d+ l/ n. \ e5 F
我们从未排序区间取出数据和已排序区间的数据进行比较,如果小于已排序区间的数据,那我们就交换数据。
& X0 Y' r1 y4 y1 t0 P
3 ?) f0 L \! R. J/ T
! u# ~6 S$ M p( T; T) R
6 w& }1 a: ~: V2 w; w+ u4 u3 f! [0 e# `- Q; e& u( z
7 l) H% Q' \+ g8 S- H9 P如果交换到已排序区间数据不在大于插入的数据,然后将元素插入进去。2 I; }; V0 D( H3 z/ H2 W
& m+ R z6 r% p, Q* ~, t, N1 Y) N. [% k0 P
& A/ T7 i" n9 J9 `* v
3 n: T! w' Q8 Y G. R& d% j: ]# b0 j2 P3 s H1 }
最后我们看一下总的插入排序动画和代码实现。
( U7 V$ Q! j& J" F, G" E% m- i+ O3 G$ T4 g' D- L. _( l, |
% D' Y2 {/ b! g' U; |7 l
- O3 \( p; y* K" O( Y5 W" Z3 _4
; O0 v; r- y8 M* n7 S% k# h3 Y' W: o. c$ X
插入排序的性能
' v# f- }: L& h( {
f6 u7 A2 Q W! @/ ?/ U我们通过上边的对插入排序的拆分讲解和动画以及代码实现,想必面试官让你手写一个插入排序可以轻轻松松写出。但是我们掌握的插入排序知识还往往不够,我们在实际项目中,还要考虑插入排序的性能怎么样?因为才能更好的选择适当排序应用到项目中去。& M' x% L- z. I6 l M; W7 T( B
& U5 W7 P- @' V P9 P
4.1 插入排序的稳定性
, s6 T8 f/ }: X
" F5 c: a$ A+ g g" V再插入排序中,如果存在重复数据的话,前边的元素再插入的过程永远在第二个重复数据的前边,所以插入排序后的重复数据前后顺序不变,所以插入排序是稳定排序算法。. n- J! T' V0 |8 n2 T+ Q- W
1 v' d; q9 E8 z! W) l4.2 插入排序的空间消耗8 e6 F$ A) d4 q4 p$ \3 Q
% ^; F4 e) P3 P% P( c我们可以发现,插入排序的移动方式,需要消耗常量级的额外内存空间存储,也就是代码中的 temp,所以时间复杂度为 O(1),我们上边讲到,空间复杂度为O(1)的是原地排序算法。
9 S9 ^0 t* a2 @; Q% l3 C% y/ Z8 _, w' q7 H
4.3 插入排序的时间效率1 v5 V3 |* `/ e7 B- w* ], N& n+ Y
* }4 Z: U: n- F& `" a
插入排序的最好情况就是不需要搬移任何数据,从头到尾寻找插入数据,每次只比较一次即可,即一组有序数据,所以最好时间复杂度为O(n)。
* D+ a! S. S; V+ B7 C
5 @" V9 V( _3 V2 _如果一组数据正好是倒序输出,那么每次都需要比较移动所有数据,每次移动时 n,n 个数据时间复杂度为O(n2)。
1 v; N- A3 O; L7 q" G) i
; V* Y6 R! g+ S; I/ ^5 C8 l+ [对于插入排序的平均时间复杂度,每次插入都要移动数据,插入 n 次,所以平均时间复杂度为 O(n2)。- }7 E1 z7 P5 S, A- D5 V
( A6 l8 d1 h7 ]) o' }: Q$ z
5' w! p. z! F/ V% r
G2 m( m, k# Z/ }
小结
( n/ B# g8 [/ w2 K5 ?
# |7 T# D/ p8 r# _$ F" w我们学完了今天的插入排序之后,我们回到最初的面试官问题上。插入排序和冒泡排序哪个更好呢?+ N7 c/ ^9 N4 q! _8 B. Y
, B9 k8 l+ u- D$ V$ _3 ~
我们现在元素移动次数上进行分析,如果一组无序的数据通过冒泡排序排好序之后,它的交换次数是这种数据的逆序度;对于插入排序来说也是一样的,移动次数上都是原本数据的逆序度。
! ~) ~2 ]) h8 O3 Y
, W3 s( \; L% G: V元素的移动次数是相同的,那我们接下来看看元素的交换次数。从代码上分析可以明显看出,冒泡排序的一次交换需要三行代码,而插入排序的交换却需要一行,所以总的交换次数冒泡排序大于插入排序。
+ _* f3 i. D3 Q( U! p2 p6 Q% N$ W F1 D, r# O& `8 M
有小伙伴会问,这两行的差别有那么大吗?移动一次,我们可以不计较,如果数据很多,想想下,两者的效率差别很轻易的就比较出来了。) t/ B. M9 l" n- [
7 q! ^$ b. d- N( j2 o! Y2 s7 \虽然冒泡排序的时间复杂度和插入排序的时间复杂度是相同的,但是我们实际使用中还是优先选择插入排序。
0 c: s7 ^7 j* ~1 [$ K. l- }) L3 [3 T+ _
对于插入排序还是可以优化的,对了,没错,就是希尔排序,我们在这不多分开写,后期会继续更新。
3 P! L5 D! e8 J6 K8 ?————————————————7 }# M% N# v% ~/ M1 v9 M5 \) K
版权声明:本文为CSDN博主「胡鹏程的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。: y! V4 |% y0 R$ W: y
原文链接:https://blog.csdn.net/lyshark_lyshark/article/details/1267927083 d- X! W" {4 g1 n1 R) H- ]
% P1 t4 L7 t# \# `' ?; b: p* F' |
0 n, K6 w( C7 ]' m! N, ? |
zan
|