数学建模社区-数学中国

标题: 【基于C的排序算法】插入排序之直接插入排序 [打印本页]

作者: 杨利霞    时间: 2022-9-14 16:31
标题: 【基于C的排序算法】插入排序之直接插入排序
【基于C的排序算法】插入排序之直接插入排序% }# C0 R( E* c2 E3 }& S4 p( c, a- ?2 m

& r  s7 V% H  M前言
& y; @, l% D  _, ]3 ]& G$ D" q) R8 |2 N" s本文基于C语言来分享一波笔者对于排序算法的插入排序中的直接插入排序的学习心得与经验,由于水平有限,纰漏难免,欢迎指正交流。. ^1 [4 `' [; e0 w/ z8 I' i
. W& R, b  u8 v
直接插入排序; I: Y, l  F% ]5 ?2 w# @: U) p9 |5 h
​ 直接插入排序是一种简单的插入排序法,其基本思想是 :5 k# i: |9 k1 U# I

3 z. k' t1 L0 l​ 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为5 k1 K4 U4 e2 j, }2 ]% p  Y
止,得到一个新的有序序列 。* U- U8 q1 W8 f
​ 实际中我们玩扑克牌时,就用了插入排序的思想
4 ]+ `! v5 J/ F0 R4 n; H5 T& H/ v4 S. H" x

7 `9 R/ d: x! i4 r: `1 |; l6 u: ?, J5 |# u
​ 当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array的排序码与6 b: a/ h6 z  G+ i
array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array插入,原来位置上的元素顺序后移。
2 ]% y. M/ t4 k6 P! b/ ^
4 J3 H$ `7 k2 B; {0 F, ]3 k% {1 ?升序排列的示例:3 v% t/ X- H/ R$ w8 m

8 ^1 S# H6 J- ^7 m! ^
0 p4 ~& O5 e( c7 B4 ]* `2 j+ p3 N4 J8 _7 S2 c+ g' O2 R: _
下面以升序排列为例讲解过程:& s1 P. L  D  S

+ C8 D4 R6 \: i$ R% [, \9 ?) o​ 原序列中可以分成两个序列,前面的是已排序的有序序列,用一个下标end标志该序列的尾,初始状态下end是0;后面的是还未排序的序列,用一个tmp变量暂存未排序序列首个元素,实际上是通过tmp = arr[end + 1] 实现的,也就是end指向的下一个元素。为什么要用变量暂存end的下一个元素呢?因为有可能涉及到元素后移,比如说,如果arr[end]要比tmp的值大,根据升序,应该把arr[end]的值后移对吧,那要是直接后移就会覆盖掉arr[end + 1],所以在移动前要先把元素暂存到tmp中。在每一次比较后end要递减一下,向前移动。要是tmp比arr[end]要大该怎么操作呢?这时候就说明找到要插入的位置了,把tmp的值插入到arr[end + 1]即可。
+ M# C0 G. e% a% N
$ t3 h8 \. g0 Q: [3 Q7 B& s% i  i6 l: Y
- ?% a2 t+ A) q1 F) W
​ 可以看出,直接插入排序不可能只有一轮,像前面讲的过程就是一轮的过程,结果就是把未排序序列的首元素插入到了已排序序列中并保持原来的顺序,正如把刚摸到的一张牌按顺序插入到你的手牌中。实际上,一开始序列是全部未排序的,我们可以把第一个元素作为已排序元素,也就是说已排序序列一开始只有一个元素,end值就为0,后面的元素就全部都是未排序序列的了。/ U( f( b2 K3 R7 F+ X

0 P! U, M2 w( m9 x
# ]* d2 P1 }$ r
$ C  Y# Q: _9 i1 s! ^: u​ 也就是说要将整个原序列排好序的话要让已排序序列拓展至整个原序列,也就是end要不断增加到size - 1(size是数组元素个数),end值为size - 1时结束,所以还要外套一个循环。
# y5 \2 L; s" v  A' I) L- F+ N  d5 H& [2 g' N- l
void InsertSort(int* arr, int sz)
2 K5 T2 z! i1 |1 k7 P2 B0 }4 R{
3 a4 p; [% |& |3 h7 y# ]7 O/ z        assert(arr);
* ^: j5 u' b0 h9 U* D& X! K9 f( a* {/ W. K0 y# S
        for (int i = 0; i < sz - 1; ++i)//i的取值就是end的取值,end最多取到sz-2算有效,当它取到sz-1时就该结束循环了
- O0 {6 Z; I3 J& y1 _: R9 F        {) L' v2 p, K+ {& m
                //单轮排序
+ p2 F2 D5 f- @  _) b+ ]0 V% B                int end = i;
; p; X* y  @3 K. m7 p                int tmp = arr[end + 1];, ~2 k0 h* `2 u  ]' A0 U
                while (end >= 0)//为什么要>=0呢?可不可以>0?3 n& y* s6 X+ `: g; w! \
                {
8 W: S7 `6 L# i# H" y                        //要排升序               
3 f6 _' ]. _' U                        if (tmp < arr[end])- t1 z* X7 N9 s
                        {
- F, g7 Q7 c$ U/ s                                arr[end + 1] = arr[end];$ c; W* ]5 ~  M* n3 q5 w( I
                                --end;$ j* ~1 D. V. B) h: E, L
                        }7 t; ^: B- e% w' d$ Q. m
                        else
4 R! }" K+ O. R6 p                        {                               
( y+ Y: r# \: R+ {7 @! ]1 b                                break;; I0 w3 z! m% R" i
                        }                ) A: Y1 g( ~+ b% D
                }% N, P) ]1 H* |4 I# L' m; v
                arr[end + 1] = tmp;
' F8 g' u; [0 W; e3 W. c        }) X6 ]/ \( C0 @- p
}
9 O: O0 R6 v5 Y0 A5 [# P6 G7 d2 y2 R% A+ y; E
1) F3 o; O- x, ?0 y  b
2
$ l2 G: c4 p, e/ {3( H1 n; P$ T/ H" @7 o+ L) h
4
7 ~0 v, n# q% p1 n8 v4 s5
  b. n0 _1 M3 I7 Z+ ]60 y+ H3 C: x: W4 L
7
% z* d/ r9 F' A1 x  t, K8
, W/ ?: O/ R$ ^" A- ~7 ~9
& Q; j+ N& `4 K! p- L10
* i1 t5 U% r  ^/ n113 E  l( N& E( U- ?  Z2 e
12  y% S5 |; p' }4 y
13$ n, |& o! \7 \8 G7 X
14
8 O( }# L5 u8 a3 t1 P' N15# I$ q( O6 n  k6 E. O. N: S
16' ~2 [$ N" n/ s/ U
17# D! F6 F4 J: O
18
! M- a. n* y) y4 q# e19
/ W( ^# _" o0 ^- k( E20  r% O9 j) H2 S8 \/ I5 W
21
5 i" F! N7 @5 S  K, M  n# T225 O! @( O# k* b
23
4 k# I9 O- l4 P: {9 _# G. N, W/ p4 N24
7 x3 D2 e8 A8 ?25
) f* V  C" U7 E2 {. N) Q3 m; M/ _3 x' d​ end可以为0,因为有可能tmp的值比arr[0]还小,那就得让原来的arr[0]后移,把tmp放到arr[0]的位置。
( W+ a9 g; e6 z* {2 O+ ~$ b7 s6 u! ^5 U& Y/ {( c: i& f
' [% R# r, A* Q- H0 t! a$ z
$ A2 x1 N5 Q3 A& W7 P  M
直接插入排序的特性总结:
0 N6 n) k$ X1 l. H
& A* Z) E! i7 _# I& S* n* K4 O元素集合越接近有序,直接插入排序算法的时间效率越高,最好情况下(有序)时间复杂度为O(n)
& P0 @0 m; u, D0 l2 s时间复杂度:O(n2)
% i8 H% m, |8 }2 i6 `4 d6 a空间复杂度:O(1),它是一种稳定的排序算法
9 Z; \3 X' e( J# @7 m. h+ ^' n' f稳定性:稳定4 L% T" I# L  T- G0 A8 O; k4 {
感谢观看,你的支持就是对我最大的鼓励~. i; ]: G4 S* ?& w/ w! F/ ]
————————————————
5 n/ d$ j' l9 ^( a, x# N版权声明:本文为CSDN博主「桦秋静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。" r  [: r. C) n, j' }8 ?0 u
原文链接:https://blog.csdn.net/weixin_61561736/article/details/126796593
" V1 r$ F. Z, H/ x6 e8 m$ O* H, x
+ E# m3 [& j5 d8 M& r# K& C3 K
, z- L8 ]0 `- ]& T0 p% f* S




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5