Java雙向連結串列的實現

君墨痕發表於2013-11-28

原文地址:http://blog.csdn.net/yangchuxi/article/details/6621057

看連結串列的時候還是用c中指標那種思維來思考比較容易理解,c很久以前學的都忘得差不多了,需要補補鳥……

在上面文章所寫的基礎上拿來改了下,新增了類似list集合get()方法,直接通過索引得到節點物件,節點物件裡的Object成員變數就是用來儲存資料,可以在這個基礎你在自己封裝一下,我就部封裝鳥……


/**
* @Description : 描述
* @author YangXuan
* @email 364105996@qq.com
* @date 2013-11-28 上午12:35:19
*/
public class TWLink {

	/**
	 * @Description : 節點實體
	 */
	@SuppressWarnings("hiding")
	class Node<Object> {
		private Object object;
		private Node<Object> next;
		private Node<Object> pre;

		public Node(Object object) {
			this.object = object;
			this.next = null;
			this.pre = null;
		}

		public String toString() {
			return object.toString();
		}
	}

	private Node<Object> head;
	private int size;

	/**
	 * 連結串列的初始化
	 */
	public TWLink() {
		size = 0;
		head = new Node<Object>(null);
		head.next = null;
		head.pre = null;
	}

	/**
	 * 插入到連結串列前段(表頭之後)
	 */
	public boolean insertFirst(Node<Object> node) {
		if (node != null) {
			if (head.next != null) {
				node.pre = head;
				node.next = head.next;
				head.next.pre = node;
				head.next = node;
			} else {
				head.next = node;
				node.pre = head;
			}
			size++;
			return true;
		}
		return false;
	}

	/**
	 * 插入到連結串列的末尾
	 */
	public boolean insertLast(Node<Object> node) {
		if (node != null) {
			Node<Object> current = head;
			while (current.next != null) {
				current = current.next;
			}
			current.next = node;
			node.pre = current;
			size++;
			return true;
		}
		return false;
	}

	/**
	 * 在指定節點node1後插入節點node2
	 */
	public boolean insertInto(Node<Object> node1, Node<Object> node2) {
		if (node1 != null && node2 != null) {
			// 先遍歷這個連結串列,看看有沒有等於node1
			Node<Object> current = head;
			while (current != node1) {
				current = current.next;
				if (current == null) {
					System.out.println("不存在節點 " + node1.toString() + ",無法插入節點 "
							+ node2.toString());
					return false;
				}
			}

			// 此時的current如果是最後一個節點,這呼叫 insertLast()方法插入到最後
			if (current.next == null) {
				insertLast(node2);
				size++;
				return true;
			}

			node2.pre = current;
			node2.next = current.next;
			current.next.pre = node2;
			current.next = node2;
			size++;
			return true;
		}
		return false;
	}

	/**
	 * 刪除連結串列前端節點
	 */
	public boolean deleteHead() {
		if (head.next != null) {
			if (head.next.next != null) {
				// Node<Object> current = head.next;
				// head.next = current.next;
				// current.next.pre = head;
				// current = null;
				head.next = head.next.next;
				head.next.pre = head;
				size--;
				return true;
			} else {
				head.next = null;
				size--;
			}

		}
		return false;
	}

	/**
	 * 刪除尾節點
	 */
	public void deleteEnd() {
		Node<Object> current = head;
		while (current.next != null) {
			current = current.next;
		}
		// Node<Object> pre = current.pre;
		// pre.next = null;
		// current = null;
		current.pre.next = null;
		size--;
	}

	/**
	 * 刪除指定節點
	 */
	public boolean deleteNode(Node<Object> node) {
		if (node != null) {
			Node<Object> current = head;
			while (current != node) {
				current = current.next;
				if (current == null) {
					return false;
				}
			}

			if (node == head.next) {
				return deleteHead();
			}

			// 儲存與node相等的值
			Node<Object> acurrent = current;
			while (current.next != null) {
				current = current.next;
			}
			if (current == node) {
				deleteEnd();
				return true;
			}

			Node<Object> pre = acurrent.pre;
			Node<Object> next = acurrent.next;
			pre.next = next;
			next.pre = pre;
			acurrent = null;
			size--;
			return true;
		}
		return false;
	}

	public Node<Object> get(int index) {
		if (index < 0 || index >= size) {
			System.out.println("索引超過範圍!");
			throw new IllegalAccessError("索引超過範圍!");
		}

		Node<Object> current = head;
		for (int i = 0; i < size - index; i++) {
			current = current.next;
		}
		return current;
	}

	/**
	 * 連結串列長度
	 */
	public int getSize() {
		return size;
	}

	/**
	 * 正序和反序遍歷遍歷連結串列並列印
	 */
	public void display() {
		Node<Object> current = head.next;
		if (current != null) {
			Node<Object> tail = null;

			System.out.println("正序輸出:");
			while (current != null) {
				System.out.println(current.toString());
				tail = current;
				current = current.next;
			}

			System.out.println("反序輸出:");
			while (tail != head) {
				if (tail != null) {
					System.out.println(tail.toString());
				}
				tail = tail.pre;
			}
			System.out.println("連結串列大小:" + getSize());
		} else {
			System.out.println("連結串列為空!");
		}

	}

	@Test
	public void myTest() {
		TWLink twl = new TWLink();
		Node<Object> node1 = new Node<Object>("AAA");
		Node<Object> node2 = new Node<Object>("BBB");
		Node<Object> node3 = new Node<Object>("CCC");
		Node<Object> node4 = new Node<Object>("DDD");

		twl.insertFirst(node1);
		twl.insertFirst(node2);
		twl.insertFirst(node3);
		twl.insertFirst(node4);

		twl.display();

		for (int i = 0; i < twl.getSize(); i++) {
			System.out.println(twl.get(i).toString());
		}
		

	}
}
順帶附一張草稿圖便於理解

相關文章