• 双向链表学习笔记


    1.链表接口定义

    package com.ncs.datastructure.linklist;
    
    public interface ILinkList {
    
    	/**
    	 * 链表是否为空
    	 * @return
    	 */
    	public abstract boolean isEmpty();
    
    	/**
    	 * 在链表的第一个节点前插入节点
    	 * @param data
    	 */
    	public abstract void addToHead(Object data);
    
    	/**
    	 * 在链表的最后一个节点追加节点
    	 * @param data
    	 */
    	public abstract void addToTail(Object data);
    
    	/**
    	 * 删除链表中的第一个节点
    	 * @return
    	 */
    	public abstract Object deleteFromHead();
    
    	/**
    	 * 删除链表中的最后一个节点
    	 * @return
    	 */
    	public abstract Object deleteFromTail();
    
    	/**
    	 * 链表中是否存在指定的节点
    	 * @param data
    	 * @return
    	 */
    	public abstract boolean isContains(Object data);
    
    	/**
    	 * 删除指定的节点
    	 * @param data
    	 */
    	public abstract void deleteNode(Object data);
    
    }

    2.双向链表的简单实现

    package com.ncs.datastructure.linklist;
    
    import com.ncs.datastructure.linklist.SingleLinkList.Node;
    
    
    /**
     * 双向链表的简单实现
     * @author yuanli
     *
     */
    public class DoubleLinkList implements ILinkList {
    	
    	/**
    	 * 之所以定义为内部类,是因为用户并不关心链表节点的结构,而只关心链表存储的数据
    	 * @author yuanli
    	 *
    	 */
    	public class Node {
    		
    		//数据域
    		private Object data;
    		
    		//前驱节点
    		private Node prev;
    		
    		//后继节点
    		private Node next;
    
    		public Node() {
    			super();
    		}
    
    		public Node(Object data) {
    			this(data, null, null);
    		}
    		
    		public Node(Object data, Node prev, Node next) {
    			super();
    			this.data = data;
    			this.prev = prev;
    			this.next = next;
    		}
    
    		public Object getData() {
    			return data;
    		}
    
    		public void setData(Object data) {
    			this.data = data;
    		}
    
    		public Node getPrev() {
    			return prev;
    		}
    
    		public void setPrev(Node prev) {
    			this.prev = prev;
    		}
    
    		public Node getNext() {
    			return next;
    		}
    
    		public void setNext(Node next) {
    			this.next = next;
    		}
    		
    		
    	}
    	
    	//表示链表的第一个节点
    	protected Node head;
    	
    	//表示链表的最后一个节点
    	protected Node tail;
    
    	public void addToHead(Object data) {
    		if (this.head == null) {
    			this.head = new Node(data);
    			if (this.tail == null ) this.tail = this.head;
    		} else {
    			Node temp = new Node(data,null,this.head);
    			this.head.prev = temp;
    			this.head = temp;
    		}
    	}
    
    	public void addToTail(Object data) {
    		if (!isEmpty()) {
    			this.tail = new Node(data, this.tail, null);
    			this.tail.prev.next = this.tail;
    		} else {
    			this.tail = this.head = new Node(data); 
    		}
    	}
    
    	public Object deleteFromHead() {
    		Node delete = null;
    		if (this.head == this.tail) {
    			delete = this.head;
    			this.head = this.tail = null;
    		} else {
    			delete = this.head;
    			this.head = this.head.next;
    			this.head.prev = null;
    		}
    		return delete;
    	}
    
    	public Object deleteFromTail() {
    		Node delete = null;
    		if (this.head == this.tail) {
    			delete = this.head;
    			this.head = this.tail = null;
    		} else {
    			delete = this.tail;
    			this.tail = this.tail.prev;
    			this.tail.next = null;
    		}
    		return delete;
    	}
    
    	public void deleteNode(Object data) {
    		if (!isEmpty()) {
    			//如果只有一个节点
    			if (this.head == this.tail) {
    				this.head = this.tail = null;
    				return;
    			}
    			//如果是删除第一个节点
    			if (this.head.data.equals(data)) {
    				this.deleteFromHead();
    				return;
    			}
    			
    			//如果是删除最后一个节点
    			if (this.tail.data.equals(data)) {
    				this.deleteFromTail();
    				return;
    			}
    			
    			//删除中间节点
    			for (Node temp = this.head; temp.next != null; temp = temp.next) {
    				if (temp.data.equals(data)) {
    //					Node prev = temp.prev;
    //					Node next = temp.next;
    //					prev.next = next;
    //					next.prev = prev;
    					temp.prev.next = temp.next;
    					temp.next.prev = temp.prev;
    				}
    			}
    		}
    	}
    
    	public boolean isContains(Object data) {
    		if (!isEmpty()) {
    			Node temp = this.head;
    			for (; temp.next != null; temp = temp.next) {
    				if (temp.data.equals(data)) {
    					return true;
    				}
    			}
    		}
    		return false;
    	}
    
    	public boolean isEmpty() {
    		return this.head == null;
    	}
    
    	/**
    	 * 遍历链表的所有节点,并打印出节点数据信息
    	 */
    	public void printAll() {
    		Node temp = this.head;
    		for (; temp != null; temp = temp.next) {
    			System.out.println("node data is " + temp.data);
    		}
    	}
    	
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    
    		//实例化一个单向链表对象
    		DoubleLinkList dll = new DoubleLinkList();
    		
    		//向单向链表中添加节点
    		dll.addToHead("node1");
    		dll.addToTail("node2");
    		dll.addToTail("node3");
    		dll.addToTail("node4");
    		dll.addToTail("node5");
    		
    		//输出所有节点数据
    		dll.printAll();
    		
    		//删除第一个节点
    		dll.deleteFromHead();
    		
    		//删除最后一个节点
    		dll.deleteFromTail();
    		
    		//输出所有节点数据
    		dll.printAll();
    
    		//链表中是否包含指定的节点
    		boolean isExsist = dll.isContains("node11");
    		System.out.println(isExsist);
    		
    		//删除指定的节点
    		dll.deleteNode("node3");
    		dll.printAll();
    	}
    }
    

    3.总结

    双向链表弥补了单向链表的不足,可以双向获取相邻节点,比如删除最后一个节点时就不需要遍历整个链表,而可以直接操作最后一个节点。


  • 相关阅读:
    获取用户登录次数(cookie)
    漂亮的 Checkbox and Radio (jQuery)
    FancyUpload3.0
    UI upload 多文件上传
    js 匿名函数 闭包
    c# 图片插入Excel
    sql查询优化 索引优化
    GridViewAddUpdateDelete_Ajax with jquery.blockUI
    动态自动搜索 Dynamic search (js版)
    master.dbo.spt_values
  • 原文地址:https://www.cnblogs.com/yyuuaannllii/p/3775220.html
Copyright © 2020-2023  润新知