双向链表实例---解决两端极限问题

    数据结构上有关双向链表的原理:在单链表(每个节点含后继节点)的每个节点里再增加一个指向其前趋的节点,这样形成的链表含有指向前趋和后继两个方向的链,称为双向链表。网上找了个例子研究了下(http://www.cnblogs.com/matrix1024/archive/2011/12/31/2308380.html),解决原作者的两端极限时出现的空指针问题。
    上代码:

Node实体类:
/** 
 * @projectName:List 
 * @fileName:Node.java 
 * @packageName:club.younge.list 
 * @date:2016年8月25日上午12:17:17 
 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. 
 * 
 */  
  
package club.younge.list;  
/** 
 * @className:Node 
 * @function: 双向链表节点实体类  
 * @reason:    
 * @date:     2016年8月25日 上午12:17:17
 * @author   Younge 
 * @version   
 * @since    JDK 1.8 
 * @see       
 */
public class Node<T> {
	private T data;
	private Node<T> next;
	private Node<T> prev;
	
	public Node() {
		
	}
	public Node(T data) {
		this.data = data;
	}
	//实现equals和hashCode, 两个最好一同改写
	public boolean equals(Node<T> node) {
		if (data.equals(node.getData())) {
			return true;
		}
		return false;
	}
	
	@Override
	public int hashCode() {
		return data.hashCode();
	}
	
	@Override
	public String toString() {
		return data.toString();
	}
	
	public T getData() {
		return data;
	}
	public void setData(T data) {
		this.data = data;
	}
	public Node<T> getNext() {
		return next;
	}
	public void setNext(Node<T> next) {
		this.next = next;
	}
	public Node<T> getPrev() {
		return prev;
	}
	public void setPrev(Node<T> prev) {
		this.prev = prev;
	}
	
}


BirectionalLinkedList链表操作类:
/** 
 * @projectName:List 
 * @fileName:BirectionalLinkedList.java 
 * @packageName:club.younge.list 
 * @date:2016年8月25日上午12:22:51 
 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. 
 * 
 */

package club.younge.list;

/**
 * @className:BirectionalLinkedList
 * @function: 双向链表操作类
 * @reason: 
 * @date: 2016年8月25日 上午12:22:51
 * @author Younge
 * @version
 * @since JDK 1.8
 * @see
 */
public class BirectionalLinkedList<T> {
	private Node<T> head;
	private Node<T> tail;

	public BirectionalLinkedList() {
		head = new Node<T>();
		tail = new Node<T>();
	}

	public void insertAfterHead(Node<T> data) {
		if (head.getNext() == null) {// 头节点后还没有节点,说明链表为空,也可以通过尾节点的前一个节点是否为空作出判断
			head.setNext(data);
			data.setPrev(head);
			tail.setPrev(data);
			data.setNext(tail);
		} else {
			data.setNext(head.getNext()); // 改变该节点的后一个节点为头节点的下一个节点---该节点下一个节点
			head.getNext().setPrev(data); // 改变头节点的下一个节点的前一个节点为该节点---下一个节点的前一个节点
			// 打通该节点后的两个指向
			head.setNext(data); // 最后将头节点的下一个节点指向该节点
			// (若一开始指向该节点,则无法获取头节点的原始下一节点,觉得思路不清晰,可以分离出头节点的原始下一节点到一临时节点)
			data.setPrev(head); // 头节点没值
		}
	}

	public void insertBeforeTail(Node<T> data) {
		if (isEmpty()) {
			tail.setPrev(data);
			data.setNext(tail);
			head.setNext(data);
			data.setPrev(head);
		} else {
			data.setPrev(tail.getPrev());
			tail.getPrev().setNext(data);
			tail.setPrev(data);
			data.setNext(tail); // 尾节点没值
		}
	}

	// 添加某个节点到指定的数值的节点后面
	public void insertAfter(Node<T> data, T key) {
		if (isEmpty()) {
			System.out.println("The biretional linked list is empty!");
		} else {
			Node<T> temp = head;
			while (temp.getNext() != null) {
				if (temp.getNext().getData().equals(key)) {
					/*if (temp.getNext().getNext() == null) {
						temp.getNext().setNext(tail);
					}*/
					data.setNext(temp.getNext().getNext()); // 该节点的下一个节点
					temp.getNext().getNext().setPrev(data); // 下一个节点的前一个节点
					temp.getNext().setNext(data);
					data.setPrev(temp.getNext());
					break;
				}
				temp = temp.getNext();
			}
			
		}
	}

	// 添加某个节点到指定的数值的节点前面
	public void insertBefore(Node<T> data, T key) {
		if (isEmpty()) {
			System.out.println("The biretional linked list is empty!");
		} else {
			Node<T> temp = head;
			while (temp.getNext() != null) {
				if (temp.getNext().getData().equals(key)) {
					data.setNext(temp.getNext());
					temp.getNext().setPrev(data);
					temp.setNext(data); // temp.getNext().getPrev().setNext(data);
										// //前一个节点的下一个节点
					data.setPrev(temp); // data.setPrev(temp.getNext().getPrev());
										// //该节点的前一个节点
					break;
				}
				temp = temp.getNext();
			}
		}
	}

	public void traverseFromHead() {
		if (isEmpty()) {
			System.out.println("The biretional linked list is empty!");
		} else {
			Node<T> temp = head;
			while (temp.getNext() != null) {
				if (temp.getNext() == tail) {
					break;
				}
				System.out.print(temp.getNext() + "--->");
				temp = temp.getNext();
			}
			System.out.println();

		}
	}

	public void traverseFromTail() {
		if (isEmpty()) {
			System.out.println("The biretional linked list is empty!");
		} else {
			Node<T> temp = tail;
			while (temp.getPrev() != null) {
				if (temp.getPrev() == head) {
					break;
				}
				System.out.print(temp.getPrev() + "--->");
				temp = temp.getPrev();
			}
			System.out.println();

		}
	}

	public boolean isEmpty() {
		if (head.getNext() == null || tail.getPrev() == null) {
			return true;
		}
		return false;
	}
}

测试类:
/** 
 * @projectName:List 
 * @fileName:BirectionalLinkedListTest.java 
 * @packageName:club.younge.test 
 * @date:2016年8月25日上午1:10:52 
 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. 
 * 
 */  
  
package club.younge.test;

import club.younge.list.BirectionalLinkedList;
import club.younge.list.Node;

/** 
 * @className:BirectionalLinkedListTest 
 * @function: 双向链表测试类  
 * @reason:   TODO ADD REASON. 
 * @date:     2016年8月25日 上午1:10:52
 * @author   Younge 
 * @version   
 * @since    JDK 1.8 
 * @see       
 */
public class BirectionalLinkedListTest {
	
	public static void main(String[] args) {
		final int MAX = 6;
		BirectionalLinkedList<Integer> list = new BirectionalLinkedList<Integer>();
		System.out.println( "Form insert:");
		Node<Integer> node;
		for (int i = 0; i < MAX; i++) {
			node = new Node<Integer>(i);
			System.out.print(node + "--->");
			list.insertAfterHead(node);
		}
		System.out.println("\nTraverse from head:");
		list.traverseFromHead();
		System.out.println("Traverse from tail:");
		list.traverseFromTail();
		Node<Integer> node1 = new Node<Integer>(33);
		list.insertAfter(node1, 0);
		System.out.println("\nTraverse from head(insert 33 after 3):");
		list.traverseFromHead();
		System.out.println("Traverse from tail(insert 33 after 3):");
		list.traverseFromTail();
		
		Node<Integer> node2 = new Node<Integer>(66);
		list.insertBefore(node2, 5);
		System.out.println("\nTraverse from head(insert 66 before 5):");
		list.traverseFromHead();
		System.out.println("Traverse from tail(insert 66 before 5):");
		list.traverseFromTail();
	}
}

测试结果:
Form insert:
0--->1--->2--->3--->4--->5--->
Traverse from head:
5--->4--->3--->2--->1--->0--->
Traverse from tail:
0--->1--->2--->3--->4--->5--->

Traverse from head(insert 33 after 0):
5--->4--->3--->2--->1--->0--->33--->
Traverse from tail(insert 33 after 0):
33--->0--->1--->2--->3--->4--->5--->

Traverse from head(insert 66 before 5):
66--->5--->4--->3--->2--->1--->0--->33--->
Traverse from tail(insert 66 before 5):
33--->0--->1--->2--->3--->4--->5--->66--->



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值