单链表数据结构 - Java简单实现

链表中最简单的一种是单向链表,每个元素包含两个域,值域和指针域,我们把这样的元素称之为节点。每个节点的指针域内有一个指针,指向下一个节点,而最后一个节点则指向一个空值。如图就是一个单向链表

一个单向链表的节点被分成两个部分。第一个部分保存或者显示关于节点的信息,第二个部分存储下一个节点的地址。单向链表只可向一个方向遍历。

使用java实现一个简单的单链表,需要定义一个节点类、对节点的操作方法(add 、get、remove...)

**
 * 单链表数据结构简单实现
 * 
 * @author jade
 *
 */
public class SingleLinkedList<E> {

    private Node<E> head = null; // 每个链表都存有一个空值的头结点。
    private Node<E> tail = null; // 链表的最后一个结点,尾结点。
    private int size = 0; // 当前链表中的节点数目。

    /** 
     * 建立一个空链表(建立其头结点)。 
     */  
    public SingleLinkedList() {  
        head = new Node<E>();  
        tail = head;  
    }

    /**
     * 在链表的尾部插入数据
     * @param e 待插入的数据
     *            
     * @return
     */
    public boolean add(E e) {
        Node<E> node = new Node<E>(e); // 将要插入的值封装成一个节点。
        tail.setNext(node); // 将待插入结点放到尾结点的下一个结点。
        tail = tail.getNext(); // 将新增加的结点设为尾节点。
        ++size; // 链表大小增1。
        return true;
    }

    /**
     * 
     * @param index 待插入的位置
     * @param e  待插入的元素
     *            
     * @return
     */
    public boolean add(int index, E e) {
        checkValidateIndex(index);
        Node<E> newNode = new Node<E>(e); 
        Node preNode = null;
        if (index > 0) {
            preNode = getNode(index - 1);
        }else{
            preNode = head;
        }
        newNode.setNext(preNode.getNext());
        preNode.setNext(newNode);
        return true;
    }

    

    /**
     * 获取指定位置的结点的值
     * @param index  欲获取值的结点的下标
     *            
     * @return
     */
    public E get(int index) {
        checkValidateIndex(index);
        Node<E> node = getNode(index);
        return node.getValue();
    }


    /**
     * 删除指定位置的结点
     * @param index   待删除结点的下标
     * @return
     */
    public boolean remove(int index) {
        Node<E> curNode = null;
        if (0 == index) {
            curNode = head.getNext();
            Node<E> nextNode = curNode.getNext();
            head.setNext(nextNode);
        } else {
            checkValidateIndex(index);
            curNode = getNode(index); // 获取待删除节点。
            Node<E> preNode = getNode(index - 1); // 获取待删除节点的前一个结点。
            preNode.setNext(curNode.getNext());
        }
        curNode.setNext(null); // 将待删除节点的下一结点置空。
        return true;
    }

    /**
     * 设置指定位置结点的值。
     * @param index 待设置值的结点的下标
     * @param e
     */
    public void set(int index, E e) {
        checkValidateIndex(index);
        Node<E> node = getNode(index);
        node.setValue(e);
    }
    
    /**
     * 获取指定位置的结点
     * @param index 获取结点的下标
     *            
     */
    private Node<E> getNode(int index) {
        checkValidateIndex(index);
        Node<E> node = head;
        for (int p = 0; p <= index; ++p) {
            node = node.getNext();
        }
        return node;
    }

    /**
     * 验证下标值是否合法,非法时抛出异常。
     * @param index 待验证的下标值
     * @throws Exception 
     *            
     */
    private void checkValidateIndex(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("无效的下标:" + index);
        }
    }

    /**
     * 获取链表的大小。
     * @return
     */
    public int size() {
        return size;
    }
    
    /**
     * 链表中的节点,e代表节点的值,next是指向下一个节点的引用
     * 
     * @author jade
     *
     */
    static class Node<E> {
        private E e;
        private Node<E> next = null;

        Node() {
        }

        Node(E e) {
            this.e = e;
        }

        public void setNext(Node<E> next) {
            this.next = next;
        }

        public Node<E> getNext() {
            return next;
        }

        public E getValue() {
            return e;
        }

        public void setValue(E e) {
            this.e = e;
        }

    }

猜你喜欢

转载自www.linuxidc.com/Linux/2017-03/141977.htm
今日推荐