数学建模社区-数学中国

标题: 【Java演示】什么是链表?数据结构 [打印本页]

作者: 杨利霞    时间: 2020-5-4 15:55
标题: 【Java演示】什么是链表?数据结构

3 p, @6 b4 x& j6 T, ~, n# c【Java演示】什么是链表?数据结构
. T- I( C/ V  S2 J3 W: w2 F- S一、单向链表
$ N8 K2 }+ k6 b4 w1 b/ _; g4 A
1 z# y3 n  f: [/ E 1.png
4 }0 y# t) N7 @* s1 f链表(linked list)是一种在物理上非连续、非顺序的数据结构,由若干节点(node)所组成。; ~$ p% ~: a: b" d/ H& d1 `
单向 链表的每一个节点又包含两部分,一部分是存放数据的变量data,另一部分是指向下一个节点的指针next。) K5 f- W& `1 R+ s. ^/ p# B( p; A/ q
链表的第1个节点被称为头节点,最后1个节点被称为尾节点,尾节点的next指针指向空。
, b  d/ W) Z% E# t! |- b0 F' p: ^5 H5 O* \) T! o5 ]
什么叫随机存储呢?
9 `8 Z: T& e3 z- r% ]1 h1 N7 B' k9 U
4 n% q) {. M- s7 x% F如果说数组在内存中的存储方式是顺序存储,那么链表在内存中的存储方式则是随机存储 。
9 D! L' e( ?9 J$ o上一节我们讲解了数组的内存分配方式,数组在内存中占用了连续完整的存储空间。而链表则采用了见缝插针的方式,链表的每一个节点分布在内存的不同位置,依靠next指针关联起来。这样可以灵活有效地利用零散的碎片空间。
3 q" A7 i( S" l4 f7 C$ ^& ~+ r 3.png 9 j, \) q  r) }% \3 v% H, F
+ |0 e  ?& h3 `5 E; z( l; k; \" r

图中的箭头代表链表节点的next指针。

链表的基本操作1. 查找节点

在查找元素时,链表不像数组那样可以通过下标快速进行定位,只能从头节点开始向后一个一个节点逐一查找。

4.png : F0 G4 X1 Q1 e
6 f8 p1 O0 h) Q8 ~5 w: @
/**
7 V* G. \) m1 w4 [- r     * 链表查找元素9 }9 t! |  b" m) C8 S
     *
3 x- a/ f) `; q! V& ^     * @param index 查找的位置
+ t; g: g( w8 R' Z, o     * @return index位置的Node对象
7 Y0 K! Q# U: o8 @, E  _3 A     */) [5 R5 g, E9 `$ k/ J9 x
    public Node get(int index) {: c' X9 V& y% j3 l6 l
        if (index < 0 || index > size) {
) Z: y6 F1 S% s            throw new IndexOutOfBoundsException("超出链表的节点的范围!");3 s- A1 \1 g; K$ [; C! _8 m
        }3 |' l4 T0 D' ]2 G; J; F
        Node temp = head;5 N7 k% V9 Q, C& W( g
        for (int i = 0; i < index; i++) {
4 T. X  c6 N9 I            temp = temp.next;: [. L5 h2 e0 c( \8 S! r
        }
  U8 @' P: m- Q( [# C) c        return temp;- Z) v% I6 U: R0 n0 O
    }
& w# {: _$ i  J- ?$ ?3 o# W" E* T* [/ t' l

链表中的数据只能按顺序进行访问,最坏的时间复杂度是O(n)

2. 更新节点 5.png - x3 B! K7 A  o/ `7 ^+ O

" g8 I. Q7 @' ]& O如果不考虑查找节点的过程,链表的更新过程会像数组那样简单,直接把旧数据替换成新数据即可。7 _* A) ?+ z- R% n8 |* R  h
如果不考虑查找元素的过程,只考虑纯粹的更新节点操作,时间复杂度是O(1)
: `6 s7 G# l, ], Z4 C" p% n" s/**
0 g) C9 Y; A; F3 |! k9 r" v     * 更新节点 将列表中指定位置的节点的data替换为指定的data。
+ w' a  c9 D. P3 ?  p/ Y5 V     *
: A4 k( Q; o- k3 Y+ O% n     * @param index 需要更新的节点的位置
5 C+ C& g$ o9 h+ G, C) s* b     * @param data  新data4 a1 _1 t* \" e
     * @return 旧data
; c! ?8 g: o1 Z6 s0 @& ~, ^6 v     */
8 J4 [1 k! i5 B" C9 f    public int set(int index, int data) {
$ Q$ o7 A# x7 i* W# T5 U# D$ _7 u        Node x = get(index);
- z% Q4 d" K+ ?        int oldVal = x.data;+ U  L9 g  E$ c2 L2 p& I# F
        x.data = data;
2 e9 h! T# Q/ p1 V. ~        return oldVal;% Z% u* M" |( o: ~6 N1 Q' Y  C
    }
( f+ \1 n# b$ W8 j' `; R* a
6 M/ b' c+ x, k8 ~3 p$ r3. 插入节点

只要内存空间允许,能够插入链表的元素是无穷无尽的,不需要像数组那样考虑扩容的问题。

与数组类似,链表插入节点时,同样分为3种情况。

3.1. 尾部插入

尾部插入,是最简单的情况,把最后一个节点的next指针指向新插入的节点即可。


1 ^4 O8 Y, R5 i" I# ?& N 6.png ( T$ W! B, l3 y/ ?
3.2. 头部插入

头部插入,可以分成两个步骤。

7.png , d% a' t% S$ v

7 o$ `) C3 V, {+ A3.3. 中间插入

中间插入,同样分为两个步骤。

8.png
2 e, _' |8 z6 a' x8 D, P7 p) M- o3 H
三钟情况的代码合到一起" T5 G4 I3 ]4 X6 v3 M
0 S) U; d& U8 k3 k+ c$ z
/**. U: ]) G2 d6 n; l! Q. @- K1 [
     * 链表插入元素
! Y8 H1 m8 U$ d4 S% C* {     *
" [* t  r* W; ~6 _( v. m; [     * @param index 插入位置9 Q/ [- k- U9 P
     * @param data  插入元素 被插入的链表节点的数据4 N+ R2 ~$ I7 j% y, |8 `
     */
0 g; f+ A% v5 h    public void insert(int index, int data) {. b4 U9 S* r* t( O
        if (index < 0 || index > size) {% B& Q( i0 c# K. d7 r
            throw new IndexOutOfBoundsException("超出链表节点范围!");9 Q/ t& q3 u/ e6 c2 z" K$ G
        }' ^8 h) g2 _, @8 c* O  G9 S
        Node insertedNode = new Node(data);3 T* n) D5 A( K2 q
        if (size == 0) {, N) Y# B. x+ [+ R; ^1 O% C
            //空链表
6 p/ B5 w; f6 Y" c- O6 w& p            head = insertedNode;
; V2 t5 }; {2 w- j9 e" c6 O. v7 V            last = insertedNode;3 W6 c) n1 [4 }8 ]; u
        } else if (index == 0) {
8 ^" H" z2 |( L9 K            //插入头部
& x! ~% E# ^# u9 T0 M5 L5 _. H            insertedNode.next = head;: Z0 l  y- ^4 S- f) H
            head = insertedNode;
" e" b% x- q* |! a7 c        } else if (size == index) {
* A/ [# n3 F8 D; e  u+ s            //插入尾部
, b8 M  \: ~) g; l4 U/ e+ j* ~. b            last.next = insertedNode;
" s+ R" s3 c2 r+ N0 m            last = insertedNode;
0 E. l" K/ j2 ]' X# Z/ D9 D# L        } else {, g* j5 R/ B, H7 `9 O7 l2 R
            //插入中间
# e: U7 f, _3 t0 \" Q" m) P1 S            Node prvNode = get(index - 1);
; f" k# a5 Z4 A, D) p7 f            insertedNode.next = prvNode.next;2 _- t" Z) ~9 h3 B3 c  D4 v5 d
            prvNode.next = insertedNode;
" p9 Q7 s3 |. {. R6 r        }- L& \2 W+ m0 }
        size++;
* }, n# l; k" l3 u' q    }9 L6 b/ T9 L0 ]

2 [7 ]" W# O+ f" y* a8 e/**
3 C* v9 t' @; }  \% p! m     * 链表插入元素5 O3 I3 J2 H- Z: B( Q$ ~
     *
9 n+ ]4 L& T3 _7 ?8 r     * @param index 插入位置
, |' M- B: N: f3 Z' V$ F     * @param data  插入元素 被插入的链表节点的数据( D* f2 v5 C5 c7 U2 p# R
     */% y+ Y4 q1 Q3 g: j
    public void insert(int index, int data) {
+ B. _) m* ^! g! A  b0 S        if (index < 0 || index > size) {
: v" ^. Y5 ?/ N5 W8 Y            throw new IndexOutOfBoundsException("超出链表节点范围!");
! a  `- [8 i4 |% L* C0 t        }1 }% L5 W1 L2 {4 C! R9 J# ?1 f
        Node insertedNode = new Node(data);
! B6 U4 U: {& T2 v, y        if (size == 0) {9 _1 y& d1 F, F4 t8 R0 A5 B
            //空链表
6 h) ~) U7 Q' l; \5 k' U/ T            head = insertedNode;
8 m0 k/ x4 C4 [* Q            last = insertedNode;. a8 c: c6 D1 @! Q4 u3 h
        } else if (index == 0) {
4 z( r5 o2 k$ L' I3 ~            //插入头部$ ~2 V0 U7 a3 a8 a4 f& D: Y
            insertedNode.next = head;
9 S* T; V0 Y' Y! L            head = insertedNode;- Y2 ?1 Q1 x- z% `  j
        } else if (size == index) {; A" c+ F1 K+ D* s+ @$ o+ n1 G
            //插入尾部
; {- @4 s7 @$ }, ]            last.next = insertedNode;3 \2 @. ?% ^- F1 E- Z
            last = insertedNode;
% m- i" @8 L5 X        } else {
& t7 ~# g- g3 \3 W4 V6 Y            //插入中间8 L2 W* }# F6 d9 i
            Node prvNode = get(index - 1);
" f) z5 N* J$ K$ ~2 V            insertedNode.next = prvNode.next;
; N, X1 T. j; _+ u  z6 `8 I% t0 E4 f            prvNode.next = insertedNode;
% q: N6 n5 M6 O0 R: k& g7 W        }
, T/ e9 I$ v6 K' U% q. ^6 G        size++;. H$ `) _) o" P9 _) t
    }* |9 h# ]0 k0 E+ T7 w/ d+ U
4. 删除元素

链表的删除操作同样分为3种情况。

4.1. 尾部删除

尾部删除,是最简单的情况,把倒数第2个节点的next指针指向空即
# K  N( y6 Q! _# S可。

9.png ! b( B1 d/ s& `/ c( J1 c
9 I' Q) H( A; A4 _( a4 _& }) \
4.1. 头部删除

头部删除,也很简单,把链表的头节点设为原先头节点的next指针即可。

10.png ; O: a, B2 g8 l3 }& G) v, G- K( m
' _; Z! ?$ B( G
4.1. 中间删除

中间删除,同样很简单,把要删除节点的前置节点的next指针,指向要
. Q1 M+ @" k+ t" l; V删除元素的下一个节点即可。

11.png $ `0 a9 l! d! I. Q- W6 u; H

4 V7 w9 ]  L/ \( q# B( V
5 c0 E9 K' Z7 W2 B4 S& P4 q这里需要注意的是,许多高级语言,如Java,拥有自动化的垃圾回收机制,所以我们不用刻意去释放被删除的节点,只要没有外部引用指向它们,被删除的节点会被自动回收。2 x' ~" l7 ?) n; @3 _
如果不考虑插入、删除操作之前查找元素的过程,只考虑纯粹的插入和删除操作,时间复杂度都是O(1)
/ s* b" N- _* U$ ^* O' ^3 ?/**
% a$ {! H4 B8 y( d3 U9 N     * 链表删除元素! p( g* n. K4 |4 V1 v
     *
2 }- s4 ]: [1 d. `: ?& P" k     * @param index 删除的位置+ P; Q8 P$ K1 A: W
     * @return 被删除的节点
$ g, E2 X) F" B, o     */, h: W! ]+ j; X- o/ z* h$ V
    public Node remove(int index) {# n9 q8 \  C8 W7 `' X
        if (index < 0 || index > size) {! k% Z8 E* Z$ q3 U! O
            throw new IndexOutOfBoundsException("超出链表节点范围");
2 W6 k5 T- l. [2 s  d% P        }* D* n1 B' @5 _4 k" X
        Node removeNode;2 J  w9 b7 S  _; E0 M
        if (index == 0) {
# C# \4 p) J" X7 n. e            if (size == 0) {2 z4 g9 g7 g+ m, r
                throw new NullPointerException("当前链表为空,不可以进行删除操作");
' K5 {3 V9 ?" y, ?) o7 u: a            }
) \, W0 w2 |) b5 n  V( B            //删除头节点. W: ^6 g$ W) n
            removeNode = head;# s* a6 d$ ^/ ~7 _  ]: j) A
            head = head.next;
) \& A* `" J2 C( C$ l        } else if (index == size - 1) {: H- c! w+ y: p2 v) b# u9 p
            //删除尾节点
% w- |3 L+ @; ?* Y. U/ U3 U            Node preNode = get(index - 1);; m$ H  e! g7 Q( n
            removeNode = preNode.next;) T! z, q" [2 }  D6 m& B
            preNode.next = null;' \, d( [, ]* H
            last = preNode;1 K' x! m+ c2 ~8 ?* Q" U
        } else {0 d4 l6 J1 |% C: _+ R6 O
            //删除中间节点5 p; x, R* y5 H, l4 e' X; W4 C
            Node prevNode = get(index - 1);
: E# u% @6 G# |( ^9 f8 Z- ]( h            removeNode = prevNode.next;
" W; z- c  \" x" N* d- b4 s. n/ C            prevNode.next = prevNode.next.next;- i( j, K' z4 B6 B' o
        }
/ v! S+ Y* b$ Y9 I: h        size--;  k) N) m0 |1 o( m
        return removeNode;" G& m3 Z9 R/ b; k' |/ L
    }
9 H. h" M% h) a2 i2 hJava实现链表的完整代码package chapter2.part2;9 V9 l# F$ \* S7 O7 }$ C  q8 O
+ D. }1 B" M2 G5 w0 g, e+ W( f( j
/**) O( @( Z0 }$ I1 Y) t
* Created by IntelliJ IDEA.& B+ l! ]7 j. p" L
*0 Q8 _, u0 i7 u+ t5 `5 L4 k$ A: S, h8 P
* @Author: 张志浩  Zhang Zhihao  k% L& L$ K' F8 G
* @Email: 3382885270@qq.com
0 O7 q) s/ E6 l! ?1 v8 k * @Date: 2020/5/3( k7 H3 j0 Y6 D4 C' j$ C
* @Time: 13:39
; z7 m4 o. u  p. s6 Q+ I * @Version: 1.01 R0 \8 j( ]- F) H
*/
1 V7 K) \4 |' J0 V6 Opublic class MyLinkedList2 {
; N! i( X, H- e6 A* b6 r8 X3 ~, L    private Node head; //头节点+ Q4 P1 C, U/ H! i6 s
    private Node last; //尾节点
5 o% q) z8 E. ^+ g. e    private int size; //链表实际长度
) l( `! y8 q/ Q1 }! L7 U
/ U5 v. o9 Z3 }0 Z& R+ \0 r: s* |/ P0 G0 z    public static void main(String[] args) {
$ _  a) F& V5 R, M" r" Z        MyLinkedList2 myLinkedList = new MyLinkedList2();
+ J6 D( i' Q/ _% }* V//        myLinkedList.remove(0); // java.lang.NullPointerException: 当前链表为空,不可以进行删除操作( s9 P4 Y( P: U+ A9 Y
//        myLinkedList.remove(3); // java.lang.IndexOutOfBoundsException: 超出链表节点范围
' W7 R1 g9 u8 O        myLinkedList.insert(0, 3);
5 u5 i  v4 ?0 L& @        myLinkedList.insert(1, 7);
! b4 D( j# y" L/ s, i2 ^        myLinkedList.insert(2, 9);
6 h3 ~: x9 r5 q8 X  ~        myLinkedList.insert(3, 5);
3 Y6 U9 m, M) b6 g# [        myLinkedList.insert(1, 6);. p% n$ ~8 z( T  |  {5 k$ u
        myLinkedList.remove(0);+ |8 `" R( T, L" N
        myLinkedList.set(0, 23);0 {; p% j8 ]4 R! U; N) c3 R; x) B
        myLinkedList.output();( c. @( d2 J8 u3 g7 s  v
    }! u5 j/ K- ?! f1 Q" [* p6 ^

' H- N$ x& |' }; O$ g0 G; i5 r" @    /**
7 Y: T8 G+ ?7 l. ?     * 链表插入元素
8 k/ l% E, E7 h% y. @( B     *5 U) H4 m- j" `. P
     * @param index 插入位置  \/ ~' O! ~0 {, U0 z- z* Z$ N
     * @param data  插入元素 被插入的链表节点的数据3 A9 }2 }! k( Y; m1 F3 {0 W
     */
7 B- R$ w+ C" D1 O$ |( K9 Q" }8 y    public void insert(int index, int data) {
2 T7 L" z  C  D% a) a  e- L        if (index < 0 || index > size) {
6 h3 R1 Q" G& f9 Z# g8 P6 t            throw new IndexOutOfBoundsException("超出链表节点范围!");( y+ E3 c  ~! ^8 Y- c2 h; x, @
        }
' j! V- ?4 Q, j5 }: j2 _, D1 h        Node insertedNode = new Node(data);, y, e4 N$ j4 [( Y
        if (size == 0) {7 l, ^, f% _9 _8 J' g0 M
            //空链表
0 x0 E7 I- s. y, n            head = insertedNode;
# \8 @1 H/ C, P. `' s/ X            last = insertedNode;
4 S4 K  y0 A) a' E        } else if (index == 0) {
8 E) L4 Q: o* F0 G+ n, e9 n9 k            //插入头部
0 b/ u1 j* J* l4 b( d+ _, o            insertedNode.next = head;
% ^/ ^* x. o1 I$ c2 T9 E; k            head = insertedNode;6 V# {9 G( U- q3 v: n# i  k
        } else if (size == index) {
3 |& T- M1 s, R/ G) N+ z5 L            //插入尾部# f! c) N" X. ~& r) O) X! {" ^
            last.next = insertedNode;
7 P$ M* a1 w5 i6 x1 @            last = insertedNode;) n" x# B* U- K
        } else {  ]1 ?3 j# U7 V
            //插入中间
5 H: N' _5 A! ^$ j" c5 ?+ S            Node prvNode = get(index - 1);* \* a0 a& A$ @. A1 E. @8 M
            insertedNode.next = prvNode.next;
* O3 v3 `0 k2 V            prvNode.next = insertedNode;
8 o9 T5 c$ _' g2 x1 ^4 H) H/ J6 I        }
. b% ^+ d9 N' @# W5 @3 n        size++;8 m/ s/ _6 a/ p: e* H2 I
    }
9 }' G' s  @2 Y( m) M0 f
  e1 L* r% c, ^. `/ d& y1 y) H    /**$ ?. d3 M. j6 L# x+ Y5 r9 a
     * 链表删除元素  t3 _- P- x3 \! G' g
     *% T$ Z4 h( K5 L" `
     * @param index 删除的位置
$ w: n; V. K' g1 t     * @return 被删除的节点
3 h& K* t7 r8 x! C: K4 w) F     */
% ?0 Y. c$ ^0 K! T  D2 B    public Node remove(int index) {
, p) v' M5 G: t$ Y7 M        if (index < 0 || index > size) {3 }8 i- x8 r' U- A6 Q- P& `
            throw new IndexOutOfBoundsException("超出链表节点范围");% u- {. g9 \6 ?6 B# h& B* H! m4 G
        }
" Q/ y& s; k5 N/ m        Node removeNode;. ^- c$ Q$ |  a
        if (index == 0) {
0 j) a$ b$ o. i- J: H; v: O, b            if (size == 0) {
& Z' C$ U- V$ L* O9 m! j0 s                throw new NullPointerException("当前链表为空,不可以进行删除操作");' y# V. V8 r; |+ E( W- j
            }' i1 ?) F: }9 V/ \9 w2 a' S% F
            //删除头节点
4 G) T* v9 P6 [6 t7 J6 @            removeNode = head;6 @5 E; z6 F3 ^
            head = head.next;- P" b8 Q: Y( E$ f
        } else if (index == size - 1) {& W; F7 p/ |9 y& c6 K4 |
            //删除尾节点
: [0 b1 O- R8 \% \* i+ v            Node preNode = get(index - 1);
9 o2 g: H3 e% _# p+ ?1 P6 `            removeNode = preNode.next;  J4 S9 P3 S2 r" v
            preNode.next = null;* r; x. A  t3 e9 U: @
            last = preNode;
: Z1 ^. W; y6 }# y7 ?/ G        } else {" n' ~8 j1 ?7 Q/ H: ^7 _
            //删除中间节点
7 o2 t) ?5 \4 j            Node prevNode = get(index - 1);
/ P' w# k; _4 n1 }! `! l            removeNode = prevNode.next;
9 K/ U% |5 {/ a& W% D$ }            prevNode.next = prevNode.next.next;# {) f$ ]5 Z" J" F7 t% Q
        }0 O% U# W( O4 Q5 H8 h
        size--;, g* ^; A4 B! P; r+ E" q6 P/ Q
        return removeNode;1 N( @: e8 Z1 Y( a+ R$ e
    }
/ n$ x: a4 n9 O
8 z: R7 j9 f. u" m" f9 O- w# [    /**: ]; n' N5 p4 w! G) I4 F
     * 更新节点 将列表中指定位置的节点的data替换为指定的data。$ B% p& ?" _! i
     *
- r: `- C* q  Q, p     * @param index 需要更新的节点的位置
( b- U: f2 U( u8 e1 ~% K% j& Z% \     * @param data  新data+ R& q% Z# O/ T5 p4 _) ]- ^" y
     * @return 旧data
, C. D) l9 Z$ w& [: N. {! L     */
! b# ?* \3 U1 V; m    public int set(int index, int data) {9 s0 u! ?+ g% |" p# ]3 v
        Node x = get(index);
2 i+ B' q7 n2 `6 k! q7 O- u        int oldVal = x.data;
& \$ X/ K2 n+ {/ U5 Q( {; n5 k        x.data = data;
' H) R: O* z, U1 e/ K5 C" j        return oldVal;4 m1 b6 T0 N7 }
    }; A. \7 T$ r' a% P7 n- m5 N
1 Y: Y/ C9 W* h* B# X
    /**. i8 U5 y/ B4 Q5 R6 n- ~
     * 链表查找元素. ]/ l; E) J* r- O
     *
' |* o' k3 x2 l* F' U     * @param index 查找的位置# T1 y: E  L( c1 Q4 O
     * @return index位置的Node对象
9 z. Q( h  C" m0 ^6 Q' m3 b     */2 D1 E) v) n3 U7 n! K, M8 o# r. r
    public Node get(int index) {
, Y( H, i4 I( n7 x+ y; B2 a        if (index < 0 || index > size) {1 g1 M" L' r7 y( p2 c2 t
            throw new IndexOutOfBoundsException("超出链表的节点的范围!");
: ]: m* a! D4 l0 R        }
) b) @/ Z. x* K0 z% e7 R        Node temp = head;: U* z/ m! k% @7 [
        for (int i = 0; i < index; i++) {" V/ D0 ~6 c" v8 }
            temp = temp.next;5 v' F$ O  w3 R
        }
$ {$ k" A# _, u  p" L" [1 m' d( H4 O        return temp;" O/ N9 b7 k. Q2 w
    }
* r0 O" R0 Z" T+ I) n/ N2 V7 D/ I' M# |7 R* m. {) @: Y& B, }
    /**
' m* H. q( x& }     * 输出链表% D  |- V  {) Q) H* H
     */
4 o1 o) f8 m, }0 }; X5 p3 [& P, `    public void output() {1 G$ A, @& u6 _! c
        Node temp = head;
: Y$ u- j+ F! O6 P: r        while (temp != null) {6 K0 k# G) x# p9 C2 ~$ ~# k
            System.out.print(temp.data + " ");
- h% c' W% J& \. B            temp = temp.next;2 W" t' U, h* r# ]
        }/ [& ~3 @0 J$ k8 v: a2 y
    }, I3 x  n: N, K- z& \9 f
4 F4 m4 z! @% o  N" [& ]
    /**, y  F+ r8 `) Q  g% {& c; S
     * 链表节点5 _- p) x0 T6 H6 F1 t& J9 O: V
     */
; W. o. U- E. k6 a' ~9 I    class Node {
: D" e4 s/ s; P+ I( }4 u" P        int data;
, S  ^: B" }; j& h        Node next;
3 c0 F+ Y% [1 ^1 y& R
" ?! S1 Q& x- q+ k+ s3 Y' v        Node(int data) {: K0 q: m  }' e' V" C3 l
            this.data = data;
$ @" t2 p0 j( E) Q        }% ~, V  V7 j/ ~, p- K
    }' @9 C. g& F! `: M: w
}' S4 N  d7 X6 b; |7 |
* q- r, C$ d& B8 F0 m# V

) l/ ~3 {& @% R9 c) P二、双向链表 12.png
' u1 A9 T8 O3 Z8 s4 [" g) b0 E双向链表比单向链表稍微复杂一些,它的每一个节点除了拥有data和next指针,还拥有指向前置节点的prev 指针。
: w$ A" ^/ k; b5 C/ C  m0 P, Y
, ]5 ?1 y  G8 V7 R* l3 G; |
2 a  w! I/ K5 K9 l8 Q' \$ [
1 Q% }6 \' r! K$ O% g
————————————————! V+ c2 f" F' `+ P: s6 j# ?
版权声明:本文为CSDN博主「爱做梦的鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。$ z" i! B. V) u0 B2 W+ j
原文链接:https://blog.csdn.net/weixin_43124279/article/details/1059044683 z- ^: b; S' t6 Z- r

  k8 |$ V/ r+ y5 I9 O3 n4 V3 w" D
2 f8 z2 i3 u( e& R5 v. N+ L

2.png (256.36 KB, 下载次数: 245)

2.png






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