码迷,mamicode.com
首页 > 其他好文 > 详细

学习笔记之循环链表

时间:2015-11-08 15:04:36      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:

public class MyLinkedList {
    private class Node{  //定义节点  ,利用私有内部类的排他性
        Object data;  
        Node next;
        Node pre;
        public Node(){             
        }  
        
        public Node(Object data,Node next, Node pre){  
            this.data = data;   
            this.next = next;  
            this.pre = pre;
        }  
    }
    private Node head;//定义头节点
    private int size;//定义链表长度
    /**
     * 构造一个空列表
     * */
    public MyLinkedList() {
        head = new Node();//空头结点,来区分首部和尾部
        head.next = head.pre = head;
        //head.next = head;
        //size = 0;
    }
    /**
     * 构造一个包含指定 myList 中的元素的列表,这些元素按其 myList 的迭代器返回的顺序排列。
     * @param myList 要将其元素放入此列表的集合 
     * @exception 如果指定的集合为null,则抛出空指异常
     * */
    public MyLinkedList(MyLinkedList myList){
        this();//调用无参构造器
        /*
        if(myList == null){
            throw new NullPointerException();
        }*/
        addAll(this.size, myList);
    }
    /**
     * 在此列表中指定的位置插入指定的元素。移动当前在该位置处的元素(如果有),所有后续元素都向右移(在其索引中添加 1)。
     * @param index - 要在其中插入指定元素的索引
     * @param element - 要插入的元素
     * @exception 如果索引超出范围 (index < 0 || index > size()) - 抛出IndexOutOfBoundsException异常
     * */
    public void add(int index, Object data){
        cheakIndexException(index, 0);
        add(findIndexNode(index), data);
    }
    /**
     * 在链表中添加节点的方法
     * @param node 
     * @param data
     * @return true-添加成功,false-添加失败
     * */
    private void add(Node node, Object data) {  
        //新建一个节点,新节点的next指向node,新节点的last指向node的last  
        //完成指向过程node.pre←newNode→node  
        Node newNode = new Node(data, node, node.pre);  
        //维持双向链表的指向,将node的last节点的next指向新节点,完成指向过程node.pre→newNode  
        node.pre.next = newNode;  
        //node节点的前一个节点指向新节点,完成指向过程newNode←node  
        node.pre = newNode;  
        //上面两行代码不能颠倒,否则node的前一个节点会被覆盖成新节点,会丢失node原来的前一个节点的next指向  
        //上述代码完成了在node节点和node前一个节点之间加入一个新节点,并维护了双向关系  
        this.size++;  
        //return true;  
    }
    /**
     * 添加指定 myList 中的所有元素到此列表的结尾,顺序是指定 myList 的迭代器返回这些元素的顺序。如果指定的 myList 在操作过程中被修改,则此操作的行为是不确定的。(注意,如果指定 myList 就是此列表并且非空,则此操作的行为是不确定的。)
     *  @param myList-链表
     *  @return true-表示添加成功
     *  @param false-表示添加失败
     * */
    public boolean addAll(MyLinkedList myList){
        
        return addAll(this.size, myList);
    }
    /**
     * 在指定index位置添加myList里的所有元素 
     * @param index-添加集合的位置
     * @param myList-添加的集合
     * @exception IndexOutOfBoundsException - 如果索引超出范围 (index < 0 || index > size()) 
     * @exception NullPointerException - 如果指定的 myList为 null
     * @return true-插入成功
     * @return false-插入失败
     * */
    public boolean addAll(int index, MyLinkedList myList){
        cheakIndexException(index, 0);
        
        int oldSize = size;

        Node node = index == this.size ? this.head : findIndexNode(index);

        Node otherNode = myList.head.next;
        
        while(otherNode != myList.head){
            add(node, otherNode.data);
            
            otherNode = otherNode.next;
        }  
        //this.size += myList.size;  
        return oldSize != size; 
    }  
    /**
     * 把元素插在链表首部
     * @param - e 要插入的元素
     * */
    public void addFirst(Object e){
        add(this.head.next, e);
    }
    /**
     * 将指定元素添加到此列表的结尾。
     * @param - e 要插入的元素
     * */
    public void addLast(Object e){
        add(this.head, e);
    }
    /**
     * 从此列表中移除所有元素。
     * */
    public void clear(){  
        Node node = head.next;  
        //将每一个节点的双向指向都清空,这样每个节点都没有被引用,可以方便垃圾回收器回收内存  
        while(node != head){
            Node tmp = node.next;
            this.remove(node);
            node = tmp;
        }  
        //清空head的双向指向null  
        //this.head.next = this.head.pre = this.head;  
        //this.size = 0;  
    }  
    /**
     * 删除一个节点的方法
     * */
    private void remove(Node node){  
        //node的前一个节点next指向node的下一个节点  
        //node的下一个节点last指向node的前一个节点  
        //A→node←B改成A→←B  
        node.pre.next = node.next;  
        node.next.pre = node.pre;  
        //node的前后指向null  
        //A←node→B改成null←node→null  
        node.pre = node.next = null;  
        //Object data = node.data;  
        node.data = null;  
        size--;  
        //return data;  
    }  

    /**
     * 从此列表中移除首次出现的指定元素(如果存在)
     * @param e-要删除的data
     * @return true-删除成功
     * @return false-删除失败
     * */
    public boolean remove(Object e){
        Node node = head.next;
        while(node != head) {
            
            if(e==null ? node.data==null : e.equals(node.data)){
                remove(node);
                return true;
            }
            node = node.next;
        }
        return false;
    }
    /**
     * 移除此列表中指定位置处的元素。
     * @param index-下标
     * @return data-值
     * */
    public Object remove(int index){
        cheakIndexException(index, 1);
        Node node = findIndexNode(index);
        Object data = node.data;
        remove(node);
        return data;
    }
    /**
     * 删除链表的首部
     * @exception NoSuchElementException - 如果此列表为空
     * @return 返回被删除的元素
     * */
    public Object removeFirst(){
        cheakNoSuchException();
        Node node = this.head.next;
        Object data = node.data;
        remove(node);
        return data;
    }
    /**
     * 删除链表的尾部
     * @exception NoSuchElementException - 如果此列表为空
     * @return 返回被删除的元素
     * */
    public Object removeLast(){
        cheakNoSuchException();
        
        Node node = this.head.pre;
        Object data = node.data;
        remove(node);
        return data;
    }
    /**
     * 返回此列表中指定位置处的元素
     * @param index-要返回的元素的索引
     * @return 列表中指定位置的元素
     * */
    public Object get(int index){
        cheakIndexException(index, 1);
        return findIndexNode(index).data;
    }
    /**
     * 返回此列表中首位的元素
     * @return 列表中位于首位的元素
     * */
    public Object getFirst(){
        cheakNoSuchException();
        return head.next.data;
    }
    /**
     * 返回此列表中尾部的元素
     * @return 列表中位于尾部的元素
     * */
    public Object getLast(){
        cheakNoSuchException();
        return head.pre.data;
    }
    /**
     * 将此列表中指定位置的元素替换为指定的元素。
     * @param index - 要替换的元素的索引
     * @param element - 要在指定位置存储的元素
     * @return 以前在指定位置的元素
     * */
    public Object set(int index, Object element){
        cheakIndexException(index, 1);
        Node node = findIndexNode(index);
        Object temp = node.data;
        node.data = element;      
        return temp;
    }
    /**
     * 如果此列表包含指定元素,则返回 true。更确切地讲,当且仅当此列表包含至少一个满足 (o==null ? e==null : o.equals(e)) 的元素 e 时返回 true。 
     * @return  表示包含
     * @return  表示不包含
     * */
    public boolean contains(Object e) {
        
        return indexOf(e) != -1;
    }
    /**
     * 返回此列表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。更确切地讲,返回满足 (o==null ? get(i)==null : o.equals(get(i))) 的最低索引 i;如果没有此索引,则返回 -1。
     * @return -1 - 没有找到该元素
     * @return k - 元素的索引
     * */
    public int indexOf(Object e){
        int k = 0;
        Node node = head.next;
        while(node != head) {
            if(e==null ? node.data==null : e.equals(node.data)){
                return k;
            }
            k++;
        }
        return -1;
    }
    /**
     * 返回此列表中最后出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。更确切地讲,返回满足 (o==null ? get(i)==null : o.equals(get(i))) 的最高索引 i;如果没有此索引,则返回 -1。
     * @return -1 - 没有找到该元素
     * @return k - 元素的索引
     * */
    public int lastIndexOf(Object e){
        Node node = head.pre;
        int k = size - 1;
        while(node != head) {
            if(e==null ? node.data==null : e.equals(node.data)){
                return k;
            }
            k--;
        }
        return -1;
    }
    /**
     * 检查数组下标越界的方法
     * @param index-传入的下标
     * @exception IndexOutOfBoundsException - 如果索引超出范围 (index < 0 || index > size())
     * */
    private void cheakIndexException(int index, int s){
        if(index < 0 || index > this.size - s)  
        {  
            throw new IndexOutOfBoundsException();  
        }
    }
    /**
     * @exception NoSuchElementException - 如果此列表为空 
     * */
    private void cheakNoSuchException(){
        if(this.size == 0){
            throw new NoSuchElementException();
        }
    }
   /**
    * 迭代至index处的节点
    * @param index 传入下标
    * @return node 当按下标的找到的节点
    * */  
    private Node findIndexNode(int index){  
        cheakIndexException(index, 1); //判断index是否越界       
        Node node = this.head;  
        //判断index是否小于size的一半,如果小于就从header往后开始迭代,否则就从header往前开始迭代,提高效率  
        //例如有一个链表header→A→B→C→D→header  
        if(index <= (this.size/2)) {  
            //因为header是空的头节点,所以i要小于等于index  
            //例如index=1, 小于size的一半2  
            //i=0时,node=A  
            //i=1时,node=B,然后跳出循环  
            for(int i=0; i<=index; i++){  
                node = node.next;          
            }  
        }else{  
            //例如index=2,不小size的一半  
            //i=3, node等于header的前一个, node=D  
            //i=2, node=C,然后跳出循环  
            for(int i=this.size - 1; i>=index; i--){  
                node = node.pre;  
            }  
        }  
        return node;  
    }  
    /**
     * @return 此列表的元素数
     * */
    public int size(){
        return this.size;
    }
    /**
     * 判断该链表中是否包含了myList链表中的所有的元素
     * @param myList - 被判断的数组
     * @return true - 表示包含
     * @return false - 表示不包含
     * */
    public boolean containsAll(MyLinkedList myList){
        if(myList==null){  
            throw new NullPointerException(); 
        } 
        Node otherNode = myList.head.next;
        
        while(otherNode != myList.head) {
            if(!this.contains(otherNode.data)) {
                return false;
            }
        }
        
        return true;
    }
    /**
     * 判断是否为空链表
     * @return true - 表示为空
     * @return false - 表示不为空
     * */
    public boolean isEmpty(){
        return this.size == 0;
    }
    /**
     * 判断该链表中是否包含了myList链表中的所有的元素
     * @param myList - 被判断的数组
     * @return true - 表示删除完毕
     * */
    public boolean removeAll(MyLinkedList myList){
        
        Node node = head.next;
        int oldSize = size;
        while(node != head) {
            Node tmp = node.next;
              if(myList.indexOf(node.data) != -1) {
                  this.remove(node);
              }
              node = tmp;
              
        }
        
        return oldSize != size;
    }
    /**
     * 保留该链表中在与myList链表中相同的元素
     * @param myList - 被判断的数组
     * @return true - 表示保留完毕
     * */
    public boolean retainAll(MyLinkedList myList){
        Node node = head.next;
        int oldSize = size;
        while(node != head) {
            Node tmp = node.next;
              if(myList.indexOf(node.data) == -1) {
                  this.remove(node);
              }
              node = tmp;
              
        }
        return true;
    }
   
}

 

学习笔记之循环链表

标签:

原文地址:http://www.cnblogs.com/hnzyyTl/p/4947097.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!