Java 实现双向链表

双向链表:

就是有双向指针 即 双向的链域

链结点的结构:

┌────┬────┬────────┐

│data│next│previous│

└────┴────┴────────┘

双向链表不必是双端链表(持有对最后一个链结点的引用),双端链表插入时是双向的

有两条链:一条从头到尾,一条从尾到头,删除遍历时也是双向的

/**
 * 双向链表
 *
 * @author stone
 */
public class DoublyLinkedList<T> {
	private Link<T> head;		//首结点
	private Link<T> rear;		//尾部指针

	public DoublyLinkedList() {

	}

	public T peekHead() {
		if (head != null) {
			return head.data;
		}
		return null;
	}

	public boolean isEmpty() {
		return head == null;
	}

	public void insertFirst(T data) {// 插入 到 链头
		Link<T> newLink = new Link<T>(data);
		if (isEmpty()) {//为空时,第1次插入的新结点为尾结点
			rear = newLink;
		} else {
			head.previous = newLink; //旧头结点的上结点等于新结点
		}
		newLink.next = head; //新结点的下结点旧头结点
		head = newLink; //赋值后,头结点的下结点是旧头结点,上结点null
	}

	public void insertLast(T data) {//在链尾 插入
		Link<T> newLink = new Link<T>(data);
		if (isEmpty()) {
			head = newLink;
		} else {
			rear.next = newLink;
		}
		newLink.previous = rear;
		rear = newLink; //赋值后,尾结点的上结点是旧尾结点,下结点null
	}

	public T  deleteHead() {//删除 链头
		if (isEmpty()) return null;
		Link<T> temp = head;
		head = head.next; //变更首结点,为下一结点
		if (head != null) {
			head.previous = null;
		} else {
			rear = null;
		}
		return temp.data;
	}

	public T  deleteRear() {//删除 链尾
		if (isEmpty()) return null;
		Link<T> temp = rear;
		rear = rear.previous; //变更尾结点,为上一结点
		if (rear != null) {
			rear.next = null;
		} else {
			head = null;
		}
		return temp.data;
	}

	public T find(T t) {//从头到尾find
		if (isEmpty()) {
			return null;
		}
		Link<T> find = head;
		while (find != null) {
			if (!find.data.equals(t)) {
				find = find.next;
			} else {
				break;
			}
		}
		if (find == null) {
			return null;
		}
		return find.data;
 	}

	public T delete(T t) {
		if (isEmpty()) {
			return null;
		}
		Link<T> current = head;
		while (!current.data.equals(t)) {
			current = current.next;
			if (current == null) {
				return null;
			}
		}
		if (current == head) {
			head = head.next;
			if (head != null) {
				head.previous = null;
			}
		} else if (current == rear) {
			rear = rear.previous;
			if (rear != null) {
				rear.next = null;
			}
		} else {
			//中间的非两端的结点,要移除current
			current.next.previous = current.previous;
			current.previous.next = current.next;
		}
		return current.data;
	}

	public boolean insertAfter(T key, T data) {//插入在key之后, key不存在return false
		if (isEmpty()) {
			return false;
		}
		Link<T> current = head;
		while (!current.data.equals(key)) {
			current = current.next;
			if (current == null) {
				return false;
			}
		}
		Link<T> newLink = new Link<T>(data);
/*		if (current == head) {//若为头,考虑头的后指针,原头后指针的前指针,新链结点的前后指针
			newLink.next = current.next;
			current.next.previous = newLink;
//			newLink.previous = current;
//			current.next = newLink;
		} else if (current == rear) {
//			newLink.next = null;
			rear = newLink;
//			current.next = newLink;
//			newLink.previous = current;
		} else {
			newLink.next = current.next;
			current.next.previous = newLink;
//			current.next = newLink;
//			newLink.previous = current;
		}*/
		//上面的判断简写成:
		if (current == rear) {
			rear = newLink;
		} else {
			newLink.next = current.next;
			current.next.previous = newLink;
		}
		current.next = newLink;
		newLink.previous = current;
		return true;
	}

	public void displayList4Head() {//从头开始遍历
		System.out.println("List (first-->last):");
		Link<T> current = head;
		while (current != null) {
			current.displayLink();
			current = current.next;
		}
	}
	public void displayList4Rear() {//从尾开始遍历
		System.out.println("List (last-->first):");
		Link<T> current = rear;
		while (current != null) {
			current.displayLink();
			current = current.previous;
		}
	}

	class Link<T> {//链结点
		T data;		//数据域
		Link<T> next; //后继指针,结点			链域
		Link<T> previous; //前驱指针,结点		链域
		Link(T data) {
			this.data = data;
		}
		void displayLink() {
			System.out.println("the data is " + data.toString());
		}
	}

	public static void main(String[] args) {
		DoublyLinkedList<Integer> list = new DoublyLinkedList<Integer>();
		list.insertLast(1);
		list.insertFirst(2);
		list.insertLast(3);
		list.insertFirst(4);
		list.insertLast(5);
		list.displayList4Head();

		Integer deleteHead = list.deleteHead();
		System.out.println("deleteHead:" + deleteHead);
		list.displayList4Head();

		Integer deleteRear = list.deleteRear();
		System.out.println("deleteRear:" + deleteRear);
		list.displayList4Rear();

		System.out.println("find:" + list.find(6));
		System.out.println("find:" + list.find(3));

		System.out.println("delete find:" + list.delete(6));
		System.out.println("delete find:" + list.delete(1));
		list.displayList4Head();

		System.out.println("----在指定key后插入----");
		list.insertAfter(2, 8);
		list.insertAfter(2, 9);
		list.insertAfter(9, 10);
		list.displayList4Head();
	}
}

打印

List (first-->last):
the data is 4
the data is 2
the data is 1
the data is 3
the data is 5
deleteHead:4
List (first-->last):
the data is 2
the data is 1
the data is 3
the data is 5
deleteRear:5
List (last-->first):
the data is 3
the data is 1
the data is 2
find:null
find:3
delete find:null
delete find:1
List (first-->last):
the data is 2
the data is 3
----在指定key后插入----
List (first-->last):
the data is 2
the data is 9
the data is 10
the data is 8
the data is 3
时间: 2024-10-11 06:18:36

Java 实现双向链表的相关文章

java实现双向链表

java实现循环链表:http://www.cnblogs.com/lixiaolun/p/4643911.html 在单链表中,查询下一个元素的时间是O(1).查询上一个元素的时间却是O(n). 为了克服这种缺点,我们开始学习双向链表. 双向链表类的代码: package doublelinkedlist; public class DoubleLinkedList { class Element { private Element prior=null; public Object valu

Java中双向链表的代码实现

写在前面: 双向链表是一种对称结构,它克服了单链表上指针单向性的缺点,其中每一个节点即可向前引用,也可向后引用,这样可以更方便的插入.删除数据元素. 由于双向链表需要同时维护两个方向的指针,因此添加节点.删除节点时指针维护成本更大:但双向链表具有两个方向的指针,因此可以向两个方向搜索节点,因此双向链表在搜索节点.删除指定索引处节点时具有较好的性能. Java语言实现双向链表: 1 package com.ietree.basic.datastructure.dublinklist; 2 3 /*

大话数据结构(八)Java程序——双向链表的实现

线性链表--双向链表 双向链表定义: 双向链表(double linked list): 是在单表单的每个结点中,再设置一个指向前驱结点的指针域.因此,在双向链表中的结点都有两个指针域,一个指向前驱,一个指向后继. 双向链表的存储结构 typedef struts DulNode{ Element data; Struct DulNode *prior;前驱指针 Struct DulNode *next;后继指针 }DulDouble, *DulLinkList; 双向链表的插入与删除 双向链表

Java 自定义双向链表

双向链表 LinkedList其实也就是我们在数据结构中的链表,这种数据结构有这样的特性: 分配内存空间不是必须是连续的:插入.删除操作很快,只要修改前后指针就OK了,时间复杂度为O(1):访问比较慢,必须得从第一个元素开始遍历,时间复杂度为O(n):在Java中,LinkedList提供了丰富的方法,可以模拟链式队列,链式堆栈等数据结构,为用户带来了极大的方便,下面我们来自定义一个双向链表(目的了解底层实现原理) 自定义节点结构 1 // 自定义节点结构 2 class Node { 3 No

Java:双向链表反转实现

有个小需求要求实现一个双向链表的反转于是就有了下边代码: 链表元素结构定义: package com.util; public class LinkedNode<T>{ private T value; private LinkedNode<T> prev; private LinkedNode<T> next; public LinkedNode(T value, LinkedNode<T> prev, LinkedNode<T> next)

Java数据结构——双向链表

什么是双向链表?每一个结点不仅配有next引用,同时还有一个prev引用,指向其上一个结点(前驱结点), 没有前驱的时候就为NULL. (以下图片均来自网络,侵删) 与单链表的区别?和单向链表相比有以下优势: 插入删除不需要移动元素外,可以原地插入删除 可以双向遍历 插入操作 删除操作 实现 public class DLNode { Object data; DLNode prev; DLNode next; static DLNode head; static DLNode tail; //

java集合框架04——LinkedList和源码分析

上一章学习了ArrayList,并分析了其源码,这一章我们将对LinkedList的具体实现进行详细的学习.依然遵循上一章的步骤,先对LinkedList有个整体的认识,然后学习它的源码,深入剖析LinkedList. LinkedList简介 首先看看LinkedList与Collection的关系: LinkedList的继承关系如下: java.lang.Object ? java.util.AbstractCollection<E> ? java.util.AbstractList&l

Java集合深入学习总结-LinkedHashMap

1. LinkedHashMap概述: LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表.此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序. 注意,此实现不是同步的.如果多个线程同时访问链接的哈希映射,而其中至少一个线程从结构

深入Java集合学习系列:LinkedHashMap的实现原理

1. LinkedHashMap概述: LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变.   LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表.此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序.   注意,此实现不是同步的.如果多个线程同时访问链接的哈希映射,而其中至少一个线