找回密码
 注册
关于网站域名变更的通知
查看: 733|回复: 0
打印 上一主题 下一主题

玩转C语言链表,单链表/双向链表的建立/遍历/插入/删除

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-9-2 17:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
  最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层)、Service(业务逻辑层)、Persistence(持久化层)的分离和耦合,一种面向过程的MVC的感觉。- j- A; ]( s1 m4 u
  而这一切的基础就在于对链表的创建、删除、输出、写入文件、从文件读出......
: m+ ^" P' p; ^1 ?  本篇文章在于巩固链表的基础知识(整理自《C语言程序设计教程--人民邮电出版社》第十章——指针与链表),只对链表的概念及增删改查作出探讨,欢迎指教。; R" m$ f- {: w: |+ c) p- F
  一、链表结构和静态/动态链表
0 p) Y- J- n, \6 h* ^8 T! B, V$ M  二、单链表的建立与遍历
" A- z. B2 [, ]! I0 a' r6 z  三、单链表的插入与删除! @$ O9 i# K$ T8 }) Z
  四、双向链表的概念1 W, V+ [" I% \& [2 u' V
  五、双向链表的建立与遍历% q% M% E7 [$ e
  六、双向链表的元素查找7 r5 q" J+ O! @: V$ z/ R
  七、循环链表的概念
- ]$ y) l1 H8 r% o9 `6 @6 p" M  八、合并两个链表的实例* C, x! h5 _  H! L1 l
  九、链表实战( n0 S) y' ]: F5 z2 l0 r
  拓展思维、拉到最后去看看 (•̀ᴗ•́)و ̑̑
1 h& X( Y+ G6 l9 @1 @  一、链表结构和静态/动态链表
4 m' F5 j. _1 ~( I, |  链表是一种常见的数据结构——与数组不同的是:, U. g0 G! p: D" q2 n+ g8 U/ S
  1.数组首先需要在定义时声明数组大小,如果像这个数组中加入的元素个数超过了数组的长度时,便不能正确保存所有内容;链表可以根据大小需要进行拓展。
, S- i% V, R$ U+ f  2.其次数组是同一数据类型的元素集合,在内存中是按一定顺序连续排列存放的;链表常用malloc等函数动态随机分配空间,用指针相连。0 ?- G1 ^; `% l0 s% ?* s* e
  链表结构示意图如下所示:) H/ Z6 L  S1 F5 n9 v: y
  

4 M: r1 N! o# f: ^4 t# q  Y  B  在链表中,每一个元素包含两个部分;数据部分和指针部分。数据部分用来存放元素所包含的数据,指针部分用来指向下一个元素。最后一个元素的指针指向NULL,表示指向的地址为空。整体用结构体来定义,指针部分定义为指向本结构体类型的指针类型。# T, r. |, @8 B- N- ~" k
  静态链表需要数组来实现,即把线性表的元素存放在数组中。数组单元存放链表结点,结点的链域指向下一个元素的位置,即下一个元素所在数组单元的下标。这些元素可能在物理上是连续存放的,也有可能是不连续的,它们之间通过逻辑关系来连接——这就要涉及到数组长度定义的问题,实现无法预知定义多大的数组,动态链表随即出现。
3 w( d9 S9 G0 u, i' p4 j( m% J  动态链表指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点的数据,并建立起前后相连的关系。4 b" Q1 j& j/ }" E
  二、单链表的建立与遍历
3 J: n  n! k7 W. Y  单链表中,每个结点只有一个指针,所有结点都是单线联系,除了末为结点指针为空外,每个结点的指针都指向下一个结点,一环一环形成一条线性链。
. a6 A, {& M$ a) V  链表的创建过程:  P7 c/ F; t6 M
  
% v* K/ P; ^+ X; ^  L
  接下来在源码中建立并遍历输出一个单链表。* Y4 b7 w, L" ^0 I* f+ e
) c5 u* C: \1 M2 }& G4 H

1 ?1 B9 N, G. a6 |+ I7 L6 u# ]/ b) S
. r5 ?0 }) l! B  l
  1.   #include
    6 o( k# U! T. l0 ~' D: I
  2. ) {2 j4 u# b  V) c4 o  e
  3.   #include
    - R4 k) Z! c& v# C" J* b

  4. . X! g# R1 J/ p6 D9 Q0 H+ C$ g7 z
  5.   #include$ B* w# y6 E$ V  j

  6. & l3 C2 A% y3 W; s! Y& a3 x
  7.   /*单向链表*/
    ' A. Z# }# F$ B7 U
  8. 5 f% ^: r* I, x* W: s: I
  9.   struct Student/*建立学生信息结构体模型*/# [6 z8 z; ^4 m5 e+ E: \( k/ j

  10. % |) v2 ?" h# ]3 f
  11.   {
      Z* H9 _. c7 X
  12. ( G% C% V0 t+ B* I) N2 m
  13.   char cName[20];/*学生姓名*/' m; }8 T0 h* V4 P, s6 Z
  14. 6 D1 J& H, P. r* z  k5 ?& q5 j; P% o
  15.   int iNumber;/*学生学号*/
    * Z7 s$ s4 y) k

  16. ( o: T5 {; N5 P, F6 ^( X
  17.   struct student *next;/*指向本结构体类型的指针类型*/
      m9 U9 v+ |( z$ z

  18. $ e" o) E. a8 C  F' q' i
  19.   };1 {& v# x' e( b. }* M
  20. 0 e2 [( c# X- [5 q
  21.   int iCount;/*全局变量表示链表长度*/
    3 v: Z5 s# ^5 s% U

  22. , ~+ C3 J+ Q4 c* }" p, U6 V
  23.   struct Student *Create();/*创建链表函数声明*/  l* j& Z+ B0 g1 U2 c) E
  24. ! [, Y$ o; O1 R9 U
  25.   void print(struct Student *);/*遍历输出链表函数声明*/8 s8 I, |' j) q$ W6 m( V2 H. u" T

  26. 7 K( B* E( M, ^, s7 |2 {! i+ {
  27.   int main()
    " K4 h, t2 C; E0 p- s/ _  q* Z

  28. 8 x5 L! U7 M3 V$ N: {: z
  29.   {0 j; t( s/ ^* ~3 T2 a% ?

  30. 4 B! C" g3 q& J4 Z! [9 _2 x
  31.   int insert_n=2;/*定义并初始化要插入的结点号*/
    : L# L6 G" @/ a# l, m+ A. F
  32. ' i2 a* p1 a3 m& n+ ~
  33.   int delete_n=2;/*定义并初始化要删除的结点号*/
    ( O! O) r2 N; v4 {" g/ z3 y* A' X. Q3 S

  34. 9 _4 |, ~7 v0 J
  35.   struct Student *pHead;/*声明一个指向学生信息结构体的指针作pHead为头结点传递*/
    9 q. E0 z7 n9 o$ q/ M( {% W! C

  36. 3 f. S; a1 [+ ^
  37.   pHead=Create();/*创建链表,返回链表的头指针给pHead*/
    " V# g4 l: }) E- i: O7 Q
  38. 6 K) ?* K( |1 w! |# K
  39.   print(pHead);/*将指针pHead传入输出函数遍历输出*/2 m+ x% }8 O2 p  [) T
  40. 0 F5 A) |! j* g3 @0 V
  41.   return 0;: y" F4 r6 ~! D% H/ N9 b

  42. $ w8 y, F1 {. |! P* U! r+ q
  43.   }$ U3 L! u6 L+ J

  44. % B/ ^9 o5 C% q4 G2 r5 ]
  45.   struct Student *Create()
    ; \! a# `6 k% k! O

  46. 8 D4 |9 T0 o3 }5 J. b; d9 X
  47.   {, [. C4 R8 ^+ G% d; w$ n

  48. 1 Z3 H7 A1 E% W$ r0 [  R
  49.   struct Student *pHead=NULL;/*初始化链表,头指针为空*/
    ! p+ t  h5 u% x( J! p0 G' q
  50. " Y3 O9 s0 C: R! [% c1 b( @% W
  51.   struct Student *pEnd,*pNew;
    9 \+ I% N+ k/ d9 Z" e0 K

  52. / Q7 @5 }" p/ e% |9 R  L
  53.   iCount=0;/*初始化链表长度*/
    / G4 {: l' {7 Y/ g
  54. 1 j4 f) D8 l& R
  55.   pEnd=pNew=(struct Student *)malloc(sizeof(struct Student));/*动态开辟一个学生信息结构体类型大小的空间,使得pEnd和pNew同时指向该结构体空间*/# ~" K9 H. h. H' u0 X+ E

  56. % K! y& H7 Q$ Y+ g) Q
  57.   scanf("%s",pNew->cName);/*从输入流获取第一个学生姓名*/9 P$ v7 {1 A! t
  58. ( T9 M) q% ]* n
  59.   scanf("%d",&pNew->iNumber);/*从输入流获取第一个学生学号*/
    / F8 e& A% i7 J) b

  60. 2 X) `$ p/ {/ B
  61.   while(pNew->iNumber!=0)/*设定循环结束条件——学号不为0时*/6 t- k5 B: K" M$ ]5 B' K7 W
  62. 4 `* |$ K$ U) V: i9 u
  63.   {  X4 B! o1 P; n4 H  B( U1 a/ D# i

  64. 8 X: {$ j/ \6 {
  65.   iCount++;/*链表长度+1,即学生信息个数+1*/
    7 e1 J. u! D  Y0 V( t* V2 G. Q
  66. ; g8 r# w1 U5 j# s$ f
  67.   if(iCount==1)/*如果链表长度刚刚加为1,执行*/
    : ?8 T7 n: S- |$ C, l
  68. ( b# I5 ]0 v% e& l% i! b/ }
  69.   {0 n1 r( b5 h, S' N# N. q

  70. 6 a) k/ @, v% V, y" k5 [( u0 C7 I
  71.   pNew->next=pHead;/*使指针指向为空*/
    9 P) f5 J! T! T
  72. 9 f8 A, @$ f7 J  q# p1 N  N
  73.   pEnd=pNew;/*跟踪新加入的结点*/
    + k8 F. u- }2 M$ k2 ]

  74. # ]$ |$ s& T: `- a4 u
  75.   pHead=pNew;/*头结点指向首结点*/
    5 l  R7 o* ~& A* Z' n

  76. 9 Z4 b; A4 s# C9 G2 L0 @
  77.   }
    $ e2 j9 w" t! h
  78. + R1 d  j" k) H* I% G/ {
  79.   else/*如果链表已经建立,长度大于等于2时,执行*/
    % c0 F7 z( M8 Q  }& E1 d
  80. ' e; I5 r/ ~* P! C
  81.   {) @+ ?& {$ b5 E  {, m/ L
  82. . c0 L. k0 M$ B/ i2 F% w
  83.   pNew->next=NULL;/*新结点的指针为空*/
    : L! `# m: ^6 o, A, h
  84.   N$ m. f: E  p
  85.   pEnd->next=pNew;/*原来的结点指向新结点*/
    4 j4 G* G1 y0 Q5 |; J
  86. 7 r; c& N3 A" b& c  Q  ~1 a
  87.   pEnd=pNew;/*pEnd指向新结点*/
    9 |9 t& q  o% D

  88. ! ]" {' m; m8 R
  89.   }) d4 |) j0 E" Y0 L7 F

  90. 2 ]1 q- C: Z6 y, X7 ]% I9 D
  91.   pNew=(struct Student *)malloc(sizeof(struct Student));/*再次分配结点的内存空间*/
    - g. W! O  y' ?) B

  92. 7 G8 C: r+ z, y1 T
  93.   scanf("%s",pNew->cName);/*从输入流获取第一个学生姓名*/5 U% P; B4 w7 a! K" s( ~8 U0 F

  94. - d. Q7 `2 [1 Q, I% J
  95.   scanf("%d",&pNew->iNumber);/*从输入流获取第一个学生学号*/; L% V% G; [6 n# D
  96. * l3 y( A% D# R+ X5 A3 p
  97.   }
    5 n  W- f& m9 ~$ J: d* Z9 K& H
  98. 7 u) I8 |( Z. T2 r8 `
  99.   free(pNew);/*释放结点空间*/5 H/ @( Y' H/ W" r* Q, N" N
  100. 6 @  e! x" j4 f% N- F5 l
  101.   return pHead;/*返回创建出的头指针*/
    , ~5 R/ @" T+ j5 D6 J

  102. $ ^% ~2 [( E2 F; W  Z
  103.   }( |  g( w* |* V' z0 v7 Z

  104. 0 E) a% |  t) h% H* y* R# j
  105.   void print(struct Student *pHead)* ]0 u- W0 n7 D8 |9 Y; W
  106. 1 q: _6 v4 c/ B# w/ G
  107.   {
    7 Q5 ^1 I/ p4 h% S
  108. 3 a/ _8 g; E. \$ E4 _' v) e5 R
  109.   struct Student *pTemp;/*定义指向一个学生信息结构体类型的临时指针*/
    " y2 _, U" S  Q& [
  110.   ~' w  {$ I8 a* S* o, H. k( ?
  111.   int iIndex=1;/*定义并出事哈变量iIndex,用来标识第几个学生(信息)*/
    # @& ]1 S( w; v5 D9 x, s! `) W' X
  112. 3 c% j4 ^9 F( a+ t, @# S/ I
  113.   printf("总共%d个学生(信息):\n",iCount);
    . T9 T0 c) n9 q* S4 d9 J8 D

  114. ( R$ @; L+ |" |2 J: y
  115.   pTemp=pHead;/*指针得到首结点的地址*/$ h, I) W' ?5 l9 O& U- V
  116. $ x5 e3 x  d8 g
  117.   while(pTemp!=NULL)/*当临时指针不指向NULL时*/
    9 x- k+ h4 O* p6 F! B* A4 k

  118. 4 U" B0 }- @1 a- M9 r
  119.   {
    ' N+ f9 J" T. c+ C! I9 F
  120. 1 [( Q+ @) h9 l+ l( y( ]
  121.   printf("第%d个学生信息:\n",iIndex);
    4 k. `: `& B/ V) l' S# G
  122. 0 T3 C: `; [3 g, z* Y
  123.   printf("姓名:%s",pTemp->cName); /*输出姓名*/
    2 a; u  ]- Y0 I$ \, g
  124. ) X, r0 g  i( T4 h
  125.   printf("学号:%d",pTemp->iNumber);/*输出学号*/3 t# }( z4 }3 _# D1 C# t

  126. 7 X' A+ s4 u9 c' i! f
  127.   pTemp=pTemp->next;/*移动临时指针到下一个结点*/6 _* g' X6 e6 U' b2 I

  128. ) B5 |% l5 M7 G$ y
  129.   iIndex++;/*进行自加运算*/
    8 D0 _) C. S. M* D) M
  130. 6 E( L& a6 b) X# B5 _8 [1 {
  131.   }& o, f+ y! D0 a( v7 v  h
  132. ( z. @8 [1 v" W9 D" @/ j
  133.   }
复制代码

- N& P9 c' H  S0 X. e. p- H; ?8 o
, o/ n3 q. e" R/ b

" o- s9 ~8 z& k. w% B3 }& C5 \  三、单链表的插入与删除
8 Z3 _) g! b% L+ p! ?& h  在本实例中,插入时根据传递来的学号,插入到其后。
& {, K9 m8 F0 Q7 g  删除时根据其所在链表的位置,删除并释放该空间。0 {0 M7 ~/ \  t
  主函数增加如下:
: P$ j' w# {5 |* S5 k# P
/ }) B3 B" t8 v6 K5 t0 f9 l$ g8 \) p% k/ {# T% [! r  g$ e

; O( Q" I! ^  z2 P2 [
  1.   int main()
    , V. E7 I$ J% M4 C! t! g" H4 V
  2. ) L+ x0 _" A2 G2 |  f% }2 c( T
  3.   {
    : {! J, B& Q, F+ M1 e; S* g  k

  4. 6 p' u# v: W8 K& s
  5.   int insert_n=2;/*定义并初始化要插入的结点号*/
    ) u" Z& U0 K) z
  6. ( n$ c" C& d' `: M4 B" [( Z- d) X; V' K
  7.   int delete_n=2;/*定义并初始化要删除的结点号*/! C0 K  K4 Y, q* H* B
  8. 7 G, C+ M0 I! k3 |! p" x7 h
  9.   struct Student *pHead;/*声明一个指向学生信息结构体的指针作pHead为头结点传递*/4 [$ ?$ Q0 p& k  j4 t3 F9 \1 J
  10. . ^+ E- |* R# h* m( x
  11.   pHead=Create();/*创建链表,返回链表的头指针给pHead*/
    " E5 E1 Q; C( k+ z

  12. 4 l9 ?- a8 v0 S
  13.   pHead=Insert(pHead,insert_n);/*将指针pHead和要插入的结点数传递给插入函数*/2 w4 O0 Q5 i! ~# `: j! x  k9 S; S) L

  14. + @' E8 a% L+ W3 z$ g4 E' ?
  15.   print(pHead);/*将指针pHead传入输出函数遍历输出*/# d. f" M' G% Z  ~' s

  16. - u  \6 B. E6 W5 |. w- [; n( M( i& }
  17.   Delete(pHead,delete_n);/*将指针pHead和要删除的结点数传递给删除函数*/6 ~8 m# t5 h2 l' u( Z

  18. " X' z* J5 a+ U- r0 ~8 u! u) T
  19.   print(pHead);/*将指针pHead传入输出函数遍历输出*/8 q/ {; l% q" {  c8 u- M# B+ w
  20. 3 |0 w6 s- h) q6 O
  21.   return 0;
    $ E* L; ?0 o. u: O! j

  22. , Y8 k7 }7 h) O2 I) r, e
  23.   }
复制代码

  z% z) q4 n; B. ]. P
+ P& w; u6 }8 D5 h5 h* C2 z% o7 o& x% j
4 {8 ]- x; N! P4 P6 c( {
  插入函数:8 Z+ x4 D. A0 x" }- H0 W8 K3 s
5 r' N, ^. d8 _* D2 p" s* x

5 Y9 Y# i, O/ F! L1 a
6 Q+ ]7 T8 R* K3 h
  1.   struct Student *Insert(struct Student *pHead,int number)" s$ j% X3 l- g  m

  2. 8 ?* ?* N  ~& c
  3.   {1 c$ T& z0 m- f2 t& ^6 X( D

  4.   S8 _/ @# c' B, N' _
  5.   struct Student *p=pHead,*pNew;/*定义pNew指向新分配的空间*/
    ) K/ U3 o0 }$ h
  6. 6 D6 n# c2 I+ Y' e# h8 o. d* k
  7.   while(p&&p->iNumber!=number)0 c5 t0 X7 }; P( ]* D
  8. & c0 @# q6 J; W2 q& }7 f
  9.   p=p->next;/*使临时结点跟踪到要插入的位置(该实例必须存在学号为number的信息,插入其后,否则出错)*/
    ' a# P* x7 M6 \
  10. " R- I, L. I' Z5 Q! z. h
  11.   printf("姓名和学号:\n");
    - E- h! p, m: w2 y# [5 _% O+ x- k

  12. # U7 G+ s; a8 j9 |% K
  13.   /*分配内存空间,返回该内存空间的地址*/. R. V8 N6 }' `$ N

  14. : R$ k* o% R- F& S* p0 c
  15.   pNew=(struct Student *)malloc(sizeof(struct Student));6 O" F0 s: g' r& }1 N

  16. # O5 F1 ^( S9 p- ^' U
  17.   scanf("%s",pNew->cName);  L# x/ y( d% s

  18. 2 {0 n( p* F  R7 {% o/ a) |# @$ K
  19.   scanf("%d",&pNew->iNumber);/ a3 D/ Z) T/ F$ w! g5 U

  20. 3 ^0 @1 i7 }2 U1 \6 f# _+ t
  21.   pNew->next=p->next;/*新结点指针指向原来的结点*/" K& {" n9 s4 h' s' ^  ]7 C: @

  22. 6 B! ?7 T* {! \4 l8 G$ u! Q
  23.   p->next=pNew;/*头指针指向新结点*/, U4 ?2 d9 g2 ~- {- B0 A
  24. " w8 e, k; V4 M
  25.   iCount++;/*增加链表结点数量*/( p% K+ U4 m. e

  26. 2 B& u7 b& I% ]* P
  27.   return pHead;/*返回头指针*/
    - o5 A; E# p& n

  28. ) s/ F0 M7 J5 k7 {+ x# q
  29.   }
复制代码

/ v& @# d6 {1 _1 g' i. v, a' V
; L, J; J0 W& M+ m" T
! c; |( J6 n/ w5 ]3 R* i$ N
, C: K% Q7 b- p6 x9 t; H  删除函数:
- i4 N  |* }8 t9 I4 o" w6 Q4 t# ~

8 A& O5 }' l# i" F+ F9 w4 w: O3 T" H8 u; T& I: S5 _
. }6 ~! S4 \/ B2 M6 N
  1.  void Delete(struct Student *pHead,int number)6 y# z; t! w, r) {9 c0 a

  2. - o3 w; k- n' `- W2 n5 y8 s
  3.   {; }: j, |# `" @
  4. 3 j! k/ y& ^& T  p: e
  5.   int i;
    " W! C; m) Z4 ^

  6. ( |4 b4 V. g+ O- I9 Z- x; [' q
  7.   struct Student *pTemp;/*临时指针*/
    , l! s3 t- j; x. v, P

  8. / a( E$ B' S2 j: a' ?2 O
  9.   struct Student *pPre;/*表示要删除结点前的结点*/- B; g7 t8 V5 u' }. o5 h% ]

  10. 0 U  `) z) `0 v. t
  11.   pTemp=pHead;/*得到链表的头结点*/, g4 W! a2 i; h$ ^$ c: m

  12. 8 x, G0 U" c0 V3 S1 b
  13.   pPre=pTemp;8 e  z: `# A; {; N6 C% _" g) g
  14. * p) k) Q/ L6 c' Y# l3 V) x
  15.   for(i=0;i+ b4 `% W* m* W/ E
  16. " Q" ^) S: L* k! U2 M; ?7 X
  17.   {/*通过for循环使得Temp指向要删除的结点*/5 M! X) j- y! d9 S; [  ?2 `8 @; |

  18. / E# ?( W( ]6 d& o7 s
  19.   pPre=pTemp;! d! z/ z" F7 D9 t! g8 V' b
  20. ! j6 }* l: _/ ~
  21.   pTemp=pTemp->next;
    2 |# J. w8 Q& Y. j7 m" V6 w

  22. + b: Z: `4 [' U; w8 ?
  23.   }
    ) t& Y* J# B( {! o3 z$ J) ]# S
  24. 6 I- b9 q$ R- q0 L
  25.   pPre->next=pTemp->next;/*连接删除结点两边的结点*/
    # o' l8 [( E% D  K: Y+ E8 S) [% e

  26. 3 b% g+ i$ Y2 H. ^
  27.   free(pTemp);/*释放要删除结点的内存空间*/
    . Z0 |, Z2 a8 h: W

  28. , Z3 p, X7 g2 q
  29.   iCount--;/*减少链表中的结点个数*/  {% e( g6 S  _6 g$ N. K: h
  30. 2 o# K! X4 m$ Z! Z* c& c! f! x
  31.   }
复制代码
# [  A5 x4 S3 \1 v7 b) D

1 O8 T2 C) S; B
8 O6 S7 k0 m& J. k8 K" l  四、双向链表的概念* t8 T# B* |. ]3 _) _4 g
  双向链表基于单链表。单链表是单向的,有一个头结点,一个尾结点,要访问任何结点,都必须知道头结点,不能逆着进行。而双链表添加了一个指针域,通过两个指针域,分别指向结点的前结点和后结点。这样的话,可以通过双链表的任何结点,访问到它的前结点和后结点。
# z4 L8 H" Z2 G# p  在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点的地址,一般称为右链域;一个存储直接前驱结点地址,一般称之为左链域。8 `; x& O. y% [! k! i
  双向链表结构示意图:+ Y2 {; M5 }1 J7 p: H
# q* `- ^1 F" @! y# [. w

3 I' X. G5 ~3 j$ ], t& h4 ~
  

6 M9 ]5 a2 q( d( J  五、双向链表的建立与遍历
9 q7 E& ^9 L6 s/ D% |3 |: D! R  双向链表的源码实战和单链表类似,只是多了第二个指针域的控制,这里直接贴上没有注释的源代码。8 A) U4 u3 [! n$ |" D
/ n! c2 h9 W3 t4 p2 n" |4 f/ Z" D

; N7 a# L7 z  t/ r1 v* Q% I: y+ ]6 @) P( A/ e
  1.   #include #include
      i% w/ {9 V! {; J; J

  2. 3 V  ~$ U2 _5 r7 N. B! {: l
  3.   #include% W; I  m- K+ J% ]
  4. & N, F4 V4 y- R0 ]
  5.   #define N 101 E" \+ L+ V! h9 Y' M  R" ^
  6. ( {  a, d" g( g5 r2 T6 F- ]! m* X
  7.   typedef struct Node
    ) D. C5 ?& x8 v- P* c
  8. 9 C$ q4 |& y) c3 ]+ U1 `8 S* z
  9.   {+ f7 T. I# q; q) o2 B& a( |& z! x, A
  10. + G/ d$ q  q$ L+ i6 S
  11.   char name[20];7 T4 X& @) F+ g1 V6 I  h8 L
  12. ; W8 s2 b7 u) m5 S
  13.   struct Node *llink,*rlink;
    * x. s) Z- y2 x3 h+ b' {
  14. , p$ O9 K+ a5 S+ b: ~) R$ l
  15.   }STUD;
    $ d2 n. E+ _+ \+ y" Y  w

  16. 6 C( [6 `3 [- m6 |5 M2 m4 n+ o
  17.   STUD *creat(int);void print(STUD *);9 M6 [# L: P+ G2 d
  18. % T+ R6 \# Y5 F- ?; k: K6 p4 p
  19.   int main()* n8 ^6 O' g, q0 o

  20. # @7 V  Z+ b% u! M8 e6 v
  21.   {
    6 L! v6 Z% g3 N. t; M; c2 }
  22. # m# B: T$ d1 V, P% q
  23.   int number;* H+ e2 O6 i5 X! G
  24. : r: n: W, U6 N+ t! z+ H
  25.   char studname[20];9 i/ h, F: c0 ^

  26. 3 `9 h  `. p* M# ^
  27.   STUD *head,*searchpoint;4 L5 T  K) E2 A& I
  28. 3 J8 o% B! d% Q" r
  29.   number=N;
    6 X8 w% K5 x, V2 R
  30. 7 ~! c8 X; T/ e4 ?, w
  31.   head=creat(number);
    - i+ G9 ]+ a  b8 f& O
  32. ' P, y" }, K7 L3 |
  33.   print(head);0 D6 g' f# z$ r2 A% A# \' I& `, a

  34. 1 G$ F: k9 x: ?2 h! ?. L
  35.   printf("请输入你要查找的人的姓名:");& Y9 x0 B5 {; Z5 n  z) F

  36. 7 C5 }; M- J1 @" U& V, R
  37.   scanf("%s",studname);
    % I/ D* z- T: _# G( u

  38. ( z7 U  b* J2 B! M& X
  39.   searchpoint=search(head,studname);
    6 _# g+ ?+ V, v* u
  40. 2 e! u) T# \3 F4 M0 ]: K) o
  41.   printf("你所要查找的人的姓名是:%s",*&searchpoint->name);
    * a& a( b7 \: Z0 ~' \
  42. 7 {. e/ U; y2 y( E5 L3 k
  43.   return 0;5 |. V/ Y+ O1 k; a2 U

  44. 0 d8 C  b; G* v0 N8 w6 `* v$ B
  45.   }  `. M0 {& c- q: X+ H0 X
  46. 0 d+ F/ ^1 ?3 \# z( h8 t
  47.   STUD *creat(int n)
    ) ~0 c* ?* y8 T
  48. 5 \' x+ D7 f  R0 b
  49.   {. d: x* a+ U- I3 f8 A2 l) {3 }

  50. 4 S4 a$ P; _) P5 M; n$ w% `7 H
  51.   STUD *p,*h,*s;
    3 F3 _3 |4 v6 G3 m7 E

  52. * }$ x8 B+ P, }/ k
  53.   int i;/ D6 s( x8 U  A8 w. Z( z) n

  54. : b3 @8 f, O4 l) o) S" O9 S
  55.   if((h=(STUD *)malloc(sizeof(STUD)))==NULL)' E) h2 }' M$ g2 A3 U2 Z7 c
  56. ( w2 ^" G) K% s1 l% V
  57.   {
    0 l8 K1 d6 m4 T* {8 K  P
  58. ' W0 E; o' J+ x/ T: W+ ^
  59.   printf("不能分配内存空间");
    ( f8 i+ P+ k: G+ O- e
  60. 2 s+ U9 |8 b8 I+ K. t& @
  61.   exit(0);
    ; s/ h( M9 V0 g7 e) s2 @; Y
  62. , A! t% _, y, \
  63.   }
    ' L" ~( K7 q% j; v5 V: d6 {- Q

  64. ! V1 V0 H# s3 [+ ^' l$ g
  65.   h->name[0]='\0';( w4 r& `0 h3 m* {) m6 t/ B+ E

  66. + P. @) g+ A. G4 h, Z. i+ m2 ~' t
  67.   h->llink=NULL;' v* p) d+ A7 O7 s6 s
  68. ) U* g. E  D6 Q: H: d
  69.   h->rlink=NULL;) }! f- I* @5 {/ R* v; F

  70. 2 W% F' J; `/ `% ]6 K  n; j
  71.   p=h;2 B/ I  I3 f  y$ N- z7 [
  72. 9 E* _  t: _) b6 c/ b/ c2 i9 C
  73.   for(i=0;i7 ?  q! G3 p" @* b/ H/ |$ B. e; F
  74. % K$ v; k/ P1 g; @) a  f7 Q
  75.   {8 v3 f# X9 Z9 W3 q- C' t% T1 T

  76. ( v- j' w; {8 M" ^
  77.   if((s=(STUD *)malloc(sizeof(STUD)))==NULL)
    4 {* E1 ~) E6 N/ B

  78. 5 W  P1 ]' C0 c1 B2 O+ @
  79.   {9 q( e* o# k$ D6 T

  80. 6 P* Y0 ~1 v. L" v1 ]% t
  81.   printf("不能分配内存空间");! y: [, E2 b$ f" F: D: m. u" {9 ]

  82. , ~" E3 l, R2 u/ H" C
  83.   exit(0);7 v% N- S# N- S7 W$ I0 `

  84. 6 k  X/ q% T2 P( Q0 `: g
  85.   }, W9 X5 z% _, N) h, Q1 E) e
  86. ( u! [" ]+ }  o9 {- s. R$ x
  87.   p->rlink=s;9 z% u, A1 V& E" X7 z
  88. ! E4 f$ J$ P2 x* K
  89.   printf("请输入第%d个人的姓名",i+1);: S, Z4 _7 U; l0 P( B, \0 x

  90. $ {! ~0 m' m7 U
  91.   scanf("%s",s->name);& H! h4 l# w, ~* ?" i0 Z
  92. ; K$ A0 e4 o, W0 Y* ~' Q
  93.   s->llink=p;+ g/ ~  e' ^5 ~) @* w1 ^" ^

  94. 6 k: W. b8 Z+ J/ x; j: Y
  95.   s->rlink=NULL;/ R% H9 {2 N! @% o( d  k" e- Z) d

  96. 3 [. J! w& t$ t
  97.   p=s;, c) R$ [- V6 E

  98. ' \1 p+ f4 ^! f& K- P  n  v
  99.   }
    8 ^) Q9 |( X- g' U  h( w
  100. 0 n( {; x- y2 o1 _% _% o) Y
  101.   h->llink=s;
    4 x' U# v; \# R
  102. # l/ k1 P6 M, l( K- h
  103.   p->rlink=h;
    : b! m: Z% i1 K

  104. 8 s! [2 B( i* H
  105.   return(h);
    % o* P! ]1 h; n0 S4 b, A1 M: T
  106. 7 U& ~& m) {% J0 l9 V
  107.   }void print(STUD *h)
    1 o( y( O! @3 ~' Y- m5 \
  108. " W0 M# [$ ]9 p/ N# H+ [3 v
  109.   {2 v8 Z3 ~- x6 o

  110. ; O' G* M% Z& b& u7 s4 e# R5 _7 v
  111.   int n;2 x& x3 x  E, d

  112. - k1 e, B% X6 R) f2 x. i
  113.   STUD *p;
    $ i& Q6 J( b! G4 K

  114. - @4 A3 r# m9 n0 L
  115.   p=h->rlink;
    & T9 r' a3 X# _5 V6 k; v  N. J& b

  116. 4 v. x2 p: l! A- x
  117.   printf("数据信息为:\n");$ C& j& i% Z& [

  118. - r! v/ Y# @7 P2 y' J& l' n
  119.   while(p!=h). ~$ }  x- }7 t" H# I

  120. , y9 W" B% I; @& Q' q# Z
  121.   {
    7 |5 w+ b/ T6 A7 u8 h* H: a
  122. 1 c! P* d2 p7 H# ?! `
  123.   printf("%s ",&*(p->name));0 R# f% ?, [* ~5 N
  124. 6 M# w3 K& T' l5 h# h
  125.   p=p->rlink;
      V/ i% O* U$ ~' y" Y, W
  126. " w5 t; y; n0 G# G/ M  r
  127.   }
    4 f- S. c8 P- M

  128. ! `) e1 x1 l1 C2 I" p7 y, ~
  129.   printf("\n");( I2 f) W! d' J% _* B
  130. * H0 W5 N0 \+ e# q+ h
  131.   }
复制代码

* z9 u1 y8 T9 P0 I6 s- }. [; w' {/ C0 o( }8 k" P

/ C' a3 L  N$ `% b/ q, K8 e+ L6 N( J* f% P
  六、双向链表的元素查找
; a' b6 c# a" o- h3 B# c  查找函数 STUD *search(STUD *,char *);
) ~3 f' a6 V9 S" A0 [" Y2 G
: O7 |. @/ I5 k+ {& G! W! d: H, F# d' p( s, a5 p, r/ G
- {+ x3 x/ w% T6 p% a+ _& x9 Z' j: T1 a
  1.   STUD *search(STUD *h,char *x). ~8 g& s& q- }/ D0 g& W' s3 i
  2. & E9 o/ Q5 i3 T# }& M
  3.   {
    # V& l! @/ V! V3 G$ p+ L% K

  4. 2 G& I7 R) v( n" M/ `  r  u: v
  5.   STUD *p;* O1 p) j) \, H; ?; i& O8 m' {# }6 \; [
  6. 8 e. U$ A, w3 A: F4 R8 f' g6 A* Q2 a
  7.   char *y;
    2 [  ?& d! t3 E

  8. $ I9 u8 s( X3 p  e$ ]3 [+ d
  9.   p=h->rlink;
    8 p$ P3 @7 d  Z% \( r8 A( f

  10. * F4 y% _# O7 w% m
  11.   while(p!=h)& ?$ b6 P3 q/ Z

  12. 9 L+ d7 B( c% L
  13.   {
    / V$ o9 L7 X3 C0 A% q& p) X& W! z! x

  14. ) U0 G7 @9 c9 H# l& ~
  15.   y=p->name;. P. b) |# C( p
  16. 7 W% o; p* d4 I2 ^) z
  17.   if(strcmp(y,x)==0)$ m5 _5 B  b* r; J- u
  18. 6 n6 @2 M1 v& Z
  19.   return(p);
    4 R: q& S% |6 s; c* B/ r% k
  20. + j' H/ q( X" M# D# j
  21.   else
    7 P8 \' f$ j+ X

  22. & O- }" {; {0 ~. a9 Q
  23.   p=p->rlink;
    * k' y/ K* @5 `4 Z

  24. # L- z1 y; a) D4 Q
  25.   }( {( ^3 I7 E6 g& a

  26. ' }' h8 ]9 ?- g4 g. E+ f
  27.   printf("没有查到该数据!");
    . C' U  S. S! A1 h1 _

  28. 5 U. h# m' V7 f/ n5 \; i) c
  29.   }
复制代码
, x3 b' M& u6 q6 |

- a9 T/ e) Z$ h0 N* \! a; s5 g0 R( f. \/ |+ R7 g2 t- T& q, T
- l0 A8 C1 L5 b: a1 |
  七、循环链表的概念" P2 P( h; ?: T( V
  类似于单链表,循环链表也是一种链式的存储结构,由单链表演化而来。4 _7 ~+ g. F% Y* l( H- I& t, P
  单链表的最后一个结点的指针指向NULL,而循环链表的最后一个结点的指针指向链表头结点。
& u  f: A/ B' K7 c$ e  这样头尾相连,形成了一个环形的数据链。& x. J0 j+ }. F( e! G( c+ f- x
  循环链表的建立不需要专门的头结点。! B2 N5 g# H5 s- Q% P" K$ d
  判断循环链表是否为尾结点时,只需判断该节点的指针域是否指向链表头节点。" H& j5 ]* e, J( R8 [: o
  八、合并两个链表的实例
& q. {# h  W& l, b  建立两个带头节点的学生链表,每个节点包含学号、姓名和成绩,链表都按学号升序排列,将它们合并为一个链表仍按学号升序排列。" B; x& L( Y; a+ [; z7 |, w
  算法分析:
4 I% f/ e$ |! G% ?2 q. l5 m  合并链表用merge()函数实现。函数中定义3个工作指针a、b、c,其中a、b分别指向La链表、Lb链表的当前结点,C指向合并后的链表尾结点。合并后链表的头结点共用La链表的头结点。3 }6 i. o3 J7 D) a
  ①合并前,先让a和b分别指向两个链表的第一个结点,c指向La链表的头结点。
. w: |" _2 y% z/ j, {0 a; e  ②合并时应该分3种情况讨论,即La和Lb都没有处理完;La没处理完,但Lb处理完毕;Lb没处理完,但La处理完毕。
7 c/ U' @. c: U1 q1 `2 |# \  ③合并过程中应始终将La和Lb链表中较小的一个链接在Lc中,方能保持有序。
3 B* M9 Y+ r( ^+ y& a" p
: L7 ]9 W+ z3 v) ^( s" P/ \8 m% _
2 j3 d9 T0 M% r

9 W4 H+ M; N$ C- v- }
  1.  void merge(struct stud *La,struct stud *Lb)  y$ a9 ^- D7 U) h( W6 c! a: {

  2. ' A- K4 s1 [* m) y4 O$ E
  3.   {
    0 i) \9 j6 t3 ?9 G. F& Y! X
  4. ) I: x$ M" j' {7 B1 }+ [
  5.   struct stud *a,*b,*c;/ X, L$ R% j7 w, t7 N, F* N  Q# v
  6. ( Z- s# ?. s! {9 E% K5 x. w
  7.   c=La;
    , h& X) e" Y& Z! ?) r) z

  8. ' b6 D7 Q' x6 ^5 E2 H- p6 @0 }
  9.   a=La->next;/* 合并前 */0 }, p# @0 ^$ g( D( M) N# M

  10. ( o- |, |3 }# x5 P+ A" `# o" E
  11.   b=Lb->next;7 S  J+ f" y3 P, j' ]+ B
  12. ( s6 o- h% v7 n) M
  13.   while(a!=NULL && b!=NULL)/* La和Lb都没处理完 */( t- }* \. }+ u/ ?, |+ d
  14. - m) z. o' z' N: a
  15.   {
    & z8 Q- C. `+ `% c9 t5 L3 C7 c0 P
  16. + X; Y, Z! W+ w, g9 W
  17.   if(a->num <= b->num)
    7 f. h+ y8 g' @7 e% o
  18. 2 p' b- D* p  Y$ L; i  a
  19.   {
    % Y% A0 c) D5 X8 \( q4 T$ v3 @9 E

  20. 8 L/ l8 C" B" u: |- F$ E* m
  21.   c->next=a;! ^+ p- D7 _8 t' D% t3 n' U

  22. : h& r% L) |* ?- x
  23.   c=a;/ ~# l' B0 [) ?0 ^

  24. . a% ?( ~/ P1 {1 c' B; q
  25.   a=a->next;
    * w4 {. Z% D1 H8 a! y! S7 A
  26. 4 J4 D( ~  _; d+ k) B$ @# J
  27.   }
    . g6 S; }1 ?0 {
  28. ' `, N+ N- b2 a
  29.   else' B. r! Y3 A  o% K) E
  30. 9 `& z2 E  p8 i. R% T  g5 r+ l. l
  31.   {
    3 _/ U$ K! S: j1 V, O
  32. # d8 w/ t- S& m
  33.   c->next=b;
    ! c/ V& T) V: M) q& w  W5 U' O

  34. ! w. w: C* s; u% m# t, Y( ~
  35.   c=b;
    + m; T) j& z3 C+ v% j% v  ^
  36. " y4 D) X$ {0 Z* J1 t
  37.   b=b->next;8 ?4 V: d1 W" Y+ ?! H* W
  38. ; c6 a3 L: L+ n/ s- z( Q5 o. a
  39.   }
    5 f! N/ p5 j% _

  40. # n& ^! v& J  G2 p! L
  41.   }
    ' ?7 R, `2 R. h( b
  42. * E' P& @/ e/ |. j0 l
  43.   if(a!=NULL). \: x4 z( x8 `

  44. ' ^8 ]+ y. g; Y+ a8 `
  45.   c->next=a;/* 若La没有处理完 */
    ; w4 ]& M; \  K: K. a* q

  46. ' w( N4 A- C! i; V  C. L8 V
  47.   else+ c: }) `" S0 b+ o& G2 [

  48. 0 l- W: S( Q! ~6 b/ c
  49.   c->next=b;/* 若Lb没有处理完 */; i' K2 X3 _4 b3 e8 d: a0 `
  50. ! y3 g4 t+ D2 k# H& z9 \* j9 t
  51.   free(Lb); /* 释放Lb的头结点 */4 K# i9 Y9 r$ N& U, z. p8 m

  52. 9 W1 E8 g: E. l* o0 {: L9 M* r* h
  53.   }
复制代码

, B6 q  a/ _/ J4 G5 B& w
, O) w1 s8 X/ u. V1 C# A  p+ p
1 F8 Z6 E' G/ b( T
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-9-3 20:38 , Processed in 0.156250 second(s), 27 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表