Java 数据结构与算法系列精讲之单向链表
概述
从今天开始, 小白我将带大家开启 Jave 数据结构 & 算法的新篇章.
链表
链表 (Linked List) 是一种递归的动态数据结构. 链表以线性表的形式, 在每一个节点存放下一个节点的指针. 链表解决了数组需要先知道数据大小的缺点, 增加了节点的指针域, 空间开销较大.
链表包括三类:
- 单向链表
- 双向链表
- 循环链表
单向链表
单向链表 (Single Linked List) 是链表中最简单的一种形式. 单向链表每个节点包含两个部分, 第一部分是信息, 第二部分是下一个节点. (元素 + 指针)
单向链表实现
Node 类
// Node类 private class Node { public E e; // 元素 private SingleLinkedList.Node next; // 下一个节点 // 构造 public Node(E e) { this.e = e; this.next = null; } @Override public String toString() { return e.toString(); } }
add 方法
// 添加数据 public void add(int index, E e) { // 检查索引是否越界 if (index < 0 || index > size) { throw new RuntimeException("Invalid Index"); } // 获取index前一个节点 SingleLinkedList.Node prev = dummyHead; for (int i = 0; i < index; i++) { prev = prev.next; } // 添加数据 SingleLinkedList.Node node = new SingleLinkedList.Node(e); node.next = prev.next; prev.next = node; size++; }
remove 方法
// 删除数据 public void remove(int index) { // 检查索引是否越界 if (index < 0 || index > size) { throw new RuntimeException("Invalid Index"); } // 获取index前一个节点 Node prev = dummyHead; for (int i = 0; i < index; i++) { prev = prev.next; } // 删除数据 Node retNode = prev.next; prev.next = retNode.next; size --; }
get 方法
// 通过索引获取链表数数据 public E get(int index) { // 检查索引是否越界 if (index < 0 || index > size) { throw new RuntimeException("Invalid Index"); } // 获取index前一个节点 Node cur = dummyHead.next; for (int i = 0; i < index; i++) { cur = cur.next; } return cur.e; }
set 方法
// 通过索引设置链表数据 public E set(int index,E e) { // 检查索引是否越界 if (index < 0 || index > size) { throw new RuntimeException("Invalid Index"); } // 获取index前一个节点 Node cur = dummyHead.next; for (int i = 0; i < index; i++) { cur = cur.next; } // 设置新值 cur.e = e; return cur.e; }
contain 方法
// 链表是否包含元素 public boolean contains(E e) { Node cur = dummyHead.next; // 遍历所有节点 while (cur != null) { if (cur.e.equals(e)) { return true; } cur = cur.next; } return false; }
main
// main public static void main(String[] args) { // 创建单向链表 SingleLinkedList<Integer> singleLinkedList = new SingleLinkedList<>(); // 添加数据 for (int i = 0; i < 8; i++) { singleLinkedList.addFirst(i); System.out.println(singleLinkedList); } // 是否包含元素 System.out.println(singleLinkedList.contains(0)); System.out.println(singleLinkedList.contains(10)); // set singleLinkedList.set(0, 9); singleLinkedList.set(1, 7); System.out.println(singleLinkedList); // 删除数据 for (int i = 0; i < 8; i++) { singleLinkedList.remove(0); System.out.println(singleLinkedList); } }
输出结果:
0->NULL
1->0->NULL
2->1->0->NULL
3->2->1->0->NULL
4->3->2->1->0->NULL
5->4->3->2->1->0->NULL
6->5->4->3->2->1->0->NULL
7->6->5->4->3->2->1->0->NULL
true
false
9->7->5->4->3->2->1->0->NULL
7->5->4->3->2->1->0->NULL
5->4->3->2->1->0->NULL
4->3->2->1->0->NULL
3->2->1->0->NULL
2->1->0->NULL
1->0->NULL
0->NULL
NULL
完整代码
public class SingleLinkedList<E> { private Node dummyHead; // 头指针 private int size; // 链表大小 // Node类 private class Node { public E e; // 元素 private Node next; // 下一个节点 // 构造 public Node(E e) { this.e = e; this.next = null; } @Override public String toString() { return e.toString(); } } // 构造 public SingleLinkedList() { dummyHead = new Node(null); size = 0; } // 表首添加元素 public void addFirst(E e) { add(0, e); } // 表尾添加元素 public void addLast(E e){ add(size, e); } // 添加数据 public void add(int index, E e) { // 检查索引是否越界 if (index < 0 || index > size) { throw new RuntimeException("Invalid Index"); } // 获取index前一个节点 Node prev = dummyHead; for (int i = 0; i < index; i++) { prev = prev.next; } // 添加数据 Node node = new Node(e); node.next = prev.next; prev.next = node; size ++; } // 删除数据 public void remove(int index) { // 检查索引是否越界 if (index < 0 || index > size) { throw new RuntimeException("Invalid Index"); } // 获取index前一个节点 Node prev = dummyHead; for (int i = 0; i < index; i++) { prev = prev.next; } // 删除数据 Node retNode = prev.next; prev.next = retNode.next; size --; } // 通过索引获取链表数数据 public E get(int index) { // 检查索引是否越界 if (index < 0 || index > size) { throw new RuntimeException("Invalid Index"); } // 获取index前一个节点 Node cur = dummyHead.next; for (int i = 0; i < index; i++) { cur = cur.next; } return cur.e; } // 通过索引设置链表数据 public E set(int index,E e) { // 检查索引是否越界 if (index < 0 || index > size) { throw new RuntimeException("Invalid Index"); } // 获取index前一个节点 Node cur = dummyHead.next; for (int i = 0; i < index; i++) { cur = cur.next; } // 设置新值 cur.e = e; return cur.e; } // 链表是否包含元素 public boolean contains(E e) { Node cur = dummyHead.next; // 遍历所有节点 while (cur != null) { if (cur.e.equals(e)) { return true; } cur = cur.next; } return false; } // 获取链表大小 public int getSize() { return size; } // 判断链表是否为空 public boolean isEmpty() { return size == 0; } @Override public String toString() { StringBuilder builder = new StringBuilder(); Node cur = dummyHead.next; while (cur != null) { builder.append(cur + "->"); cur = cur.next; } builder.append("NULL"); return builder.toString(); } // main public static void main(String[] args) { // 创建单向链表 SingleLinkedList<Integer> singleLinkedList = new SingleLinkedList<>(); // 添加数据 for (int i = 0; i < 8; i++) { singleLinkedList.addFirst(i); System.out.println(singleLinkedList); } // 是否包含元素 System.out.println(singleLinkedList.contains(0)); System.out.println(singleLinkedList.contains(10)); // set singleLinkedList.set(0, 9); singleLinkedList.set(1, 7); System.out.println(singleLinkedList); // 删除数据 for (int i = 0; i < 8; i++) { singleLinkedList.remove(0); System.out.println(singleLinkedList); } } }
到此这篇关于Java 数据结构与算法系列精讲之单向链表的文章就介绍到这了,更多相关Java 单向链表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
为何修改equals方法时还要重写hashcode方法的原因分析
这篇文章主要介绍了为何修改equals方法时还要重写hashcode方法的原因分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-06-06SpringBoot Security使用MySQL实现验证与权限管理
安全管理是软件系统必不可少的的功能。根据经典的“墨菲定律”——凡是可能,总会发生。如果系统存在安全隐患,最终必然会出现问题,这篇文章主要介绍了SpringBoot安全管理Spring Security基本配置2022-11-11详解Java中方法next()和nextLine()的区别与易错点
这篇文章主要介绍了详解Java中方法next()和nextLine()的区别与易错点,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-11-11
最新评论