• 单向链表学习笔记


    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 java.io.Serializable;
    
    /**
     * 单向链表
     * @author yuanli
     *
     */
    public class SingleLinkList {
    	
    	/**
    	 * 之所以定义为内部类,是因为用户并不关心链表节点的结构,而只关心链表存储的数据
    	 * @author yuanli
    	 *
    	 */
    	public class Node implements Serializable {
    
    		private static final long serialVersionUID = -1413226342863254391L;
    
    		public Object data;//数据域(用户关心的内容)
    		public Node next;//引用域(指向下一个节点)(用户不关心的内容)
    		
    		public Node(Object data) {
    			this(data,null);
    		}
    		
    		public Node(Object data, Node next) {
    			super();
    			this.data = data;
    			this.next = next;
    		}
    	}
    	
    	//表示链表的第一个节点
    	protected Node head;
    	
    	//表示链表的最后一个节点
    	protected Node tail;
    	
    	/**
    	 * 链表是否为空
    	 * @return
    	 */
    	public boolean isEmpty() {
    		return (head == null || tail == null);
    	}
    	
    	/**
    	 * 在链表的第一个节点前插入节点
    	 * @param data
    	 */
    	public void addToHead(Object data) {
    		this.head = new Node(data,this.head);
    		if (this.tail == null) this.tail = this.head;
    	}
    	
    	/**
    	 * 在链表的最后一个节点追加节点
    	 * @param data
    	 */
    	public void addToTail(Object data) {
    		if (!this.isEmpty()) {
    			this.tail.next = new Node(data);
    			this.tail = this.tail.next;
    		} else {
    			this.head = this.tail = new Node(data);
    		}
    	}
    	
    	/**
    	 * 删除链表中的第一个节点
    	 * @return
    	 */
    	public Object deleteFromHead() {
    		Node current_head_node = this.head;
    		if (this.head == this.tail) {
    			this.head = this.tail = null;
    		} else {
    			this.head = this.head.next;
    		}
    		return current_head_node.data;
    	}
    	
    	/**
    	 * 删除链表中的最后一个节点
    	 * @return
    	 */
    	public Object deleteFromTail() {
    		Node current_tail_node = this.tail;
    		if (this.tail == this.head) {
    			this.head = this.tail = null;
    		} else {
    			//若想删除最后一个节点,则必须先找到倒数第二个节点,并将其next设为null
    			//如何确定倒数第二个节点呢?如果那个节点的next指向的是tail,则说明是
    			Node temp = this.head;
    			for (; temp.next != this.tail; temp = temp.next);
    			this.tail = temp;
    			this.tail.next = null;
    		}
    		return current_tail_node.data;
    	}
    	
    	/**
    	 * 链表中是否存在指定的节点
    	 * @param data
    	 * @return
    	 */
    	public boolean isContains(Object data) {
    		Node temp = this.head;
    		for (; temp != null; temp = temp.next) {
    			if (temp.data.equals(data)) return true;
    		}
    		return false;
    	}
    	
    	/**
    	 * 删除指定的节点
    	 * @param data
    	 */
    	public void deleteNode(Object data) {
    		if (!isEmpty()) {
    			//如果只有一个节点
    			if (this.head == this.tail && this.head.data .equals(data)) {
    				this.head = this.tail = null;
    				return;
    			}
    			//如果删除的是第一个节点
    			if (this.head.data.equals(data)) {
    				this.deleteFromHead();
    				return;
    			}
    			//如果删除的是最后一个节点
    			if (this.tail.data.equals(data)) {
    				this.deleteFromTail();
    				return;
    			}
    
    			//否则
    			Node temp = this.head;
    			for (; temp != null; temp = temp.next) {
    				if (temp.next.data.equals(data)) {
    					temp.next = temp.next.next;
    					break;
    				}
    			}
    		}
    	}
    	
    	/**
    	 * 遍历链表的所有节点,并打印出节点数据信息
    	 */
    	public void printAll() {
    		Node temp = this.head;
    		for (; temp != null; temp = temp.next) {
    			System.out.println("node data is " + temp.data);
    		}
    	}
    	
    	public Node getHead() {
    		return head;
    	}
    
    	public void setHead(Node head) {
    		this.head = head;
    	}
    
    	public Node getTail() {
    		return tail;
    	}
    
    	public void setTail(Node tail) {
    		this.tail = tail;
    	}
    
    	
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    
    		//实例化一个单向链表对象
    		SingleLinkList sll = new SingleLinkList();
    		
    		//向单向链表中添加节点
    		sll.addToHead("node1");
    		sll.addToTail("node2");
    		sll.addToTail("node3");
    		sll.addToTail("node4");
    		//输出所有节点数据
    		sll.printAll();
    		
    		//删除第一个节点
    		sll.deleteFromHead();
    		
    		//删除最后一个节点
    		sll.deleteFromTail();
    		
    		//输出所有节点数据
    		sll.printAll();
    
    		//链表中是否包含指定的节点
    		boolean isExsist = sll.isContains("node11");
    		System.out.println(isExsist);
    		
    		//删除指定的节点
    		sll.deleteNode("node3");
    		sll.printAll();
    		
    	}
    
    }


    总结:

    1.单向链表的优点:插入节点效率高

    2.单向链表的缺点:查询、删除节点效率低



  • 相关阅读:
    python 抽象
    hive处理日志,自定义inputformat
    random os sys 序列化模块
    collections time模块
    面试题
    正则表达式 和 re模块
    模块的导入 异常处理和软件开发目录规范
    函数的迭代 函数生成器 常用的内置方法
    函数递归 三元表达式 匿名函数 函数内置方法
    闭包函数 装饰器
  • 原文地址:https://www.cnblogs.com/yyuuaannllii/p/3775221.html
Copyright © 2020-2023  润新知