zoukankan      html  css  js  c++  java
  • 单向链表

    动态数组在使用过程中需要一次性申请一段连续的内存地址,可能会造成内存空间的浪费。

    而链表是一种链式存储的线性表,所有元素的内存地址不需要是连续的。

    链表的结点中包含两部分,一个是元素的数据信息,另一个是下一个结点元素的地址。

    定义接口:

    public interface List<E> {
    	static final int ELEMENT_NOT_FOUND = -1;
    	/**
    	 * 清除所有元素
    	 */
    	void clear();
    
    	/**
    	 * 元素的数量
    	 * @return
    	 */
    	int size();
    
    	/**
    	 * 是否为空
    	 * @return
    	 */
    	boolean isEmpty();
    
    	/**
    	 * 是否包含某个元素
    	 * @param element
    	 * @return
    	 */
    	boolean contains(E element);
    
    	/**
    	 * 添加元素到尾部
    	 * @param element
    	 */
    	void add(E element);
    
    	/**
    	 * 获取index位置的元素
    	 * @param index
    	 * @return
    	 */
    	E get(int index);
    
    	/**
    	 * 设置index位置的元素
    	 * @param index
    	 * @param element
    	 * @return 原来的元素ֵ
    	 */
    	E set(int index, E element);
    
    	/**
    	 * 在index位置插入一个元素
    	 * @param index
    	 * @param element
    	 */
    	void add(int index, E element);
    
    	/**
    	 * 删除index位置的元素
    	 * @param index
    	 * @return
    	 */
    	E remove(int index);
    
    	/**
    	 * 查看元素的索引
    	 * @param element
    	 * @return
    	 */
    	int indexOf(E element);
    }
    
    
    public abstract class AbstractList<E> implements List<E>  {
    	/**
    	 * 元素的数量
    	 */
    	protected int size;
    	/**
    	 * 元素的数量
    	 * @return
    	 */
    	public int size() {
    		return size;
    	}
    
    	/**
    	 * 是否为空
    	 * @return
    	 */
    	public boolean isEmpty() {
    		 return size == 0;
    	}
    
    	/**
    	 * 是否包含某个元素
    	 * @param element
    	 * @return
    	 */
    	public boolean contains(E element) {
    		return indexOf(element) != ELEMENT_NOT_FOUND;
    	}
    
    	/**
    	 * 添加元素到尾部
    	 * @param element
    	 */
    	public void add(E element) {
    		add(size, element);
    	}
    	
    	protected void outOfBounds(int index) {
    		throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
    	}
    	
    	protected void rangeCheck(int index) {
    		if (index < 0 || index >= size) {
    			outOfBounds(index);
    		}
    	}
    	
    	protected void rangeCheckForAdd(int index) {
    		if (index < 0 || index > size) {
    			outOfBounds(index);
    		}
    	}
    }
    

    单向链表:

    public class SingleLinkedList<E> extends AbstractList<E> {
    	private Node<E> first;
    	
    	private static class Node<E> {
    		E element;
    		Node<E> next;
    		public Node(E element, Node<E> next) {
    			this.element = element;
    			this.next = next;
    		}
    	}
    
    	@Override
    	public void clear() {
    		size = 0;
    		first = null;
    	}
    
    	@Override
    	public E get(int index) {
    		/*
    		 * 最好:O(1)
    		 * 最坏:O(n)
    		 * 平均:O(n)
    		 */
    		return node(index).element;
    	}
    
    	@Override
    	public E set(int index, E element) {
    		/*
    		 * 最好:O(1)
    		 * 最坏:O(n)
    		 * 平均:O(n)
    		 */
    		Node<E> node = node(index);
    		E old = node.element;
    		node.element = element;
    		return old;
    	}
    
    	@Override
    	public void add(int index, E element) {
    		/*
    		 * 最好:O(1)
    		 * 最坏:O(n)
    		 * 平均:O(n)
    		 */
    		rangeCheckForAdd(index);
    		
    		if (index == 0) {
    			first = new Node<>(element, first);
    		} else {
    			Node<E> prev = node(index - 1);
    			prev.next = new Node<>(element, prev.next);
    		}
    		size++;
    	}
    
    	@Override
    	public E remove(int index) {
    		/*
    		 * 最好:O(1)
    		 * 最坏:O(n)
    		 * 平均:O(n)
    		 */
    		rangeCheck(index);
    		
    		Node<E> node = first;
    		if (index == 0) {
    			first = first.next;
    		} else {
    			Node<E> prev = node(index - 1);
    			node = prev.next;
    			prev.next = node.next;
    		}
    		size--;
    		return node.element;
    	}
    
    	@Override
    	public int indexOf(E element) {
    		if (element == null) {
    			Node<E> node = first;
    			for (int i = 0; i < size; i++) {
    				if (node.element == null) return i;
    				
    				node = node.next;
    			}
    		} else {
    			Node<E> node = first;
    			for (int i = 0; i < size; i++) {
    				if (element.equals(node.element)) return i;
    				
    				node = node.next;
    			}
    		}
    		return ELEMENT_NOT_FOUND;
    	}
    	
    	/**
    	 * 获取index位置对应的节点对象
    	 * @param index
    	 * @return
    	 */
    	private Node<E> node(int index) {
    		rangeCheck(index);
    		
    		Node<E> node = first;
    		for (int i = 0; i < index; i++) {
    			node = node.next;
    		}
    		return node;
    	}
    	
    	@Override
    	public String toString() {
    		StringBuilder string = new StringBuilder();
    		string.append("size=").append(size).append(", [");
    		Node<E> node = first;
    		for (int i = 0; i < size; i++) {
    			if (i != 0) {
    				string.append(", ");
    			}
    			
    			string.append(node.element);
    			
    			node = node.next;
    		}
    		string.append("]");
    		
    //		Node<E> node1 = first;
    //		while (node1 != null) {
    //			
    //			
    //			node1 = node1.next;
    //		}
    		return string.toString();
    	}
    }
    
  • 相关阅读:
    MIT自然语言处理第三讲:概率语言模型(第四部分)
    MIT自然语言处理第二讲:单词计数(第三部分)
    MIT自然语言处理第五讲:最大熵和对数线性模型(第二部分)
    MIT自然语言处理第二讲:单词计数(第四部分)
    MIT自然语言处理第三讲:概率语言模型(第一部分)
    MIT自然语言处理第二讲:单词计数(第二部分)
    MIT自然语言处理第五讲:最大熵和对数线性模型(第一部分)
    MIT自然语言处理第四讲:标注(第二部分)
    MIT自然语言处理第二讲:单词计数(第一部分)
    MIT自然语言处理第一讲:简介和概述(第二部分)
  • 原文地址:https://www.cnblogs.com/xiuzhublog/p/12608560.html
Copyright © 2011-2022 走看看