Java中的单向链表详解
作者:java-zh
这篇文章主要介绍了Java中的单向链表详解,单向链表又叫单链表,是链表的一种,由节点构成,head指针指向第一个称为表头节点,而终止指向最后一个null指针,需要的朋友可以参考下
概述
单线链表:单向链表又叫单链表,是链表的一种。由节点构成,head指针指向第一个称为表头节点,而终止指向最后一个null指针
特点
- 链表连接的方向都是单向的
- 链表的访问要通过顺序从头部开始
- 链表是使用指针进行构造的列表
- 是由一个一个节点组成的链表,又称为节点链表
- 每个节点都有指针成员变量指向链表中的下个节点
结构
可以比喻成火车,head是火车头data是火车厢,每一个火车厢的车厢next都拉着一个下一个车厢
优点
- 单个节点的创建非常方便(增)
- 节点的删除非常方便,不需要线性结构那样移动数据(删)
缺点
- 只能冲头到位遍历,只能后续,无法找到前驱,也就是只能前进
- 查询时搜索遍历需要遍历整个链表,在不好的情况下,可能需要道链尾才能找到
- 链表需要维护next域,暂用内存
案例
创建一个单向列表
public class Node { //存储节点的值 int val; //下一个节点地址 Node next; public Node(int val) { this.val = val; } public Node(int val, com.study.data.linked.Node next) { this.val = val; this.next = next; } }
测试
1、插头法,从头部上添加数据
输出结果:5->4->3->3->2->NULL
public class NodeTest { //实际存储的个数,相当于火车车厢的个数 private int size; //第一个节点,相当于火车头 private Node head; /** * 用来展示链表 * * @return */ public String showNode() { StringBuilder ret = new StringBuilder(); Node node = head; while (node != null) { ret.append(node.val).append("->"); // 继续访问下一节车厢 node = node.next; } ret.append("NULL"); return ret.toString(); } //在头部上增加链数据(插头罚),如果链表为空,那么就是增加火车头 public void addFirst(int data) { //要向链表中添加节点,要判断当前的链表是否为空,如果一个都没有,那么就要插入第一个节点 Node node = new Node(data); if (size == 0) { head = node; size++; } else { //当前的火车已经存在节点了 // 头部为上一个节点 node.next = head; head = node; size++; } } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); System.out.println(test.showNode()); } }
2、插尾法(从尾部开始插入数据)
输出结果:2->3->3->4->5->NULL
public class NodeTest { //实际存储的个数,相当于火车车厢的个数 private int size; //第一个节点,相当于火车头 private Node head; /** * 用来展示链表 * * @return */ public String showNode() { StringBuilder ret = new StringBuilder(); Node node = head; while (node != null) { ret.append(node.val).append("->"); // 继续访问下一节车厢 node = node.next; } ret.append("NULL"); return ret.toString(); } //插尾法,从尾部开始添加数据 public void addLast(int data) { //要向链表中添加节点,要判断当前的链表是否为空,如果一个都没有,那么就要插入第一个节点 Node node = new Node(data); if (size == 0) { head = node; size++; } else { //当前的火车已经存在节点了 Node last = head; while (last.next != null) { last = last.next; } // 头部为上一个节点 last.next = node; size++; } } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addLast(2); test.addLast(3); test.addLast(3); test.addLast(4); test.addLast(5); System.out.println(test.showNode()); } }
3、在链表的中间插入位置
输出结果:5->4->4->3->3->2->NULL
图片详解
代码实现
//在链表的中间插入位置 public void addIndex(int index, int data) { //判断边界条件,判断index的合法性 if (index < 0 || index > size) { System.out.println("插入链表位置失败...."); return; } if (index == 0) { // 从链表的头部开始插入 addFirst(data); return; } //说明此时index合法,并且时在中间这个位置,此时需要知道index的前驱节点,单链表只能从前往后遍历 //将要插入的链表值添加进去 Node node = new Node(data); //获取到整个链表值 Node result = head; for (int i = 0; i < index - 1; i++) { //移除大于index-1的头部数据 result = result.next; } //将上面尾巴数据赋值过去,要注意这里时next,所以实际上是head的next,比如4 0 1 ,next的话是0 1 //node的数据还是刚刚添加的数据,这个时候就会变成了data+result.next的数据 node.next = result.next; //将result中的next对node进行替换,上面的node已经完成了拼接 result.next = node; size++; } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); test.addIndex(2,4); System.out.println(test.showNode()); }
4、获取下标中的数据
输出结果:4
// 查询index节点上的数据 public int get(int index) { if (index < 0 || index >= size) { System.out.println("获取链表位置index值失败..."); return -1; } //获取到前一个节点 Node node = head; for (int i = 0; i < index; i++) { node = node.next; } return node.val; } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); System.out.println(test.showNode()); System.out.println("获取节点1的数据" + test.get(1)); }
5、对链表中某个值进行替换
输出结果:5->4->0->3->2->NULL
//对下标的某个值进行替换 public int set(int index, int data) { if (index < 0 || index >= size) { System.out.println("修改单链表中的数据失败"); return -1; } Node node = head; for (int i = 0; i < index; i++) { node = node.next; } //需要替换位置的值 int oldData = node.val; // 进行值替换 node.val = data; return oldData; } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); test.set(2,0); System.out.println(test.showNode()); }
6、判断链表是否包含某个值
输出:true
// 判断链表中是否包含元素data public boolean contains(int data) { Node node = head; while (node != null) { if (node.val == data) { System.out.println("找到了元素" + data); return true; } node = node.next; } System.out.println("没有找到元素" + data); return false; } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); System.out.println(test.contains(5)); System.out.println(test.showNode()); }
7、移除链表中第一个值
输出结果:4->3->3->2->NULL
//移除第一个值 public void removeFirst() { if (size == 0) { return; } Node node = head; head = node.next; node.next = null; size--; } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); test.removeFirst(); System.out.println(test.showNode()); }
8、通过下标移除对应的值
输出结果:5->4->3->2->NULL
//通过下标移除值 public void removeIndex(int index) { if (index < 0 || index > size) { System.out.println("通过下标移除失败,下标异常"); } if (index == 0) { removeFirst(); } else { Node node = head; for (int i = 0; i < index - 1; i++) { node = head.next; } // node是待删除的头部节点,del就是你要删除的节点 Node del = node.next; //将两个节点给连接起来 node.next = del.next; del.next = null; size--; } } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); test.removeIndex(2); System.out.println(test.showNode()); }
9、删除指定元素的第一个节点
输出:5->4->3->2->NULL
//删除指定元素的第一个节点 public void removeValueFirst(int data) { //先判断头节点情况,看看头节点是不是正好等于待删除节点 if (head.val == data) { removeFirst(); } else { //先找到待删除的节点 Node node = head; while (node.next != null) { //找到待删除节点,找到了以后可以直接删除 if (node.next.val == data) { Node del = node.next; node.next = del.next; del.next = null; size--; break; } else { node = node.next; } } } } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); test.removeValueFirst(3); System.out.println(test.showNode()); }
10、删除链表中的所有节点
输出结果:5->4->2->NULL
//删除链表中包含值的所有节点 public void removeValueAll(int data) { //判断头节点 while (head != null && head.val == data) { removeFirst(); } if (head == null) { System.out.println("当前节点已经为空了!"); return; } //头节点处理完毕,并且链表不等于空 Node node = head; while (node.next != null) { //12345 if (node.next.val == data) { Node del = node.next; node.next = del.next; del.next = null; size--; } else { node = node.next; } } } public static void main(String[] args) { NodeTest test = new NodeTest(); test.addFirst(2); test.addFirst(3); test.addFirst(3); test.addFirst(4); test.addFirst(5); test.removeValueAll(3); System.out.println(test.showNode()); }
到此这篇关于Java中的单向链表详解的文章就介绍到这了,更多相关Java单向链表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!