作力扣 的算法题 忽然想到这个数据结构,以为有必要记录下来java
1. 定义一个Link类和一个Node类,其中Node类为Link类的内部类(避免了反复的getter和setter方法)
Link类的目的是进行节点建立
Node类的目的是进行数据和节点连接,而且Node只能为Link调用,须要定义为private
再定义一个Factory类,用来给客户端调用,返回的是一个Link类的实例node
2. Node类中须要包含有如下属性:
(1) Object data : 用于存放数据
(2) Node next : 用户存放指向下一个节点的数据
构造函数就是给data赋值
3. 增长1个追加函数,往链表中添加元素
(1) 明确的是,追加数据要在Link类中完成
(2) 须要先在Link类中声明root根节点
(3) 若是没有传入数据,那么就直接返回,不作操做
(4) 对于存放的数据,那么就要新建一个节点,新建一个节点对象,而后把这个节点对象交给Node类去处理
(5) 第4步中,存放节点数据应该从root开始,若是root为空,那么存放的数据就是root,只要把新建节点赋值给root便可
若是不是,那么就要把新建节点交由Node类处理,从root节点开始
(6) Node类接收Link类传过来的newNode对象,作如下处理:
判断root的next是否为空值,如果,则把newnode赋值给root.next
若不为空,那么递归,下个是root.next.next
以上完成增长一个数据,并处理节点关系
测试程序为:
//
public class TestLinkDemo {
public static void main(String[] args) {
Link all = Factory.getInstance();
all.add("AAA");
all.add("BBB");
all.add("CCC");
}
}
//
4. 增长一个函数,获取链表中的数据个数
(1) 在Link类中定义属性,统计个数,count
(2) 定义方法,获取count,就是返回数据个数
(3) 定义isEmpty()方法,判断链表是否为空
5. 增长一个函数,能够把链表转换成对象数组
(1) 链表就是一个动态数组,返回类型为Object[] data,每一个数据的取得有前后顺序,所以须要定义一个游标
(2) Link类中,首先须要判断,链表长度是否为零,若是是零,就返回空值,若是不是0,则须要遍历整个链表,
游标为0,从root节点开始调用Node中取出数据的函数(新定义)
(3) Node类中须要获取每一个节点的数据,并填写到数组中,若是判断下个节点还有数据,那么就要继续递归
6. 增长一个查询数据的方法
(1) 须要equals方法支持
(2) Node中追加一个方法,用于查找指定元素,并且必须从root节点开始日后找
(3) Link中追加一个方法,用于判断必须输入查找内容,以及链表不为空,若正常,就调用Node中的方法,从root开始
7. 根据索引取得数据
(1) 在Node类里面增长一个索引查找的方法,根据游标查找
(2) 在Link类中增长一个索引查找方法,目的是保证链表有数据,同时初始化游标,查找的时候从root节点日后找算法
8. 修改指定索引的数据
(1) 首先在Link类中定义一个方法,传入2个参数,第一个为索引值,第二个是要修改为的目标对象值
考虑问题,若是索引超过了链表长度,那么就不修改,结束调用
不然就先设定游标,而后从root节点开始调用Node中真正修改数据的函数
(2) Node类中定义的方法,首先判断当前游标是否为指定游标,如果,则修改数据
若不是,判断当前是否是最后一个节点,若是节点不为空,那么继续日后查找节点,递归调用数组
9. 删除数据
(1) 全部的前提是存在该数据,全部首先由上面定义的查找方法进行查找
若是删除的是根节点,更换root的操做只须要在Link类中完成便可
若是不是,那么要把根节点的下一个节点交给Node类中的删除方法进行
(2) Node类中判断当前对象的数据是不是要删除的数据,若是是的话,就把这个对象的上一个next指向下一个next数据结构
若是不是,则继续递归删除函数
更新一下查找方法,原课程写的有问题测试
//根据索引取得数据 public Object getNode(int searchIndex) { if (Link.this.index++ == searchIndex) { return this.data; } else { return this.next.getNode(searchIndex); } } class Link { private Node root; //根节点,增长数据函数添加 private int count; //统计元素个数 private Object[] retData; //返回对象数组 private int index = 0; //操做游标 // 定义Node内部类,表示Node只为Link类服务 private class Node { //负责 保存数据,节点关系配置 private Object data; private Node next; public Node(Object data) { this.data = data; } //增长数据 public void addNode(Node newNode) { if (this.next == null) { this.next = newNode; } else { this.next.addNode(newNode); } } //转换成对象数组 public void toArrayNode() { Link.this.retData[Link.this.index ++] = this.data;//先把root节点的数据取出,而后游标加一 if (this.next != null){ //若是下个节点还有数据,则递归获取 this.next.toArrayNode(); } } //查找数据 public boolean containsNode(Object search) { if (search.equals(this.data)) { return true; //找到数据 } else { if (this.next != null) { //还有后续节点 return this.next.containsNode(search);//递归查找 } else { return false; } } } //根据索引取得数据 public Object getNode(int searchIndex) { if (Link.this.index ++ == searchIndex) { return this.data; } else { this.next.getNode(searchIndex); } return null; } //修改指定索引的数据 public void setNode(int searchIndex, Object newData) { if (Link.this.index ++ == searchIndex) { this.data = newData; } else { if (this.next != null) { this.next.setNode(searchIndex,newData); } } } //删除元素 public void removeDataNode(Node previous, Object data) { if (this.data.equals(data)) { previous.next = this.next; //中间是this,若是this的data是所要删除的data,那么把this以前的一个node指向this以后的一个node } else { this.next.removeDataNode(this, data); } } } // ---------如下是Link类定义----------- //增长元素 public void add(Object data) { if ( data == null ) {//不容许存放空值数据 return; } Node newNode = new Node(data); //建立一个新的节点 if (this.root == null) { this.root = newNode; } else { this.root.addNode(newNode); } this.count ++; } //获取链表大小 public int size() { return this.count; } //判断链表是否为空 public boolean isEmpty() { if (this.root == null && this.count == 0 ) { return false; } else { return true; } } //链表转换成对象数组 public Object[] toArray() { if (this.count == 0) { //若是链表没有数据,那么就返回null return null; } this.retData = new Object[this.count];//若是count不为零,那么开辟指定空间的对象数组 this.index = 0;//游标初始化为0 this.root.toArrayNode();//交给Node类进行数据的取出 return this.retData;//返回对象数组 } //查找数据 public boolean contains(Object search) { if (search == null || this.root == null) { return false; } return this.root.containsNode(search); } //根据索引取得数据 public Object get(int searchIndex) { if (searchIndex >= this.count) { return null; } this.index = 0; return this.root.getNode(searchIndex); } //修改指定索引的数据 public void setData(int searchIndex, Object newData) { if (searchIndex >= this.count) { return ; } else { this.index = 0; this.root.setNode(searchIndex, newData); } } //删除数据 public void removeData(Object data) { if (this.contains(data)) { if (this.root.data.equals(data)) { this.root = this.root.next; } else { this.root.next.removeDataNode(this.root, data); } this.count --; } } } class Factory { public static Link getInstance() { return new Link(); } } public class TestLinkDemo { public static void main(String[] args) { Link all = Factory.getInstance(); // all.add("AAA"); all.add("BBB"); all.add("CCC"); // System.out.println("链表大小为: " + all.size()); // Object[] result = all.toArray(); System.out.println("链表转换成对象数组并输出: "); for ( Object x : result ) { System.out.println(x); } //查询数据方法 System.out.println("查询数据方法: "); System.out.println(all.contains("AAA")); System.out.println(all.contains("D")); //取得索引数据 System.out.println("查找索引为0的数据: "); System.out.println(all.get(0)); System.out.println("查找索引为3的数据: "); System.out.println(all.get(3)); //修改索引数据 System.out.println("修改索引数据: "); all.setData(0,"DDD"); Object[] result1 = all.toArray(); System.out.println("修改索引数据并输出: "); for ( Object x : result1 ) { System.out.println(x); } //删除数据 System.out.println("删除数据: "); all.removeData("BBB"); Object[] result2 = all.toArray(); System.out.println("删除数据并输出: "); for ( Object x : result2 ) { System.out.println(x); } } }
测试结果:this