package demo;

import java.util.Collection;

public class MyLinkedList<E> {
	// 属性

	// 构造方法
	public MyLinkedList() {

	}

	public MyLinkedList(Collection<? extends E> c) {
		this();
		addAll(c);
	}

	// 构建双向链表,首先要构建节点
	// 建立成员内部类节点,
	private static class Node<E> {
		E item; // 存储数据
		Node<E> next;// 下一个节点
		Node<E> prev; // 前一个节点

		public Node(Node<E> next, E item, Node<E> prev) {
			this.item = item;
			this.next = next;
			this.prev = prev;
		}
	}
	// 一个数组域存放数组,一个prev指向前一个节点的next 一个next指向下一个节点的prev.

	// 第一个节点
	private Node<E> first;
	// 最后一个节点
	private Node<E> last;
	// 数组个数
	private int size;

	// 将指定元素追加到此列表的末尾
	public boolean add(E e) {
		addLast(e);
		return true;
	}

	// 将节点连接到此列表的末尾
	void addLast(E e) {
		Node<E> l = last; // 首先找到最后一个元素
		Node<E> node = new Node<E>(null, e, l);// 根据传入的e创建一个新的节点next指向null
												// item存传入的e prev指向l;
		last = node; // 将刚刚新创建的节点node变为最后一个节点
		if (l == null) { // 如果最后一个节点null
			first = node; // 第一个节点就为node
		} else {
			l.next = node; // 将前一个节点的next指向下一个节点
		}
		size++; // size+1
	}

	public void addfirst(E e) {
		linkfirst(e);
	}

	// 在此列表中的指定位置插入指定的元素
	public void add(int index, E e) {
		checkRange(index);// 首先判断范围
		if (index == size) { // 如果插入的在最后一个就调用插入最后一个的方法
			addLast(e);
		} else { // 否则取到index位置对应的node元素,然后替换
			Node<E> l = index(index);
			addBeforeNode(e, l);
		}
	}

	// 在指定元素前插入元素
	private void addBeforeNode(E e, Node<E> l) {
		Node<E> preNode = l.prev;
		Node<E> newnode = new Node<>(l, e, preNode);
		if (preNode == null) {
			first = newnode;
		} else {
			preNode.next = newnode;
		}
		l.prev = newnode;
		size++;
	}

	// 查找index出的元素
	private Node<E> index(int index) {// 采用二分法查找

		if (index < (size / 2)) { // 首先判断index在前一半还是后一半的范围,然后找到index出的元素
			Node<E> x = first;
			for (int i = 0; i < index; i++)
				x = x.next;
			return x;
		} else {
			Node<E> x = last;
			for (int i = size - 1; i > index; i--)
				x = x.prev;
			return x;
		}
	}

	void linkfirst(E e) {
		Node<E> l = first; // 首先找到第一个一个元素
		Node<E> node = new Node<E>(l, e, null);// 根据传入的e创建一个新的节点next指向null
												// item存传入的e prev指向l;
		first = node; // 将刚刚新创建的节点node变为最后一个节点
		if (l == null) { // 如果第一个节点null
			first = node; // 第一个节点就为node
		} else {
			l.prev = node; // 将前一个节点的next指向下一个节点
		}
		size++; // size+1
	}

	// 删除所有的元素
	public void clear() {
		for (Node<E> x = first; x != null;) {
			Node<E> next = x.next;
			x.item = null;
			x.prev = null;
			x.next = null;
			x = next;
		}
		first = last = null;
		size = 0;
	}

	// 判断是否越界
	private void checkRange(int index) {
		if (index < 0 && index > size)
			throw new IndexOutOfBoundsException("越界了");
	}

	// 返回列表中指定位置的元素
	public E get(int index) {
		checkRange(index);
		return index(index).item;
	}

	//
	private void addAll(Collection<? extends E> c) {
		// TODO Auto-generated method stub
	}

	// 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
	public int indexOf(Object o) {
		Node<E> n = first;
		int c = 0;
		while (n != null) {
			if (o != null) {
				if (o.equals(n.item))
					return c;
			} else {
				if (n.item == null) {
					return c;
				}
			}
			c++;
			n = n.next;
		}
		return -1;
	}
	//删除指定节点
	public E remove (int index){
		checkRange(index);
		return	unlink(index);
	}
	//删除指定对象
	public boolean remove(Object o){
		int index = indexOf(o);
		if(index<0){
			return false;
		}
		unlink(index);
		return true;
	}
	//删除index对应的节点的连接
	private E unlink(int index){
		Node<E> l = index(index);
		E item = l.item;
		Node<E> preNode = l.prev;
		Node<E> nextNode = l.next;
		if(preNode==null){
			first = nextNode;
		}else{
			preNode.next=nextNode;
			l.next=null;
		}
		if(nextNode==null){
			last = preNode;
		}else{
			nextNode.prev = preNode;
			l.prev=null;
		}
		size--;
		l.item=null;
		return item;
	}
}

LinkedList是基于双向链表实现的, LinkedList和ArrayList的区别: ArrayList基于数组实现,因此具有数组的特点:有序.元素可重复.插入慢.查找快 LinkedList 基于双向链表实现, 因此具有链表特带你 插入快、 查找慢的特性;