链表(Linked List)介绍
链表是有序的列表,但是它在内存中是存储如下:
小结:
- 链表是以节点的方式来存储,是链式存储。
- 每个节点包含 data域 , next域 : 指向下一个节点。
- 如图:发现链表的各个节点不一定是连续存储。
- 链表分带头节点的链表 和 没有带头节点的链表,根据实际的需求来确定。
单链表介绍
单链表(带头节点)逻辑结构示意图如下:
- 单链表的应用实例
使用带head头的单向链表实现—水浒英雄排行榜管理完成对英雄人物的增删改查操作。
1)第一种方法在添加英雄时,直接添加到链表的尾部
思路分析示意图:
2)第二种方法在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
思路分析示意图:
3)修改节点的功能
思路:
①先找到该节点,通过遍历
②temp.name = newHeroNode.name; temp.nickname = newHeroNode.nickname;
4)删除节点
思路分析示意图:
5)完整代码实现
1 package com.jyj.linkedList; 2 3 public class SingleLinkedListDemo { 4 public static void main(String[] args) { 5 //测试 6 //先创建节点 7 HeroNode hero1 = new HeroNode(1,"宋江","及时雨"); 8 HeroNode hero2 = new HeroNode(2,"卢俊义","玉麒麟"); 9 HeroNode hero3 = new HeroNode(3,"吴用","智多星"); 10 HeroNode hero4 = new HeroNode(4,"林冲","豹子头"); 11 12 //创建链表 13 SingleLinkedList singleLinkedList = new SingleLinkedList(); 14 //加入 15 // singleLinkedList.add(hero1); 16 // singleLinkedList.add(hero4); 17 // singleLinkedList.add(hero2); 18 // singleLinkedList.add(hero3); 19 20 //加入 21 singleLinkedList.addByOrder(hero1); 22 singleLinkedList.addByOrder(hero4); 23 singleLinkedList.addByOrder(hero2); 24 singleLinkedList.addByOrder(hero3); 25 26 //显示 27 singleLinkedList.list(); 28 29 singleLinkedList.update(new HeroNode(2,"小卢","玉麒麟~~~")); 30 31 System.out.println("修正后:"); 32 //显示 33 singleLinkedList.list(); 34 35 singleLinkedList.del(1); 36 singleLinkedList.del(4); 37 System.out.println("删除后:"); 38 //显示 39 singleLinkedList.list(); 40 41 } 42 } 43 44 //定义SingleLinkedList 管理英雄 45 class SingleLinkedList { 46 //先初始化一个头节点,头节点不要动,不存放具体的数据 47 private HeroNode head = new HeroNode(0,"",""); 48 49 //添加节点到单向链表 50 //思路:当不考虑编号的顺序时 51 //1.找到当前链表的最后节点 52 //2.将最后这个节点的next 指向 新的节点 53 public void add(HeroNode heroNode) { 54 //因为head节点不能动,因此我们需要一个辅助节点 temp 55 HeroNode temp = head; 56 //遍历链表,找到最后 57 while(true) { 58 //找到链表的最后 59 if(temp.next == null) { 60 break; 61 } 62 //如果没有找到最后,就将temp后移 63 temp = temp.next; 64 } 65 //当退出while循环时,temp就指向了链表的最后 66 //将最后这个节点的next 指向 新的节点 67 temp.next = heroNode; 68 } 69 70 //添加英雄时,根据排名将英雄插入到指定位置 71 //(如果有这个排名,则添加失败,并给出提示) 72 public void addByOrder(HeroNode heroNode) { 73 //因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助我们找到添加的位置, 74 //因为单链表,我们找到的temp是位于 添加位置的第一个节点,否则插入不了 75 HeroNode temp = head; 76 boolean flag = false; //flag标志添加的编号是否存在,默认为false 77 while(true) { 78 if(temp.next == null) { //说明temp已经在链表的最后 79 break; 80 } 81 if(temp.next.no > heroNode.no) { //位置找到,就在temp的后面插入 82 break; 83 }else if(temp.next.no == heroNode.no) { //说明将要添加的heroNode的编号已经存在 84 flag = true; //说明编号存在 85 break; 86 } 87 //后移,遍历当前链表 88 temp = temp.next; 89 } 90 91 if(flag) { 92 System.out.printf("编号 %d 已经存在,不能再添加~ ",heroNode.no); 93 }else { 94 //插入到链表中,temp的后面 95 heroNode.next = temp.next; 96 temp.next = heroNode; 97 } 98 } 99 100 //修改节点的信息,根据no编号来修改,即no编号不能改 101 public void update(HeroNode newHeroNode) { 102 //判空 103 if(head.next == null) { 104 System.out.println("链表为空"); 105 return; 106 } 107 //找到需要修改的节点,根据no编号 108 //定义一个辅助变量 109 HeroNode temp = head.next; 110 boolean flag = false; //表示是否找到该节点 111 while(true) { 112 if(temp == null) { 113 break; //已经遍历完链表 114 } 115 if(temp.no == newHeroNode.no) { 116 //找到 117 flag = true; 118 break; 119 } 120 temp = temp.next; 121 } 122 //根据flag 判断是否找到要修改的节点 123 if(flag) { 124 temp.name = newHeroNode.name; 125 temp.nickname = newHeroNode.nickname; 126 }else { //没有找到 127 System.out.printf("编号 %d 不存在,不能修改~",newHeroNode.no); 128 } 129 } 130 131 //删除链表 132 //思路 133 //1.head 不能动,因此我们需要一个temp辅助节点找到待删除节点的前一个节点 134 //2.说明我们在比较时,是 temp.next.no 和 需要删除的节点的no 比较 135 public void del(int no) { 136 //辅助链表 137 HeroNode temp = head; 138 boolean flag = false; //标志是否找到待删除的节点 139 140 while(true) { 141 if(temp.next == null) { //已经到链表最后 142 break; 143 } 144 if(temp.next.no == no) { 145 //找到待删除节点的前一个节点temp 146 flag = true; 147 break; 148 } 149 temp = temp.next; //后移 150 } 151 152 if(flag) { 153 //删除节点 154 temp.next = temp.next.next; 155 }else { 156 System.out.printf("要删除的 %d 节点不存在 ",no); 157 } 158 } 159 160 //显示链表[遍历] 161 public void list(){ 162 //判断链表是否为空 163 if(head.next == null) { 164 System.out.println("链表为空"); 165 return; 166 } 167 //因为头节点不能动,因此需要辅助变量来遍历 168 HeroNode temp = head.next; 169 while(true) { 170 //判断是否到链表最后:注意是temp == null,不是temp.next == null 171 if(temp == null) { 172 break; 173 } 174 //输出节点的信息 175 System.out.println(temp); 176 //将temp 后移,不然就是死循环 177 temp = temp.next; 178 } 179 } 180 } 181 182 //定义HeroNode,每个HeroNode 对象就是一个节点 183 class HeroNode { 184 public int no; 185 public String name; 186 public String nickname; 187 public HeroNode next; //指向下一个节点 188 189 //构造器 190 public HeroNode(int no,String name,String nickname) { 191 this.no = no; 192 this.name = name; 193 this.nickname = nickname; 194 } 195 196 //为了显示方便,重写toString 197 @Override 198 public String toString() { 199 return "HeroNode [no=" + no + ", name=" + name + ", nickname=" 200 + nickname + "]"; 201 } 202 }
以上