常见面试题手写双向循环链表

public class DoubleLink<E> {

	private class Node<E> {
		public E value; // 节点值
		public Node<E> prev; // 前一个节点
		public Node<E> next; // 后一个节点

		public Node(E value, Node<E> prev, Node<E> next) {
			this.value = value;
			this.prev = prev;
			this.next = next;
		}
	}

	private int size;// 链表长度
	public Node<E> head;// 头节点

	/**
	 * constructor
	 */
	public DoubleLink() {
		// 头节点不存储值
		head = new Node<E>(null, null, null);
		head.prev = head.next = head;
		size = 0;
	}

	/**
	 * 获取链表的长度
	 * 
	 * @return
	 */
	public int size() {
		return size;
	}

	/**
	 * 判断链表是否为空
	 * 
	 * @return
	 */
	public boolean isEmpty() {
		return size == 0;
	}

	/**
	 * 验证索引的合法性
	 * 
	 * @param index
	 */
	public void rangeCheck(int index) {
		if (index < 0 || index >= size) {
			throw new IndexOutOfBoundsException();
		}
	}

	/**
	 * 获取位置为index的节点
	 * 
	 * @param index
	 * @return
	 */
	private Node<E> getNode(int index) {
		rangeCheck(index);
		if (index <= size / 2) {
			Node<E> cur = head.next;
			for (int i = 0; i < index; i++) {
				cur = cur.next;
			}
			return cur;
		}
		Node<E> cur = head.prev;
		int newIndex = size - index - 1;
		for (int i = 0; i < newIndex; i++) {
			cur = cur.prev;
		}
		return cur;
	}

	/**
	 * 获取位置为index的节点值
	 * 
	 * @return
	 */
	public E get(int index) {
		return getNode(index).value;
	}

	/**
	 * 获取第一个节点的值
	 * 
	 * @return
	 */
	public E getFirst() {
		return getNode(0).value;
	}

	/**
	 * 获取最后一个节点的值
	 * 
	 * @return
	 */
	public E getLast() {
		return getNode(size - 1).value;
	}

	/**
	 * 插入节点
	 * 
	 * @param index
	 * @param value
	 */
	public void insert(int index, E value) {
		if (index == 0) {
			Node<E> cur = new Node<E>(value, head, head.next);
			head.next.prev = cur;
			head.next = cur;
			size++;
			return;
		}

		Node<E> node = getNode(index - 1);
		Node<E> cur = new Node<E>(value, node, head);
		node.next = cur;
		head.prev = cur;
		size++;
	}

	/**
	 * 添加到链表的头部
	 * 
	 * @param value
	 */
	public void addFirst(E value) {
		insert(0, value);
	}

	/**
	 * 添加节点到链表的尾部
	 * 
	 * @param value
	 */
	public void addLast(E value) {
		Node<E> cur = new Node<E>(value, head.prev, head);
		head.prev.next = cur;
		head.prev = cur;
		size++;
	}

	/**
	 * 删除位置为index的节点
	 * 
	 * @param index
	 */
	public void delete(int index) {
		rangeCheck(index);
		Node<E> cur = getNode(index);
		cur.prev.next = cur.next;
		cur.next.prev = cur.prev;
		size--;
		cur = null;
	}

	/**
	 * 删除第一个节点
	 */
	public void deleteFirst() {
		delete(0);
	}

	/**
	 * 删除最后一个节点
	 */
	public void deleteLast() {
		delete(size - 1);
	}

	public static void main(String[] args) {
		DoubleLink<Integer> dl = new DoubleLink<Integer>();
		// Node<Integer> n1 = new Node<Integer>(1, dl.head, dl.head);
		dl.insert(0, 1);
		dl.insert(1, 2);
		dl.insert(2, 3);
		dl.insert(3, 4);
		// dl.addFirst(5);
		// dl.addLast(6);
		dl.deleteLast();
		// System.out.println(dl.getLast());
		// dl.removeFirst();
		// System.out.println(dl.get(1));
		for (int i = 0; i < dl.size; i++) {
			System.out.print(dl.get(i) + " ");
		}
	}

}

  • 1
    点赞
  • 0
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

俊雪恋

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值