手写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,则需要先对头节点进行初始化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值