1. 链表(Linked List)介绍
链表是有序的列表,它在内存中的存储结构如下:

1)链表是以节点的方式来存储,是链式存储。
2)每个节点包含data域,next域:指向下一个节点。
3)链表的各个节点不一定是连续存储。
4)链表分带头节点的链表和不带头节点的链表,根据实际的需求来确定。

2. 单链表的增删改查
【注】下面的所有单链表操作均是使用带 head 头的单向链表实现 - 实现对水浒英雄排行榜管理,完成对英雄人物的增删改查。
2.1 链表添加操作
2.1.1 直接添加到链表的尾部(不需要对编号排序)
思路分析:

代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| package com.self.linkedlist;
public class SingleLinkedListAdd {
public static void main(String[] args) { HeroNodeAdd hero1 = new HeroNodeAdd(1, "宋江", "及时雨"); HeroNodeAdd hero2 = new HeroNodeAdd(2, "卢俊义", "玉麒麟"); HeroNodeAdd hero3 = new HeroNodeAdd(3, "吴用", "智多星"); HeroNodeAdd hero4 = new HeroNodeAdd(4, "林冲", "豹子头");
SingleLinkedList_add singleLinkedList = new SingleLinkedList_add(); singleLinkedList.add(hero1); singleLinkedList.add(hero2); singleLinkedList.add(hero3); singleLinkedList.add(hero4);
singleLinkedList.showLinkedList();
} }
class SingleLinkedList_add{
private HeroNodeAdd head = new HeroNodeAdd(0,"","");
public void add(HeroNodeAdd heroNodeAdd){
HeroNodeAdd temp = head; while (true){ if(temp.next == null){ break; } temp = temp.next; } temp.next = heroNodeAdd; }
public void showLinkedList(){ if(head.next == null){ System.out.println("链表为空~"); return ; } HeroNodeAdd temp = head.next; while (true){ if(temp == null){ break; } System.out.println(temp); temp = temp.next; } } }
class HeroNodeAdd{
public int no; public String name; public String nickname; public HeroNodeAdd next;
public HeroNodeAdd(int no, String name, String nickname) { this.no = no; this.name = name; this.nickname = nickname; }
@Override public String toString() { return "HeroNodeAdd{" + "no='" + no + '\'' + ", name='" + name + '\'' + ", nickname='" + nickname + '\'' + '}'; } }
|
效果截图:

2.1.2 根据编号添加到指定位置
思路分析:

代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| package com.self.linkedlist;
public class SingleLinkedListAddOrder {
public static void main(String[] args) {
HeroNodeAddOrder hero1 = new HeroNodeAddOrder(1, "宋江", "及时雨"); HeroNodeAddOrder hero2 = new HeroNodeAddOrder(2, "卢俊义", "玉麒麟"); HeroNodeAddOrder hero3 = new HeroNodeAddOrder(3, "吴用", "智多星"); HeroNodeAddOrder hero4 = new HeroNodeAddOrder(4, "林冲", "豹子头");
SingleLinkedList_addOrder singleLinkedList = new SingleLinkedList_addOrder(); singleLinkedList.addByOrder(hero1); singleLinkedList.addByOrder(hero3); singleLinkedList.addByOrder(hero4); singleLinkedList.addByOrder(hero2);
singleLinkedList.showLinkedList();
} }
class SingleLinkedList_addOrder{
private HeroNodeAddOrder head = new HeroNodeAddOrder(0,"","");
public void addByOrder(HeroNodeAddOrder heroNodeAddOrder){ HeroNodeAddOrder temp = head; boolean flag = false; while (true){ if (temp.next == null){ break; } if(temp.next.no > heroNodeAddOrder.no){ break; }else if (temp.next.no == heroNodeAddOrder.no){ flag = true; break; } temp = temp.next; } if(flag){ System.out.printf("准备插入的英雄的编号 %d 已经存在,不能再次添加\n",heroNodeAddOrder.no); }else { heroNodeAddOrder.next = temp.next; temp.next = heroNodeAddOrder; } }
public void showLinkedList(){ if(head.next == null){ System.out.println("链表为空~"); return ; } HeroNodeAddOrder temp = head.next; while (true){ if(temp == null){ break; } System.out.println(temp); temp = temp.next; } } }
class HeroNodeAddOrder{
public int no; public String name; public String nickname; public HeroNodeAddOrder next;
public HeroNodeAddOrder(int no, String name, String nickname) { this.no = no; this.name = name; this.nickname = nickname; }
@Override public String toString() { return "HeroNodeAddOrder{" + "no=" + no + ", name='" + name + '\'' + ", nickname='" + nickname + '\'' + '}'; } }
|
效果截图:

2.2 链表修改操作
思路分析:
通过遍历找到需要修改的节点
temp.name = heroNodeUpdate.name;temp.nickname = heroNodeUpdate.nickname;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
| 代码实现:
```java package com.self.linkedlist;
public class SingleLinkedListUpdate {
public static void main(String[] args) { //进行测试 //创建节点 HeroNodeUpdate hero1 = new HeroNodeUpdate(1, "宋江", "及时雨"); HeroNodeUpdate hero2 = new HeroNodeUpdate(2, "卢俊义", "玉麒麟"); HeroNodeUpdate hero3 = new HeroNodeUpdate(3, "吴用", "智多星"); HeroNodeUpdate hero4 = new HeroNodeUpdate(4, "林冲", "豹子头");
//创建链表 SingleLinkedList_update singleLinkedList = new SingleLinkedList_update(); //将节点加入 singleLinkedList.add(hero1); singleLinkedList.add(hero2); singleLinkedList.add(hero3); singleLinkedList.add(hero4);
//测试修改节点信息 System.out.println("修改前:"); singleLinkedList.showLinkedList();
HeroNodeUpdate newHeroNode = new HeroNodeUpdate(2, "小卢", "玉麒麟~~"); singleLinkedList.update(newHeroNode);
System.out.println("修改后:"); singleLinkedList.showLinkedList(); } }
//定义SingleLinkedList 管理我们的英雄 class SingleLinkedList_update{
//初始化头结点,一般头结点不能更改,要不然之后的节点数据将找不到 private HeroNodeUpdate head = new HeroNodeUpdate(0,"","");
//添加节点到单向链表(找到链表的最后一个节点,让它指向新添加的节点,并将其next的null去掉) public void add(HeroNodeUpdate heroNodeUpdate){
//因为head节点不能动,因此我们需要一个辅助遍历变量 temp HeroNodeUpdate temp = head; //遍历链表,找到最后的节点 while (true){ //链表的最后一个节点 if(temp.next == null){ break; } //如果没有找到最后,就将temp后移 temp = temp.next; } //当退出了while循环时,temp就已经指向了链表的最后一个节点 //然后将最后这个的节点指向新添加的节点 temp.next = heroNodeUpdate; }
/** * 修改节点的信息,根据no编号进行修改,即no不能进行修改 * 说明: * 1.heroNode的no来修改即可 * @param heroNodeUpdate */ public void update(HeroNodeUpdate heroNodeUpdate){ if(head.next == null){ System.out.println("链表为空~"); } //找到需要修改的节点,根据no编号修改, //定义temp辅助变量, HeroNodeUpdate temp = head.next; boolean flag = false;//表示是否找到了该节点 while (true) { if (temp == null) {//已经遍历完这个链表了 break; } if (temp.no == heroNodeUpdate.no) { //找到需要修改的节点 flag = true; break; } //若没有找到,temp后移 temp = temp.next; } //根据flag判断是否找到了要修改的节点 if(flag){ temp.name = heroNodeUpdate.name; temp.nickname = heroNodeUpdate.nickname; }else {//没有找到 System.out.printf("没有找到编号为 %d 的节点编号,不能进行修改\n",heroNodeUpdate.no); } }
//显示链表【遍历】 public void showLinkedList(){ //判断链表是否为空 if(head.next == null){ System.out.println("链表为空~"); return ; } //因为head节点不能动,所以定义辅助变量进行遍历 //这里的 temp 表示链表的最后一个节点.next HeroNodeUpdate temp = head.next; while (true){ //判断是否到链表最后 if(temp == null){ break; } //输出节点的信息 System.out.println(temp); //将temp后移(输出一个节点信息后,temp后移才能输出下一个节点) temp = temp.next; } }
}
//定义一个HeroNode,每一个HeroNode对象就是一个节点 class HeroNodeUpdate {
public int no; public String name; public String nickname; public HeroNodeUpdate next;
//构造器 public HeroNodeUpdate(int no, String name, String nickname) { this.no = no; this.name = name; this.nickname = nickname; }
//toString @Override public String toString() { return "HeroNodeUpdate{" + "no=" + no + ", name='" + name + '\'' + ", nickname='" + nickname + '\'' + '}'; } }
|
效果截图:

2.3 链表删除操作
思路分析:

代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
| package com.self.linkedlist;
public class SingleLinkedListDel {
public static void main(String[] args) { HeroNodeDel hero1 = new HeroNodeDel(1, "宋江", "及时雨"); HeroNodeDel hero2 = new HeroNodeDel(2, "卢俊义", "玉麒麟"); HeroNodeDel hero3 = new HeroNodeDel(3, "吴用", "智多星"); HeroNodeDel hero4 = new HeroNodeDel(4, "林冲", "豹子头");
SingleLinkedList_del singleLinkedList = new SingleLinkedList_del(); singleLinkedList.add(hero1); singleLinkedList.add(hero2); singleLinkedList.add(hero3); singleLinkedList.add(hero4);
singleLinkedList.showLinkedList();
singleLinkedList.delete(1); System.out.println("删除后:"); singleLinkedList.showLinkedList(); } }
class SingleLinkedList_del{
private HeroNodeDel head = new HeroNodeDel(0,"","");
public void add(HeroNodeDel heroNodeDel){
HeroNodeDel temp = head; while (true){ if(temp.next == null){ break; } temp = temp.next; } temp.next = heroNodeDel; }
public void delete(int no){ HeroNodeDel temp = head; boolean flag = true; while (true){ if(temp.next == null){ break; } if(temp.next.no == no){ flag = true; break; } temp = temp.next; } if(flag){ temp.next = temp.next.next; }else { System.out.printf("要删除的 %d 节点不存在,无法删除",no); } }
public void showLinkedList(){ if(head.next == null){ System.out.println("链表为空~"); return ; } HeroNodeDel temp = head.next; while (true){ if(temp == null){ break; } System.out.println(temp); temp = temp.next; } }
}
class HeroNodeDel {
public int no; public String name; public String nickname; public HeroNodeDel next;
public HeroNodeDel(int no, String name, String nickname) { this.no = no; this.name = name; this.nickname = nickname; }
@Override public String toString() { return "HeroNodeDel{" + "no=" + no + ", name='" + name + '\'' + ", nickname='" + nickname + '\'' + '}'; } }
|
效果截图:

以上就是单链表实现增删改查的全部过程!!!