双向链表结构实现

本文转自 :双向链表代码实现和详解—java实现 有少许改动

双向链表:
双向链表是可以正向遍历链表节点和反向遍历链表节点的一种链表数据结构。在单向链表中,每个节点只有一个指向下一个节点的引用,在双向链表中节点添加一个指向前一个节点的引用,添加相应的反向遍历方法,即可实现访问前一个节点的。
添加和删除节点时需要解决四个指向(引用)操作,相对来说更复杂,但是解决好在边界处链表头部和尾部节点的添加和删除操作后,编码变得相对容易。

代码实现:

package algorithms.model;

public class DoublyLinkList<T> {
	private Link<T> first;
	private Link<T> last;
	public DoublyLinkList(){
		this.first = null;
		this.last = null;
	}
	@SuppressWarnings("hiding")
	class Link<T>{
    	public T val;
    	public Link<T> next;
    	public Link<T> pre;
    	public Link(T val){
    		this.val = val;
    	}
    	public void showCurrentNode(){
    		System.out.print(this.val+" ");
    	}
    }
	public boolean isEmpty(){
		return first == null;
	}
	//处理好每个节点的前后指向是关键;先处理哪个节点的哪个指向问题;
	public void addFirst(T value){
		Link<T> newLink = new Link<T>(value);
		if(isEmpty())  
			last = newLink;         //保证last正确引用;
		else{
			first.pre = newLink;  
			newLink.next = first;
		}   
		first = newLink; 
		//newLink.pre = null;
	}
	public void addLast(T value){
		Link<T> newLink = new Link<T>(value);
		if(isEmpty())
			first = newLink;    //保证first正确引用;
		else{
			last.next = newLink;
			newLink.pre = last;
		} 
		last = newLink;	
		//newLink.next = null;
	}
	//先考虑普遍性,再考虑特殊性;在找到的第一个key前面插入
	public boolean addBefore(T key, T value){
		Link<T> cur = first;
	    if(first.val == key){
	    	addFirst(value);
	    	return true;
	    }
	    else{
	    	while(cur.val != key){
	    		cur = cur.next;
		    	if(cur == null)
		    		return false;
	    	} 
	    }
	    //断开连接后保证断开前指向的连接还能获取到;
	    Link<T> newLink = new Link<T>(value);	
	    cur.pre.next = newLink;
	    newLink.pre = cur.pre;
	    newLink.next = cur;
	    cur.pre = newLink;
	    return true;  
	}
	public boolean addAfter(T key, T value){
		Link<T> cur = first;
		while(cur.val != key && cur != null)
			cur = cur.next;
		if(cur == null)
			return false;
		if(cur == last){
			addLast(value);
			return true;
		}
		Link<T> newLink = new Link<T>(value);	
		cur.next.pre = newLink;
		newLink.next = cur.next;
		cur.next = newLink;
		newLink.pre = cur; 
		return true; 
	}
	public void deleteFirst(){ 
		if(first.next == null)    //链表没有节点或者仅含有一个节点时;
			last = null;
		else
			first.next.pre = null;//链表至少含有两个节点时;
		first = first.next;
	}
	public void deleteLast(){
		if(first.next == null)    //链表没有节点或者仅含有一个节点时;
			first = null;
		else
			last.pre.next = null;//链表至少含有两个节点时;
		last = last.pre;
			
	}
	public Link<T> deleteKey(T key){//删除第一找到的键
		Link<T> cur = first;
		while(cur.val != key){
			cur = cur.next; 
			if(cur == null)
				return null;
		}
		if(cur == first) 
			first = first.next; //保证first引用的指向正确; 
		else 
			cur.pre.next = cur.next; 
		if(cur == last)
			last = last.pre;    //保证last引用的指向正确;
		else
            cur.next.pre = cur.pre; 
		return cur;
	}
	public T showPre(T value){
		Link<T> cur = first;
		if(value == first.val)
			return null;
		while(cur.next.val != value){
			cur = cur.next;
			if(cur.next == null)
				return null;
		}
		return cur.val;
	}
	public void showForward(){
		Link<T> cur = first;
		while(cur != null){
			cur.showCurrentNode();
			cur = cur.next;
		}
		System.out.println();
	}
	public void showBackward(){
		Link<T> cur = last;
		while(cur != null){
			cur.showCurrentNode();
			cur = cur.pre;
		}
		System.out.println();
	}
    
	public static void main(String[] args) {
		 DoublyLinkList<Integer> d = new DoublyLinkList<Integer>();
		 for(int i = 1; i < 6; i++)
			 d.addFirst(i);
		 for(int i = 6; i < 10; i++)
			 d.addLast(i);
		 d.showForward();
		 d.showBackward();
		 System.out.println(d.showPre(4));
		 System.out.println(d.showPre(0));
		 d.deleteFirst();
		 d.showForward();
		 d.deleteLast();
		 d.showForward();
		 d.deleteKey(1);
		 d.showForward();
		 d.addAfter(6, 11);
		 d.showForward();
		 d.addBefore(6, 12);
		 d.showForward();
	}

}

输出:

5 4 3 2 1 6 7 8 9 
9 8 7 6 1 2 3 4 5 
5
null
4 3 2 1 6 7 8 9 
4 3 2 1 6 7 8 
4 3 2 6 7 8 
4 3 2 6 11 7 8 
4 3 2 12 6 11 7 8 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值