前言
链表是一种常见的基础数据结构,它是一种线性表,但在内存中它并不是顺序存储的,它是以链式进行存储的,每一个节点里存放的是下一个节点的“指针”。在Java中的数据分为引用数据类型和基础数据类型,在Java中不存在指针的概念,但是对于链表而言的指针,指的就是引用数据类型的地址。
链表和数组都是线性的数据结构,对于数组而言其长度是固定的,由于在内存中其是连续的,因此更适合做查找与遍历,而链表在内存中是并不是顺序存储的,但是由于其是通过“指针”构成的,因此在插入、删除时比较数组更为的方便。
下面的代码通过内部类并结合递归的方式来实现了一个简单的用Java语言描述的链表的数据结构,下面话不多说了,来一起看看详细的介绍吧
链表数据结构的定义
首先来看一下,链表数据结构的定义,代码如下:
class NodeManager { private Node root; // 根节点 private int currentIndex = 0; // 节点的序号,每次操作从0开始 public void add(int data) {} public void delNode(int data) {} public void print() {} public boolean findNode(int data) {} public boolean updateNode(int oldData, int newData) {} // 向索引之前插入 public void insert(int index, int data) {} // 谁拥有数据,谁提供方法 class Node { private int data; private Node next; // 把当前类型作为属性 public Node(int data) { this.data = data; } public void setData(int data) { this.data = data; } public int getData() { return data; } // 添加节点 public void addNode(int data) {} // 删除节点 public void delNode(int data) {} // 输出所有节点 public void printNode() {} // 查找节点是否存在 public boolean findNode(int data) {} // 修改节点 public boolean updateNode(int oldData, int newData) {} // 插入节点 public void insertNode(int index, int data) {} } }
对于链表的定义来说,NodeManager类是用来管理链表操作的,而成员内部类Node是用于提供链表数据与链式结构的。对于类的使用者来说,并不直接访问数据,因此操作的是NodeManager类,而内部类Node提供了真正的数据管理,因此Node类需要提供真正的数据操作方法,对于NodeManager类中也需要提供一套由外部来操作链表的方法。因此,在NodeManager类和Node类中都提供了看似相同的方法,但实际的意义并不相同。
下面来查看NodeManager类和Node类中的add()方法,代码如下:
public void add(int data) { if ( root == null ) { root = new Node(data); } else { root.addNode(data); } } // 添加节点 public void addNode(int data) { if ( this.next == null ) { this.next = new Node(data); } else { this.next.addNode(data); } }
代码中上面的方法是NodeManager类中的方法,而下面的方法是Node类中的方法。
在Manager类中提供了一个root的成员变量,它用于管理链表的头节点,因此在添加节点时,会先判断root是否为空,如果为空则直接将节点由root来进行保存,如果root不为空,则通过Node类中的addNode()方法来进行添加,添加到思路是找到当前链表的最后一个节点,并将新添加到节点赋值给最后一个节点的next成员变量中。
链表增删改查
对于链表的其他操作也是相同的思路,关于链表增删改查和输出的完整代码如下:
class NodeManager { private Node root; // 根节点 private int currentIndex = 0; // 节点的序号,每次操作从0开始 public void add(int data) { if ( root == null ) { root = new Node(data); } else { root.addNode(data); } } public void delNode(int data) { if ( root == null ) return ; if ( root.getData() == data ) { Node tmp = root; root = root.next; tmp = null; } else { root.delNode(data); } } public void print() { if ( root != null ) { System.out.print(root.getData() + " "); root.printNode(); System.out.println(); } } public boolean findNode(int data) { if ( root == null ) return false; if ( root.getData() == data ) { return true; } else { return root.findNode(data); } } public boolean updateNode(int oldData, int newData) { if ( root == null ) return false; if ( root.getData() == oldData ) { root.setData(newData); return true; } else { return root.updateNode(oldData, newData); } } // 向索引之前插入 public void insert(int index, int data) { if ( index < 0 ) return ; currentIndex = 0; if ( index == currentIndex ) { Node newNode = new Node(data); newNode.next = root; root = newNode; } else { root.insertNode(index, data); } } // 谁拥有数据,谁提供方法 class Node { private int data; private Node next; // 把当前类型作为属性 public Node(int data) { this.data = data; } public void setData(int data) { this.data = data; } public int getData() { return data; } // 添加节点 public void addNode(int data) { if ( this.next == null ) { this.next = new Node(data); } else { this.next.addNode(data); } } // 删除节点 public void delNode(int data) { if ( this.next != null ) { if ( this.next.getData() == data ) { Node tmp = this.next; this.next = this.next.next; tmp = null; } else { this.next.delNode(data); } } } // 输出所有节点 public void printNode() { if ( this.next != null ) { System.out.print(this.next.getData() + " "); this.next.printNode(); } } // 查找节点是否存在 public boolean findNode(int data) { if ( this.next != null ) { if ( this.next.getData() == data ) { return true; } else { return this.next.findNode(data); } } return false; } // 修改节点 public boolean updateNode(int oldData, int newData) { if ( this.next != null ) { if ( this.next.getData() == oldData ) { this.next.setData(newData); return true; } else { return this.next.updateNode(oldData, newData); } } return false; } // 插入节点 public void insertNode(int index, int data) { currentIndex ++; if ( index == currentIndex ) { Node newNode = new Node(data); newNode.next = this.next; this.next = newNode; } else { this.next.insertNode(index, data); } } } }
以上就是链表基本操作的完整代码,下面写一个调用的代码进行测试,代码如下:
public class LinkList { public static void main(String[] args) { NodeManager nm = new NodeManager(); System.out.println("链表的添加(添加5、4、3、2、1)"); nm.add(5); nm.add(4); nm.add(3); nm.add(2); nm.add(1); nm.print(); System.out.println("链表的删除(删除3)"); nm.delNode(3); nm.print(); System.out.println("链表的查找(查找1)"); System.out.println(nm.findNode(1)); System.out.println("链表的查找(查找10)"); System.out.println(nm.findNode(10)); System.out.println("链表的更新(把1更新为10)"); nm.updateNode(1, 10); nm.print(); System.out.println("链表的插入(在第1个位置插入20)"); nm.insert(1, 20); nm.print(); System.out.println("链表的插入(在第0个位置插入30)"); nm.insert(0, 30); nm.print(); } }
将代码编译、运行,结果如下图:
对于Java中的集合类中用到了不少的数据结构的知识,等自己状态好的时候学习学习Java集合类的源码。我会努力做一个初级程序员!
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。
本文向大家介绍Java数据结构之链表(动力节点之Java学院整理),包括了Java数据结构之链表(动力节点之Java学院整理)的使用技巧和注意事项,需要的朋友参考一下 单链表: insertFirst:在表头插入一个新的链接点,时间复杂度为O(1) deleteFirst:删除表头的链接点,时间复杂度为O(1) find:查找包含指定关键字的链接点,由于需要遍历查找,平均需要查找N/2次,即O(N
本文向大家介绍C#数据结构之单链表(LinkList)实例详解,包括了C#数据结构之单链表(LinkList)实例详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#数据结构之单链表(LinkList)实现方法。分享给大家供大家参考,具体如下: 这里我们来看下“单链表(LinkList)”。在上一篇《C#数据结构之顺序表(SeqList)实例详解》的最后,我们指出了:顺序表要求开辟一组
本文向大家介绍详解ES6中的 Set Map 数据结构学习总结,包括了详解ES6中的 Set Map 数据结构学习总结的使用技巧和注意事项,需要的朋友参考一下 ES6中的 Set 数据结构 ES6 新增了一种 Set 数据结构。它类似数组。 最重要的一点是 Set中的结构成员没有重复的, 可用这点 一行代码实现数组去重。 Set 本身是一个构造函数。通过 new Set() 来创建Set结构。 通
本文向大家介绍Python实现的数据结构与算法之链表详解,包括了Python实现的数据结构与算法之链表详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python实现的数据结构与算法之链表。分享给大家供大家参考。具体分析如下: 一、概述 链表(linked list)是一组数据项的集合,其中每个数据项都是一个节点的一部分,每个节点还包含指向下一个节点的链接。 根据结构的不同,链表可以分
本文向大家介绍MySql学习day03:数据表之间的连接、查询详解,包括了MySql学习day03:数据表之间的连接、查询详解的使用技巧和注意事项,需要的朋友参考一下 主键: 关键字:primary key 特点:不能为null,并且唯一。 主键分类: 逻辑主键:例如ID,不代表实际的业务意义,只是用来唯一标识一条记录(推荐) 业务主键:例如username,参与实际的业务逻辑。 主键使用方式:
本文向大家介绍C#数据结构之双向链表(DbLinkList)实例详解,包括了C#数据结构之双向链表(DbLinkList)实例详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#数据结构之双向链表(DbLinkList)。分享给大家供大家参考,具体如下: 这是继上一篇《C#数据结构之单链表(LinkList)实例详解》的继续,对于双向链接,节点上除了Next属性外,还要有Prev属性用