手写JDK1.8前的LinkedList(头节点非哨兵节点,双向循环链表)

在这里插入图片描述
六种方法的实现:

package list;

import java.util.ArrayList;
import java.util.List;

/**
*@author  Edward
*@date  2020年6月30日---下午2:32:40
*/
public class LinkedList<E> {
	private Node head;
	private int size;
	
	class Node{
		E data;
		Node prev;
		Node next;
		Node(E e) {
			data=e;
		}
	}
	
	public boolean add(E e) {
		Node node = new Node(e);
		if (head==null) {
			head = node;
			head.next = head;
			head.prev = head;
			size++;
			return true;
		}
		Node last = head.prev;
		last.next = node;
		node.prev = last;
		head.prev = node;
		node.next = head;
		size++;
		return true;
	}
	
	public void add(int index,E e) {
		if (index<0||index>size) {
			throw new IndexOutOfBoundsException("下标越界啦");
		}
		Node node = new Node(e);
		if (head==null) {
			head=node;
			// 当head是唯一节点时,必须设置前后为自己(其默认值均为null),否则toString遍历中会空指针
			head.next = head;
			head.prev = head;
			size++;
			return;
		}
		Node next = getNode(index);
		Node prev = next.prev;
		
		node.next = next;
		next.prev = node;
		prev.next = node;
		node.prev = prev;
		if (index == 0) {
			head = node;
		}
		size++;
		
	}
	
	public String toString() {
		if (head==null) {
			return "[]";
		}
		Node dummyHead = new Node(null);
		dummyHead.next = head;
		List<E>list = new ArrayList<E>();
		do {
			dummyHead = dummyHead.next;
			list.add(dummyHead.data);
		} while (dummyHead.next!=head);
		return list.toString();
		
	}
	
	public int size() {
		return size;
	}
	
	
	public E get(int index) {
		if (index<0||index>=size) {
			throw new IndexOutOfBoundsException("下标越界啦");
		}
		Node node = getNode(index);
		return node.data;
	}
	
	public E remove(int index) {
		if (index<0||index>=size) {
			throw new IndexOutOfBoundsException("下标越界啦");
		}
		// 这个双向循环链表的很多操作是基于头节点的,因此可能影响head的操作需要特殊处理
		// 边界条件,如果整个链表只有一个节点,需设置头节点为null
		if (size==1) {
			E data = head.data;
			head = null;
			size--;
			return data;
		}
		Node node = getNode(index);
		node.prev.next = node.next;
		node.next.prev = node.prev;
		size--;
		// 边界条件,如果删除的是头节点,需重新设置一个头节点
		if (index==0) {
			head=node.next;
		}
		
		return node.data;
	}

	private Node getNode(int index) {
		Node node = head;
		if (index<size/2) {
			for (int i = 0; i < index; i++) {
				node = node.next;
			}
		}else {
			for (int i = size; i > index; i--) {
				node= node.prev;
			}
			
		}
		return node;
	}

}

在这里插入图片描述

需要注意的是,当改动涉及头节点时,需要对特殊情况进行处理,如:添加节点时,头节点为唯一节点。这是因为,头节点的变动会间接影响其他方法的运行,且头节点是未初始化的,如原先头节点为null,则需要先对头节点进行初始化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章