双链表的java实现

直接上代码,错误地方请指正。

class Node {
	Node prior; 		// 结点头指针
	Node next; 			// 结点尾指针
	Object data; 		// 数据域

	public Node(Object data) {
		super();
		this.data = data;
	}
}

class MyLinkedList {
	private Node head; 			// 首结点
	private Node tail; 			// 尾结点
	private int size; 			// 统计链表长度

	// 链尾增加
	public void add(Object obj) {
		Node newNode = new Node(obj);
		if (head == null) { 				// 首节点为空时首尾结点指针都指向新结点
			head = newNode;
			tail = newNode;
		} else { 							// 否则尾结点与新结点建立联系后重新调整尾结点指针指向新结点
			tail.next = newNode;
			newNode.prior = tail;
			tail = newNode;
		}
		size++;
	}

	// 指定位置插入
	public void insert(int index, Object obj) {
		checkIndex(index);
		Node newNode = new Node(obj);
		if (index == 1) { 							// 插入位置是首结点
			newNode.next = head; 					// 新结点尾指针指向首结点
			head.prior = newNode; 					// 首结点头指针指向新结点
			head = newNode; 						// 首结点指针指向新结点
		} else {
			Node current = getNode(index); 			// 否则获取指定位置结点current
			Node before = current.prior; 			// 获取current结点的前一个结点
			before.next = newNode; 					// 前一个结点尾指针指向新结点
			newNode.prior = before; 				// 新结点头指针指向前一个结点
			newNode.next = current; 				// 新结点尾指针指向current结点
			current.prior = newNode; 				// current结点头指针指向新结点
		}
		size++;
	}

	// 指定位置删除
	public void remove(int index) {
		checkIndex(index);
		Node current = getNode(index); 				// 获取要删除结点
		if (index == 1) { 							// 要删除结点是头结点则直接将head指针后移
			head = current.next;
		} else {
			Node before = current.prior; 			// 否则获取要删除结点的上一个结点
			Node after = current.next; 				// 获取要删除结点的下一个结点
			before.next = after; 					// 上一个结点的尾指针指向删除结点的下一个节点
			if (after != null) 						// 如果下一个结点存在则让下个结点前指针指向删除结点的上一个结点
				after.prior = before;
		}
		current = null; 							// 释放空间
		size--;
	}

	// 指定位置修改
	public void set(int index, Object obj) {
		checkIndex(index);
		getNode(index).data = obj;
	}

	// 判断操作索引是否越界
	private void checkIndex(int index) {
		if (index < 1 || index > size)
			throw new RuntimeException("索引不合法,合法索引范围:1<=index<=" + size);
	}

	// 获取指定索引的结点
	private Node getNode(int index) {
		checkIndex(index);
		Node current = null;
		if (index < (size >> 1)) {					// 索引在前半部分从前往后查找
			current = head;
			for (int i = 1; i < index; i++)
				current = current.next;
		} else {									// 否则从后往前查找
			current = tail;
			for (int i = size; i > index; i--)
				current = current.prior;
		}
		return current;
	}

	// 重写toString方法打印链表内容
	public String toString() {
		StringBuilder sb = new StringBuilder("[");
		Node current = head;
		if (current == null) {
			sb.append("]");
		} else {
			while (current != null) {
				sb.append(current.data + ",");
				current = current.next;
			}
			sb.setCharAt(sb.length() - 1, ']');
		}
		return sb.toString();
	}
}

// 测试
public class Test {
	public static void main(String[] args) {
		MyLinkedList list = new MyLinkedList();
		list.add(1);
		list.add(2);
		System.out.println(list);
		list.insert(1, 3);
		System.out.println(list);
		list.set(1, 0);
		System.out.println(list);
		list.remove(2);
		System.out.println(list);
		list.remove(2);
		System.out.println(list);
		list.remove(1);
		System.out.println(list);
	}
}

测试结果
在这里插入图片描述
双链表主要克服了单链表单向查找的缺点,在查找某个结点的前驱结点时可以从这个结点直接出发而不必从头结点开始,但因为比单链表多了一个指针域所以也降低了数据的存储密度(存储密度=数据元素本身占据的存储量÷结点结构占用的存储量)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值