首先先简单了解一下SingleLinkedList单链表
-
数据元素的存储是一个不连续的空间,每个存储节点对应一个需要存储的数据元素。
-
每个节点是有数据域和指针域组成的即(data/next):data指本个元素节点的值,next指下一个元素节点的地址。元素之间的逻辑关系通过存储节点之间的连接关系反映出来,逻辑上相邻的两个节点,物理上不必一定相邻
那么在说一下单链表的优缺点
优点
一、插入删除比较灵活相当于ArrayList来说不再是一个一个的移动数据了,只需要修改上一个元素的地址引用即可 但是前提是得定位到当前元素
二、有元素才会分配节点空间,不会有闲置的空间
缺点
一、相比ArrayList来说存储密度比较小因为需要每个节点都需要存储指针域和数据域 同时如果再相同的空间下 ArrayList要比SingleLinkedList存储的数据要多
二、查找节点的时候要比ArrayList慢 ,每个节点的地址不连续,没有规律 所以查找的时候需要一个一个的比较
在简单讲一下添加和删除节点动作
添加动作:在一个不连续的链表下 我要在第3个位置插入一个节点,首先获取要插入节点的上一个节点 即3-1:第2个的节点 修改第二个的节点的指针域的值为新加入的节点的地址,然后修改第3个节点第指针域执行之前第2个节点的指针域。
删除动作:在一个不连续的链表下,我要删除第3个节点,首先要获取前一个的节点,即第2个节点,修改第2个节点的指针域指向第3+1个节点的地址 然后将第3个节点的指针域设置为null
接下来就上代码了
首先是要实现的接口public interface List { // 返回线性表的大小,即数据元素的个数。 public int size(); // 返回线性表中序号为 i 的数据元素 根据下标获取元素 public Object get(int i); // 如果线性表为空返回 true,否则返回 false。判断是否为空 public boolean isEmpty(); // 判断线性表是否包含数据元素 e 判断集合中是否包含某元素 public boolean contains(Object e); // 返回数据元素 e 在线性表中的序号 返回指定元素的下标 public int indexOf(Object e); // 将数据元素 e 插入到线性表中 i 号位置 插入到指定下标的位置 public void add(int i, Object e); // 将数据元素 e 插入到线性表末尾 添加元素 public void add(Object e); // 将数据元素 e 插入到元素 obj 之前 将指定元素插入到标记元素之前 public boolean addBefore(Object obj, Object e); // 将数据元素 e 插入到元素 obj 之后 将指定元素插入到标记元素之后 public boolean addAfter(Object obj, Object e); // 删除线性表中序号为 i 的元素,并返回之 删除指定下标的元素 public Object remove(int i); // 删除线性表中第一个与 e 相同的元素 删除第一个元素为e 的数据 public boolean remove(Object e); // 替换线性表中序号为 i 的数据元素为 e,返回原数据元素 替换下标中的元素为指定元素 public Object replace(int i, Object e); public Iterator iterator(); //实现迭代器 } 然后定义单链表的实体类 public class Node { public Object data;//存储数据
public Node next;//指向下一个节点的引用变量
public Node(){
super();
}
public Node(Object data){
this.data=data;
}
public Node(Object data,Node next){
this.data=data;
this.next=next;
}public Object getData() { return data; } public void setData(Object data) { this.data = data; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } @Override public String toString() { return "Node{" + "data=" + data + ", next=" + next + '}'; }
}
然后就是单链表的实现类了public class SingleLinkedList implements List{
private Node head=new Node();//头结点 不存储数据 初始创建,用来指向第一个真正数据节点 private int size;//节点个数 @Override public int size() { return size; } @Override public Object get(int i) {//按照索引来查 //按照索引来查效率低 需要一个一个比较 Node p=head;//指向头节点 //从头节点开始一个一个比较向下面对比 最终指向第i个节点 for (int index=0;index<=i;index++){ p=p.next; } return p;//返回当前节点 //return p.data;当前节点的值 } @Override public boolean isEmpty() { return size==0; } @Override public boolean contains(Object e) { return false; } @Override public int indexOf(Object e) { return 0; } @Override public void add(int i, Object e) { //先找到第前一个元素 i-1 Node previousNode=head; if(i>0){ previousNode=(Node) get(i-1); } //添加一个节点 //创建一个新的节点 Node newNode=new Node(e); //新建的节点指向第i-1个节点 newNode.next=previousNode.next; //让前一个节点指向新建的节点 previousNode.next=newNode; //数量自增 size++; } @Override public void add(Object e) { this.add(size,e); } @Override public boolean addBefore(Object obj, Object e) { return false; } @Override public boolean addAfter(Object obj, Object e) { return false; } @Override public Object remove(int i) { //先找到前一个节点 即i-1 Node previousNode=head; if(i>0){ previousNode=(Node) get(i-1); } //2.删除第i个元素 //2.1.指针指向第i个节点 Node currentNode = previousNode.next; //2.2.前一个节点指向后一个节点 previousNode.next = currentNode.next; // previousNode.next = previousNode.next.next; //2.3 当前节点不再指向后一个节点 currentNode.next = null; //previousNode.next.next = null; //3.数量减1 size--; return null; } @Override public boolean remove(Object e) { return false; } @Override public Object replace(int i, Object e) { return null; } @Override public Iterator iterator() { return null; } @Override public String toString() { StringBuilder builder=new StringBuilder("["); //指向第0个节点 Node p=head.next; for (int i = 0; i < size; i++) { if(i==size-1){ builder.append(p.data); }else { builder.append(p.data + ","); } //指向下一个节点 p=p.next; } builder.append("]"); return builder.toString(); }
然后是单链表的测试类
public class SingleLinkedListTest {
public static void main(String[] args) {
//创建线性顺序表
List list = new SingleLinkedList();
//向末尾添加元素
list.add("11111");
list.add("aaaaa");
list.add("bbbbb");
list.add("33333");
list.add("22222");
list.add(3, "AAAAA");
list.remove(4);
//进行各种操作验证添加
System.out.println(list.get(3));
//System.out.println(list.get(0));
System.out.println(list.size());
System.out.println(list.isEmpty());
System.out.println(list.toString());
}
}