Java版双向链表实现

Java版双向链表实现

  双向链表是每个结点有两个地址域的线性链表,两个地址域分别指向前结点和后结点,结果如下:

  双链表结点(prev 前驱结点地址域;data 数据域;next 后继结点地址域)

1、双链表结点类

public class DoubleNode<T> {

	public T data;//数据域
	public DoubleNode<T> prev;//前驱结点
	public DoubleNode<T> next;//后继结点

	/**
	 * 创建一个空结点
	 */
	public DoubleNode() {
		this(null, null, null);
	}

	public DoubleNode(DoubleNode<T> prev, T data, DoubleNode<T> next) {
		this.prev = prev;
		this.data = data;
		this.next = next;
	}
}
2、双链表特性和操作

空双链表,只有头结点,head.next == null且head.prev == null;


非空双链表


双链表的插入操作

  在双链表中插入一个结点,可在指定结点之前或之后插入。设p指向双链表的某个结点,在p结点之前插入值为x的结点操作和语句如下



前插入有两种插入方式代码及图解如下:

方式一:

                        newNode.prev = p.prev;
			newNode.next = p;
			p.prev.next = newNode;
			p.prev = newNode;

方式二:

                        newNode.prev = p.prev;
			p.prev.next = newNode;
			newNode.next = p;
			p.prev = newNode;

   两种方式其实基本差不多,这里有个重点是不能先断开p结点与前驱结点的连接,否则就无法找到前驱结点了。

双链表的删除操作

                        p.prev.next = p.next;
			p.next.prev = p.prev;

双向链表的完整代码如下:

public class DoubleList<T> {

	public DoubleNode<T> head;

	public DoubleList() {
		head = new DoubleNode<T>();// 创建空头结点,data和prev、next为null
	}

	/**
	 * 判断双向链表是否为空
	 */
	public boolean isEmpty() {
		return this.head.next == null;
	}

	/**
	 * 链表长度
	 */
	public int size() {
		int length = 0;
		DoubleNode<T> p = this.head.next;
		while (p != null) {
			length++;
			p = p.next;
		}
		return length;
	}

	/**
	 * 定位第i个结点数据
	 * 
	 * @return
	 */
	public DoubleNode<T> locationNode(int i) {

		if (i < 0 || i > size()) {
			throw new IndexOutOfBoundsException("位置 i 没有找到,无法定位");
		} else {
			DoubleNode<T> p = this.head.next;
			int index = 0;
			while (p != null) {
				if (i == index) {
					return p;
				}
				index++;
				p = p.next;

			}
		}
		return null;
	}

	/**
	 * 将新结点插入到链表结尾
	 */
	public void insert(T data) {
		if (data == null) {
			throw new NullPointerException("data = null");
		}
		
		DoubleNode<T> newNode = new DoubleNode<T>(null, data, null);
		DoubleNode<T> p = this.head.next;
		if (p == null) {
			head.next = newNode;
			newNode.prev = head;
		} else {
			p = locationNode(size() - 1);//链表最后的结点位置是size-1
			p.next = newNode;
			newNode.prev = p;
		}
	}

	/**
	 * 将新结点插入第i个位置,相当于在原i结点之前插入
	 * 
	 * @param i
	 *            第i个位置
	 * @param data数据
	 */
	public void insert(int i, T data) {
		if (data == null) {
			throw new NullPointerException("data = null");
		}
		DoubleNode<T> p;
		DoubleNode<T> newNode = new DoubleNode<T>(null, data, null);
		if (isEmpty()) {//如果链表为空,则插入第0个结点
			p = head.next;
			p.next = newNode;
			newNode.prev = p;
		} else {
			p = locationNode(i);//定位第i个结点位置,新结点插入p结点之前

			newNode.prev = p.prev;
			newNode.next = p;
			p.prev.next = newNode;
			p.prev = newNode;
			
			newNode.prev = p.prev;
			p.prev.next = newNode;
			newNode.next = p;
			p.prev = newNode;
			
		}
	}
	

	/**
	 * 删除第i个结点
	 */
	public void delete(int i) {

		if (i < 0 || i > size()) {
			throw new IndexOutOfBoundsException("位置 i 没有找到,无法删除");
		}

		if (isEmpty()) {
			throw new NullPointerException("链表为空");
		} else {
			DoubleNode<T> p = locationNode(i);//定位第i个结点位置
			p.prev.next = p.next;
			p.next.prev = p.prev;
		}

	}

	/**
	 * 遍历双向链表
	 */
	public void display() {
		DoubleNode<T> p = this.head.next;
		if (p == null) {
			System.out.println("DoubleList is null");
		} else {
			while (p != null) {
				System.out.print(p.data.toString() + " ");
				p = p.next;
			}
		}
	}

	public static void main(String[] args) {
		DoubleList<String> list = new DoubleList<String>();
		list.insert("a");
		list.insert("b");
		list.insert("c");
		list.insert("d");
		list.insert("e");
		
		list.delete(1);

		System.out.println(list.size());
		list.display();
	}

}

运行结果如下:

4
a c d e 



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* * 基于双向链表实现双端队列结构 */ package dsa; public class Deque_DLNode implements Deque { protected DLNode header;//指向头节点(哨兵) protected DLNode trailer;//指向尾节点(哨兵) protected int size;//队列中元素的数目 //构造函数 public Deque_DLNode() { header = new DLNode(); trailer = new DLNode(); header.setNext(trailer); trailer.setPrev(header); size = 0; } //返回队列中元素数目 public int getSize() { return size; } //判断队列是否为空 public boolean isEmpty() { return (0 == size) ? true : false; } //取首元素(但不删除) public Object first() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return header.getNext().getElem(); } //取末元素(但不删除) public Object last() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return trailer.getPrev().getElem(); } //在队列前端插入新节点 public void insertFirst(Object obj) { DLNode second = header.getNext(); DLNode first = new DLNode(obj, header, second); second.setPrev(first); header.setNext(first); size++; } //在队列后端插入新节点 public void insertLast(Object obj) { DLNode second = trailer.getPrev(); DLNode first = new DLNode(obj, second, trailer); second.setNext(first); trailer.setPrev(first); size++; } //删除首节点 public Object removeFirst() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = header.getNext(); DLNode second = first.getNext(); Object obj = first.getElem(); header.setNext(second); second.setPrev(header); size--; return(obj); } //删除末节点 public Object removeLast() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = trailer.getPrev(); DLNode second = first.getPrev(); Object obj = first.getElem(); trailer.setPrev(second); second.setNext(trailer); size--; return(obj); } //遍历 public void Traversal() { DLNode p = header.getNext(); while (p != trailer) { System.out.print(p.getElem()+" "); p = p.getNex

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值