说明Linkedlist
1.Linkedlist时基于链表实现的,如图所示
2.源码里它用一个类Node来代替一个节点:
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
现在开始实现(先不添加泛型,最后改进)
1.实现节点类
一般用第二个构造方法,先实现类,再实现细节
public class Node {
Node previous; //上一个节点
Node next; // 下一个节点
Object element; //本节点里的元素
public Node(Node previous, Node next, Object element) {
super();
this.previous = previous;
this.next = next;
this.element = element;
}
public Node(Object element) {
super();
this.element = element;
}
}
2.实现add(),toString()
现在实现的链表结构并不是第一张图片的样子(一个循环双向链表),
现在的链表结构如下图所示,是一个首尾不相连,都指向空的逻辑,注意比较
public class Linklist01 {
private Node firsrt; // 第一个节点
private Node last; // 最后一个节点
private int size; //元素个数
public Linklist01() {
super();
}
// 现在不考虑链表循环
public void add(Object object) {
Node node = new Node(object);
// 第一次添加元素
if (null == firsrt) {
firsrt = node;
last = firsrt;
}else {
// 将新节点 上一个指向 之前的last
node.previous = last;
// last的下一个指向新对象
last.next = node;
// 改变 last
last = node;
}
size++;
}
// 重写toString
@Override
public String toString() {
StringBuffer sb = new StringBuffer("[");
Node temp = firsrt;
while (temp.next != null) {
sb.append(temp.element+",");
temp = temp.next;
}
sb.append(temp.element+"]");
return sb.toString();
}
}
用添加元素"ll",“kk”,“hh”,与打印验证代码
public static void main(String[] args) {
Linklist01 link = new Linklist01();
link.add("ll");
link.add("kk");
link.add("hh");
System.out.println(link);
}
通过工具查看具体逻辑结构,如下图
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
最后一张图片可能比较乱,但是说明了内部的指向问题:
3.添加get(),遍历节点代码
public Object get(int index){
// 索引有效性
if (index <0 || index >= size){
throw new RuntimeException("索引不合法:"+index);
}
Node node = firsrt;
// 遍历查找
for (int i = 0; i < index; i++) {
node = node.next;
}
return node.element;
}
但是上面的代码效率低,如下情况:集合长度600,查询下标599的元素,要把集合全部遍历一遍,效率差。
所以应该采用,下标在前一半里,从前往后;在后一半里,从后往前,
下面是改进代码:
// 改进查找,当在前一半里时,从first处开始遍历
// 反之,从 last处 从后往前遍历
public Object get(int index){
// 索引有效性
if (index <0 || index >= size){
throw new RuntimeException("索引不合法:"+index);
}
Node node ;
// 遍历查找
if (index <= (size>>2)){
node = firsrt;
for (int i = 0; i < index; i++) {
node = node.next;
}
}else {
node = last;
for (int i = size-1; i > index; i--) {
node = node.previous;
}
}
return node.element;
}