QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5252|回复: 0
打印 上一主题 下一主题

【Java演示】什么是链表?数据结构

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2020-5-4 15:55 |只看该作者 |正序浏览
    |招呼Ta 关注Ta

    4 A2 ?% s/ t( ~. P【Java演示】什么是链表?数据结构
    9 K& O9 `, T8 f$ y/ i一、单向链表7 f; i! k; e5 P5 N8 Q! S

    2 |; q( g. u' M 1.png
    5 j0 k$ q! K) |# @链表(linked list)是一种在物理上非连续、非顺序的数据结构,由若干节点(node)所组成。
    * Y; a- M: h# W, f单向 链表的每一个节点又包含两部分,一部分是存放数据的变量data,另一部分是指向下一个节点的指针next。
    - M8 ^( c3 J$ G, K2 p7 G链表的第1个节点被称为头节点,最后1个节点被称为尾节点,尾节点的next指针指向空。' c- J4 U# q1 b# i( G6 Y

    6 X& t" V( a2 Q$ \什么叫随机存储呢?
    / F. Q) f: a5 h- a" |8 f" `; Y
    4 E* d( ^( O2 t  d# B$ ?* [! A如果说数组在内存中的存储方式是顺序存储,那么链表在内存中的存储方式则是随机存储 。/ T& d( E9 v, V6 G
    上一节我们讲解了数组的内存分配方式,数组在内存中占用了连续完整的存储空间。而链表则采用了见缝插针的方式,链表的每一个节点分布在内存的不同位置,依靠next指针关联起来。这样可以灵活有效地利用零散的碎片空间。+ c( I- a. O: ]. F6 V1 {+ G& P
    3.png 4 _8 v  v3 S7 s( h) M. N% A$ {
    5 W' w% l$ H: m. l" q/ v/ \

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

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

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

    4.png ( F" \% K2 p" a- W) z
    ' c9 H* G) ^5 G$ o: ]/ [; T
    /**1 G" T7 M0 O1 p' d
         * 链表查找元素5 ]+ m+ ?, K( Q  W
         ** l6 T5 v' ]; T
         * @param index 查找的位置
    9 A. G8 J. F9 ]     * @return index位置的Node对象) m; Z7 K% T( h( c* D
         */$ `: m, s8 F! G% n1 E5 x* R
        public Node get(int index) {1 T4 g% K% \" a
            if (index < 0 || index > size) {
    # }+ F! q' x, Y7 k, s5 Z2 T6 _4 Y: l' H% D            throw new IndexOutOfBoundsException("超出链表的节点的范围!");. Z; I$ |% b& @/ b- H. m+ p
            }
    : i, `$ z4 F$ c/ e9 o/ Q# L7 s        Node temp = head;
    6 A: @# B, `- w( k6 c9 y        for (int i = 0; i < index; i++) {
    8 l0 c' u  T6 E, t2 w. {            temp = temp.next;
    8 V. d8 @. x6 O) C6 b        }
    ( C4 `' K! N6 @8 T' i  q# o        return temp;
    - r3 i: u( \/ o& G* ?: \0 q: J    }
    # Z- T! G6 b) z* o. H1 C! l) N' G1 q
    ; f1 m: u1 P# G* z1 s

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

    2. 更新节点 5.png : k& H) U+ Z6 {/ W, ~3 M

    . C# @6 R% q& T5 O; k, B8 g如果不考虑查找节点的过程,链表的更新过程会像数组那样简单,直接把旧数据替换成新数据即可。# ]' A; {/ s0 K* i+ _5 O" g! |9 c
    如果不考虑查找元素的过程,只考虑纯粹的更新节点操作,时间复杂度是O(1)( i2 G8 p7 r9 p$ n- ?
    /**; X% L: f0 S( ^! H8 P/ x
         * 更新节点 将列表中指定位置的节点的data替换为指定的data。+ N& W, d8 C- h, Q0 X- g3 A9 `  ^7 {
         *
    % S  K  d9 _  t5 ^' E     * @param index 需要更新的节点的位置
    5 y3 ^. a/ e2 k! k# i# t     * @param data  新data
    4 t- ]8 z+ ]0 u' d     * @return 旧data
    ) d. O% D  W4 d. n' x     */$ j, m* m& p4 @7 N
        public int set(int index, int data) {% t8 y. R) H! u; x" \2 X; h
            Node x = get(index);: X8 r8 C: ]- U  V& @% E, t8 R
            int oldVal = x.data;
    ; d* v! ?8 l; b! Q5 b8 S' w) g4 c( B        x.data = data;
    3 W" |4 p  J+ o! J        return oldVal;
    8 s7 T1 W& g5 e# {9 ^$ h    }+ k6 i) N# i+ Z' J3 ~' N
    1 |+ t& m1 \  G
    3. 插入节点

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

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

    • 尾部插入
    • 头部插入
    • 中间插入! N- g6 x) L: h/ _& T2 }8 h; W% S' n; \
    3.1. 尾部插入

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


    / {0 k2 d& w% ~( Y1 O+ S- j9 \ 6.png - n, {- D: h+ v: A9 W4 D$ V5 ?( ~
    3.2. 头部插入

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

    • 第1步,把新节点的next指针指向原先的头节点。
    • 第2步,把新节点变为链表的头节点。0 a  m( V; {9 @% y. z+ R
    7.png
    4 V7 ]4 E  L$ P( C9 |: B; W. J/ ^  ?$ f- t7 H
    3.3. 中间插入

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

    • 第1步,新节点的next指针,指向插入位置的节点。
    • 第2步,插入位置前置节点的next指针,指向新节点。
      ; B' S2 R3 S+ R4 _* U- W8 F/ Y4 f
    8.png : R7 K/ s% c6 g) ]

    . s# K. j' c0 e5 C三钟情况的代码合到一起$ g! Q& b9 P+ z4 x( Z% Z) `

    : ~8 ^, H6 o1 A4 V4 B/*** ]+ [$ _; L6 w2 M1 j
         * 链表插入元素. o$ h# ]' H3 K* u, |" s% \6 l
         *# n1 w) E" r; W7 ]0 h, V8 S8 E
         * @param index 插入位置
    : C3 v" K. j/ D* G     * @param data  插入元素 被插入的链表节点的数据- a- `. @" w- T7 P/ V* J
         */
    . Z$ Z) B# V' n8 Q. w& I' t& H3 S    public void insert(int index, int data) {
    $ Z6 ^* |5 i- f6 z/ f+ j        if (index < 0 || index > size) {7 E0 E5 m0 j6 P) X5 O
                throw new IndexOutOfBoundsException("超出链表节点范围!");' \7 q8 \. `3 }* M0 C5 u
            }
    8 f" e& I7 b4 N, O$ c7 y        Node insertedNode = new Node(data);! J9 q7 h" |, m2 j; Z
            if (size == 0) {9 S# ^9 }9 q* ]6 v# P( q3 a
                //空链表
    / E6 q, T/ }* P  C& m( N6 [            head = insertedNode;
    ! b% m0 A: n7 g5 e, ~9 m# w            last = insertedNode;; v5 v2 y7 N9 n7 q. B$ k1 y
            } else if (index == 0) {
    ' q0 G3 G' N5 a0 ~' V. Y! g4 g$ w            //插入头部4 q& t# x+ m2 z& v
                insertedNode.next = head;
    , B; t2 X4 v. P- s0 H            head = insertedNode;+ E7 D; O1 ]( T8 ~
            } else if (size == index) {
    6 e2 u+ l  k& J            //插入尾部% u( h0 m% d) h9 {! a' D" l, a
                last.next = insertedNode;1 Y& |+ ~/ V; ^$ Y. R: E
                last = insertedNode;
    & y0 [! K7 f/ a# |        } else {
    ' x: I1 f5 C# \, b( r6 P. m% D            //插入中间
    2 ?% G6 H. r2 |8 X            Node prvNode = get(index - 1);3 `! D" e3 v. Y
                insertedNode.next = prvNode.next;1 r! ?- E# @- R" _5 a' M, [
                prvNode.next = insertedNode;/ F9 S3 s" E0 }1 R& w: P# z; z
            }: b3 X" R0 ]  \) J! Z1 X
            size++;6 m: O' c+ B8 S3 z! a# M" Y' p" \
        }
    $ T% s8 i6 `3 s& o/ W6 n4 {9 v
    3 C7 @6 i/ N2 o. c% p8 s/**
    * m/ `: b) U$ u5 r8 @' a9 ]     * 链表插入元素
      t6 t6 l1 `' g+ j     *
    * s) l: i$ S; Z" K7 i: s3 W     * @param index 插入位置6 L, J$ w/ h  N
         * @param data  插入元素 被插入的链表节点的数据5 }' ~' F' G- p; X: E
         */
    9 R' C# `7 `# d# b; O' C( P0 q' e    public void insert(int index, int data) {( V+ q' d4 @$ |& t0 a9 @
            if (index < 0 || index > size) {6 ?6 R* P% ]3 S% [' y
                throw new IndexOutOfBoundsException("超出链表节点范围!");3 r/ o9 p7 \7 w) @
            }- d) l9 N( D: x* j. p
            Node insertedNode = new Node(data);9 V# X, x: {7 ?0 B/ i
            if (size == 0) {
    9 e1 \  {3 a8 t2 Z/ Q- k5 k6 |            //空链表
    * f: p, M+ }2 a- v1 O            head = insertedNode;3 ^) Q3 d/ S2 k) |: b/ n
                last = insertedNode;
    3 e* _2 L8 H' z# x        } else if (index == 0) {
    & _) ?1 i  ]( \8 X" y5 i! z. A            //插入头部5 V9 r8 n) h% Z, f0 W7 H* U% E
                insertedNode.next = head;
    ! j1 v. J  O6 u, |            head = insertedNode;
    % Q4 q$ N9 a. ?( q1 M5 h        } else if (size == index) {; g3 s0 I( `) ~( z$ W1 a
                //插入尾部
    5 a( e8 Y1 n- k. \& j            last.next = insertedNode;
    ) H; d( z$ I- V0 V& I6 Y/ e            last = insertedNode;
    ' W6 v0 g6 [) Q% R; M        } else {
    # C/ o. T+ h7 ~+ k4 p            //插入中间" L5 L  I  r# c  _+ c% f
                Node prvNode = get(index - 1);
    * P: u9 v" S$ n" _7 q8 }            insertedNode.next = prvNode.next;7 o) d2 g3 H4 r' N7 p9 m1 Y
                prvNode.next = insertedNode;8 m8 Q( f4 I8 |3 \
            }7 u( S0 {3 H* b6 R
            size++;' Y/ f/ ]6 z: Q' @% j% \6 w3 j& R
        }( }5 ^; {/ ]( z* u7 O
    4. 删除元素

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

    • 尾部删除
    • 头部删除
    • 中间删除
      ) S# \5 s: Q& z! ]
    4.1. 尾部删除

    尾部删除,是最简单的情况,把倒数第2个节点的next指针指向空即- i4 A3 q4 k8 G, W0 E) C% `& |: g- I
    可。

    9.png
    9 k4 }8 C9 n% ?- L+ H7 j* ]# I
    : K; v7 V) \7 f7 X* D# u. r5 Q4.1. 头部删除

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

    10.png
    1 D3 f, H  `& ]9 R' L# l
    7 ?. o* V" W: {/ g$ h4.1. 中间删除

    中间删除,同样很简单,把要删除节点的前置节点的next指针,指向要
    , R; ^6 @8 X1 n+ M: ~" Z删除元素的下一个节点即可。

    11.png
      J' {& [& |* L, h" T$ ^; `9 }, i0 e
    7 W6 ]2 \, q) j; H# b. _4 q! Q' E' n8 k3 [9 P- C/ g' |
    这里需要注意的是,许多高级语言,如Java,拥有自动化的垃圾回收机制,所以我们不用刻意去释放被删除的节点,只要没有外部引用指向它们,被删除的节点会被自动回收。3 t9 {! @8 h2 g0 j3 g
    如果不考虑插入、删除操作之前查找元素的过程,只考虑纯粹的插入和删除操作,时间复杂度都是O(1)  P: |7 T* y; U0 O
    /**
    : T) o' \6 }; i  H3 y     * 链表删除元素
    8 l; ?; u/ u4 P- q2 x# b; |     *
    + q& A  p, v# i" t9 F( G/ l) g     * @param index 删除的位置/ q- v* X. {, s7 k4 t7 f
         * @return 被删除的节点
    8 l+ T. Z' v. [- Y: |     */
    : D; _0 N+ U& O- T0 q4 X    public Node remove(int index) {9 z4 ]6 R( l; e5 u( Y/ A8 I" ?4 b3 I
            if (index < 0 || index > size) {2 B  e# L2 G% {- Q
                throw new IndexOutOfBoundsException("超出链表节点范围");1 F0 c( J+ D9 x
            }" a# E7 u7 K; h* \
            Node removeNode;
    3 e& |% w5 ^' F1 A5 u* Q        if (index == 0) {$ I2 V2 e2 J8 k1 B6 `1 q- w
                if (size == 0) {5 W, h+ Z( S( o! d) B8 f2 D2 r
                    throw new NullPointerException("当前链表为空,不可以进行删除操作");
    # W7 w' Y" r4 [! W. R& P            }
    6 e5 X* o8 c, ]            //删除头节点, ]3 {" Y2 p: G9 O3 ]4 \- {
                removeNode = head;4 s$ B, S/ v: h3 h
                head = head.next;
    , |2 {; s4 [; n; `; k/ a, P" n; x        } else if (index == size - 1) {6 s( i- @/ M1 T3 k) q6 e
                //删除尾节点
    " l: x& [3 {( Y2 d  Z8 a            Node preNode = get(index - 1);' L3 h- k# H; X* x
                removeNode = preNode.next;
    5 M4 H" [( N+ z8 S$ @7 A5 s            preNode.next = null;
    3 l, ~1 U+ A! m) d            last = preNode;
    ' j. N7 B, Q& ?        } else {
    # k0 x# r. F* W& h4 K- g8 `            //删除中间节点
    7 p2 f- \3 Z& ?0 R            Node prevNode = get(index - 1);/ r/ X' X8 V; n3 ~" q( e3 @; {
                removeNode = prevNode.next;$ J/ t  B2 ?3 p7 e9 ~0 X) E
                prevNode.next = prevNode.next.next;8 i' i2 u4 S( e( }0 b. ~
            }5 M( _1 q5 R+ k) C+ Q) h
            size--;
    # `- ?2 G# N# ~1 k! @6 b        return removeNode;
    2 D8 `% p  U8 o' ]! f2 P    }5 }2 i! v9 C' [. t  ^7 ]* ^
    Java实现链表的完整代码package chapter2.part2;/ y: o( h; v7 u* K; s9 ^
    ; _3 C# [; D* e* d/ M+ F) p2 _' z" g! q
    /*** c5 `; @4 |5 T$ ]- h
    * Created by IntelliJ IDEA.
    9 w! s( `) e+ y* o2 k4 z *
    1 F9 e: D# J- Z  Z5 @5 O * @Author: 张志浩  Zhang Zhihao
    " j+ f: z) |# P# r * @Email: 3382885270@qq.com
      m/ E2 [: v$ s6 O * @Date: 2020/5/3, R1 N2 `! g6 ?' d
    * @Time: 13:394 _+ Y- E% G4 B
    * @Version: 1.0; l7 }; x) U6 c) D
    */( Y0 w7 Y+ M) c* C5 G" [
    public class MyLinkedList2 {& H' |" Z; F; b& X
        private Node head; //头节点
    " ~. _* R* _; Z# E3 z7 ?$ o; O    private Node last; //尾节点
    ; W! L& f8 {. c0 p3 S    private int size; //链表实际长度
    7 [) i% ?7 \$ E" _1 \- y
    ; g$ h- C4 p2 l    public static void main(String[] args) {
    # l& ?% d. l9 G- z        MyLinkedList2 myLinkedList = new MyLinkedList2();- a5 t2 x1 u, y
    //        myLinkedList.remove(0); // java.lang.NullPointerException: 当前链表为空,不可以进行删除操作* U5 ~1 a. u& j$ n- Z
    //        myLinkedList.remove(3); // java.lang.IndexOutOfBoundsException: 超出链表节点范围
    , q2 X: F# D, ?# k$ V3 z        myLinkedList.insert(0, 3);
    ! {; L0 i8 Q% A! H! W) r        myLinkedList.insert(1, 7);
    1 F6 m( s  _1 a" Z; N. i        myLinkedList.insert(2, 9);" J5 R) X5 @0 q2 a. K, X' W
            myLinkedList.insert(3, 5);
    $ V9 ^0 s# N6 `6 H' }) }  `        myLinkedList.insert(1, 6);
    5 ]3 z. @) @9 p$ n0 K8 {! C        myLinkedList.remove(0);
    ! Y: k% M( Y5 W0 B        myLinkedList.set(0, 23);/ D9 K% j/ o  B' _& v1 W: P8 L+ o
            myLinkedList.output();
    2 ~5 j9 W5 Z6 ^) l% l    }  Y8 d. |7 B& z
    4 Z8 ]- X" f7 g9 @/ o2 F
        /**6 S9 _7 x0 c# A3 X
         * 链表插入元素
    ' S$ Z& k9 y7 W     *3 B% u. @) U( J' l+ }! V  {! m- u
         * @param index 插入位置4 D" y* m6 U) u. ?) D; }4 o5 i
         * @param data  插入元素 被插入的链表节点的数据
    + G9 b, W9 S8 l; |' Z7 m     */
      G1 w! a& E$ U9 A6 U+ W    public void insert(int index, int data) {
    ( U! l; g2 m: i; d8 W& W        if (index < 0 || index > size) {
    0 M9 Y+ I1 G3 ?- z( w1 }            throw new IndexOutOfBoundsException("超出链表节点范围!");
    ! D; e2 g( E/ l        }
    $ \; l# Y% G5 K( D# S        Node insertedNode = new Node(data);
    : A2 T' @+ q. S& |7 }5 T' u! Y        if (size == 0) {/ v' d! ~$ A% p: p$ o! [2 S7 V
                //空链表
    $ }9 h0 w; @8 E4 n            head = insertedNode;4 M- ^5 |# e9 p/ k; g, w1 q" p& \
                last = insertedNode;0 \1 I- T# E$ m: @. d- U. X
            } else if (index == 0) {+ W$ a; X! s; B& D) o+ @- A; [
                //插入头部
    , s  u& w* N! I% A! w5 E7 }            insertedNode.next = head;
    ! x" l2 [- ~7 t% G            head = insertedNode;
    ) ^7 K( w1 D1 p7 D- {        } else if (size == index) {% ^) W# M( U, c9 i) ~
                //插入尾部
    0 J  o) p- O2 g& E: [            last.next = insertedNode;2 v1 _: Y" O" q' k' \9 s: h; R
                last = insertedNode;
    # |/ g0 K/ ^% y6 ?5 C        } else {" F* w  a$ u2 M. A* d$ `& |, e4 i
                //插入中间4 k  Q% {4 _! J- l
                Node prvNode = get(index - 1);
    * v$ C+ F( O& i& j3 q; }1 b  K            insertedNode.next = prvNode.next;- b* @  F4 S- g/ w% {
                prvNode.next = insertedNode;
    8 b# x+ O( s% Z/ g5 G6 \        }
    ' ]: z, g6 n, |% H2 t/ D        size++;
    2 C! C/ u$ m8 l, ]  u' p    }( \; `! R2 G+ n9 a% p9 ~

    # c2 q  n0 {; r+ o- O) |) W    /**" {) W+ p( e0 P: f7 D, s4 b  s
         * 链表删除元素
    $ p' \4 ^" }7 s8 ~0 i' x     *
    ) N( p& d5 A  T     * @param index 删除的位置
    ; i. s; e9 K+ w" i     * @return 被删除的节点2 J" V( G! Z. Z/ r2 n4 t9 f
         */* b* K: `+ Q* W1 g7 W
        public Node remove(int index) {$ S! x0 V0 H' ]+ V8 I- m3 @9 H
            if (index < 0 || index > size) {& b$ F3 v  P  C8 p' ?) W
                throw new IndexOutOfBoundsException("超出链表节点范围");' J0 {' c& W% e: s4 j
            }% D& m* a$ u# r
            Node removeNode;
    * o( d% R' B+ T& j( s, \2 g3 a        if (index == 0) {6 L. Q$ _. l' ^- A0 M
                if (size == 0) {8 [: O6 h) o0 X0 B+ O" G1 h. b
                    throw new NullPointerException("当前链表为空,不可以进行删除操作");7 S9 R* i. Z9 T! G5 O  q) b
                }
    ) |) G0 u4 J. ?- i: H! k            //删除头节点6 A3 x) U2 F% G& ~- H. {, f
                removeNode = head;1 e' k0 t+ S5 b0 ^' U
                head = head.next;% m8 x& i- G9 |3 a3 H7 A4 x
            } else if (index == size - 1) {
    5 E* [" p' S* p: F) Y6 X            //删除尾节点, H) c3 ]( O- x# a
                Node preNode = get(index - 1);
    3 {( b% G: G8 M            removeNode = preNode.next;
    + F/ q4 g# S! X; h            preNode.next = null;
    2 m6 h/ [" J/ I6 @3 z$ X' Z            last = preNode;
    9 _2 J' d* e& T6 B1 C! h        } else {
    ( T( g7 V' n4 U4 |/ T* m            //删除中间节点- W+ m9 O& o" n  o4 o- |, m/ Y
                Node prevNode = get(index - 1);
    5 q# @! `' Y, ~5 n. d, c9 a  G            removeNode = prevNode.next;: b7 h+ l; H( R4 \7 l7 }
                prevNode.next = prevNode.next.next;
    9 ^% o' |7 A; |7 c) e% J, c        }
    8 d; Z; A$ ]/ s; \, n: l: d/ }        size--;; H6 L+ ?4 N( A/ a- ?4 Z
            return removeNode;; n8 N( X& g$ t: _8 m! n
        }
    ; _8 {: @2 o! G4 y
    $ O4 L2 m/ I% `: R5 G  j    /**+ r$ H: Z* T  g7 p" W! t- l
         * 更新节点 将列表中指定位置的节点的data替换为指定的data。
    $ F# N2 R! z8 l" i6 d9 p% o- j# J     */ B4 g# ?! {, p  J+ s
         * @param index 需要更新的节点的位置7 H$ V8 o+ K2 C1 ]% e( ?5 Y
         * @param data  新data6 A' \7 J9 M( _$ X9 ^/ H- i( H+ X
         * @return 旧data
    ; a& T  v; }8 [8 Y/ L- n  [1 C     */- N) g$ U( [) L. t5 h  y" [
        public int set(int index, int data) {
    8 i' M( e. i4 E$ A2 C6 w        Node x = get(index);" X* v# P. D, J# P, L7 c
            int oldVal = x.data;! x0 @, N9 V7 p! a' q2 E
            x.data = data;. u- C/ b+ W' ~, [
            return oldVal;+ R% m( e, P  k) Z0 X  E
        }4 p+ E) J4 n# |  ^, `) ]/ `

    4 U/ E  A& N6 @    /**
    3 M5 b5 r+ m+ ], ^     * 链表查找元素
    . p) }: z2 w0 W5 l, ?     *
    8 t) P4 }1 y; [$ h% n  `2 G9 K2 V     * @param index 查找的位置
    ; I+ i- I% @3 M     * @return index位置的Node对象% o$ f/ l& O7 N$ R
         */4 \0 D" G# \7 M2 a' [9 e
        public Node get(int index) {
    ( c! u/ w4 e8 j2 z/ x        if (index < 0 || index > size) {4 y! Y% |# ]8 t0 R% f5 u
                throw new IndexOutOfBoundsException("超出链表的节点的范围!");; q4 P% s) O$ N# u2 Z
            }
    8 G; b4 A* x/ N7 `5 c1 n8 W        Node temp = head;' a* W8 z2 h4 F5 l' i# |& K4 H4 A6 s
            for (int i = 0; i < index; i++) {$ t9 @% F& M, @! d5 k% ~8 [( G
                temp = temp.next;0 b9 J  p" a7 j: p) I
            }
    - J/ D0 I2 N; \" N* A" s/ |, X2 n- j6 c        return temp;
    # N! p9 z6 i  z, {: `7 H    }
    ( P3 [& ]: \6 A3 q; ~* s: }7 b% W- q) _2 `- \/ M8 q# I
        /**
    $ F/ F% ?/ A* q4 Q+ ]8 w. K     * 输出链表. i5 \& P. t* a4 b; T& ?% s
         */
    8 @$ ?$ D9 ^! {) }, S    public void output() {
    & z* _- {) o$ P' C5 _+ `2 m        Node temp = head;/ {+ x/ U+ C0 ?* {7 W! Y
            while (temp != null) {
    : |6 G( W  \, V: g            System.out.print(temp.data + " ");% m1 p# |( j- b# K3 A7 W, k
                temp = temp.next;
    : s5 D. U" P5 h5 i! \        }3 E/ |5 f2 y+ E5 O- z9 K
        }  L  |1 P' g$ x1 Q. T: O5 V5 y. @) D0 t

    1 W" |5 [2 F- N6 X    /**
    ' p6 i# ^2 o' S+ T+ L; q     * 链表节点
    8 w0 H4 l( T3 H$ w     */
    . r4 S$ D3 V( U" p6 b9 V5 F    class Node {$ f) ^% s0 `; f* k0 |; O2 t6 q2 ~
            int data;: S. B) X9 [. |- Y* |# }+ t
            Node next;% t  E( q; p5 P0 X7 K
    ! l$ @3 h7 D5 d. _: d
            Node(int data) {
    2 f3 ]& C) v$ k% p8 Q. F- n            this.data = data;
    ) I- e7 ^7 u% A: `# S' T+ u        }
    ' j1 c7 i+ s6 G2 b. ?% g    }
    ( A' v/ \  `4 L( H0 Q% j( ]1 c; c0 C}
    ! q7 o  r  i. I  P6 ]
    ! W6 h, I1 I9 Y$ k- @& q1 w- Y7 x- X8 j! ~, y' W- z! w% I
    二、双向链表 12.png 3 T0 {% G" ?& y& @
    双向链表比单向链表稍微复杂一些,它的每一个节点除了拥有data和next指针,还拥有指向前置节点的prev 指针。
    8 T2 A/ z4 H' t8 m. Q
    ! P1 K' s+ A/ o0 V: {. k. |/ k2 h, W# F# k7 j5 u- m

    $ h( P5 P; b( [4 @# ?' c/ i/ \6 D3 I! w5 k- [# ^- z
    ————————————————
    / Z" V; ^4 u2 k) F5 a2 L5 v! C版权声明:本文为CSDN博主「爱做梦的鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    4 r1 }0 u- L/ W2 @3 G5 `8 G- Y; c/ |原文链接:https://blog.csdn.net/weixin_43124279/article/details/105904468# u" X* W; E: `# s7 X! x4 ^
    / [7 G5 u( `7 u8 e

    2 O0 Z( E7 ?" A+ [* ^

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

    2.png

    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-8-1 11:38 , Processed in 0.593800 second(s), 54 queries .

    回顶部