目录
1、定义
传统的数组在使用过程中依赖于索引的控制,如果想要实现内容的动态维护,难度太大。 所以呢,对于随时可能变动的结构,就需要链表了。
所谓链表实质性的本质是利用引用的逻辑关系来实现类似数据的数据处理操作,以一种保存多方数据的形式,实现数组类似的功能。
2、链表结构
可以模拟出这种结构,但是设置节点之间的关系十分麻烦,每个关联都需要手动去做,实在太费劲。应该有个类专门做这种配置引用节点之间关系事情。实际使用者不应该关注怎么操作这个Node,而是只关注数据的操作。
public class LinkDemo {
public static void main(String args[]) {
Node<String> n1 = new Node<String>("火车头");
Node<String> n2 = new Node<String>("车厢1");
Node<String> n3 = new Node<String>("车厢2");
Node<String> n4 = new Node<String>("车厢3");
Node<String> n5 = new Node<String>("车厢4");
n1.setNext(n2);
n2.setNext(n3);
n3.setNext(n4);
n4.setNext(n5);
print(n1);
}
public static void print(Node<?> node) {
if (node != null) {
System.out.println(node.getData());
print(node.getNext());
}
}
}
3、具体实现链表数据操作
原理自己动手写一遍代码就能搞懂的
总体就三个类,接口类、实现类还有测试类
public interface ILink<E> {
//新增数据
public void add(E e);
//链表长度
public int size();
//判断链表是否为空
public boolean isEmpty();
//返回数据对象数组
public Object[] toArray();
//获取指定位置节点上的数据
public E get(int index);
//修改指定位置数据
public void set(int index,E data);
//判断链表中是否有此数据
public boolean contains(E data);
//移除数据
public void remove(E data);
//清空链表
public void clean();
}
public class LinkImpl<E> implements ILink<E> {
private class Node {
private E data;
private Node next;
public Node(E data) {
this.data = data;
}
public void addNode(Node newNode) {
if (this.next == null) {
this.next = newNode;
} else {
this.next.addNode(newNode);
}
}
public void toArrayNode() {
LinkImpl.this.returnData[LinkImpl.this.foot++] = this.data;
if (this.next != null) {
this.next.toArrayNode();
}
}
public E getNode(int index) {
if (LinkImpl.this.foot++ == index) {
return this.data;
} else {
return this.next.getNode(index);
}
}
public void setNode(int index, E data) {
if (LinkImpl.this.foot++ == index) {
this.data = data;
} else {
this.next.setNode(index, data);
}
}
public boolean containsNode(E data) {
if (this.data.equals(data)) {
return true;
} else {
if (this.next == null) {
return false;
} else {
return this.next.containsNode(data);
}
}
}
public void removeNode(Node pervious, E data) {
if (this.data.equals(data)) {
pervious.next = this.next;
} else {
if (this.next != null) {
this.next.removeNode(this, data);
}
}
}
}
private Node root;
private int count;
private int foot;
private Object[] returnData;
@Override
public void add(E e) {
if (e == null) {
return;
}
Node newNode = new Node(e);
if (this.root == null) {
this.root = newNode;
} else {
this.root.addNode(newNode);
}
this.count++;
}
@Override
public int size() {
return this.count;
}
@Override
public boolean isEmpty() {
return this.count == 0;
}
@Override
public Object[] toArray() {
if (this.isEmpty()) {
return null;
}
this.foot = 0;
this.returnData = new Object[this.count];
this.root.toArrayNode();
return this.returnData;
}
@Override
public E get(int index) {
if (index >= this.count) {
return null;
}
this.foot = 0;
return this.root.getNode(index);
}
@Override
public void set(int index, E data) {
if (index >= this.count) {
return;
}
this.foot = 0;
this.root.setNode(index, data);
}
@Override
public boolean contains(E data) {
if (data == null) {
return false;
}
return this.root.containsNode(data);
}
@Override
public void remove(E data) {
if (this.contains(data)) {
if (this.root.data.equals(data)) {
this.root = this.root.next;
} else {
this.root.next.removeNode(this.root, data);
}
this.count--;
}
}
@Override
public void clean() {
this.root = null;
this.count = 0;
}
}
public class LinkDemo {
public static void main(String args[]) {
ILink<String> all = new LinkImpl<>();
System.out.println(all.size());
System.out.println(all.isEmpty());
all.add("hello");
System.out.println(all.size());
all.add("KOBE");
all.add("james");
System.out.println(all.size());
System.out.println(all.isEmpty());
Object[] result = all.toArray();
for (Object a : result) {
System.out.println(a);
}
System.out.println(all.get(0));
all.set(1, "jordan");
System.out.println(all.get(1));
System.out.println(all.contains("龙哥"));
all.remove("hello");
Object[] result1 = all.toArray();
for (Object a : result1) {
System.out.println(a);
}
all.clean();
System.out.println(all.toArray());
}
}
这里面有好几个方法用到了内部类Node,个人觉得非常巧妙,经常手动实现一下这个代码,能帮助我们体会内部类的好处,以及加深对递归、链表概念的理解