zoukankan      html  css  js  c++  java
  • 学习笔记之循环链表

    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;
        }
       
    }
  • 相关阅读:
    go正则解析log文件
    go的堆排序
    golang实现websocket
    golang接口
    erlang时间操作
    golang函数
    golang for循环
    golang 条件语句if,switch
    golang内建变量类型
    区间存在幂个数
  • 原文地址:https://www.cnblogs.com/hnzyyTl/p/4947097.html
Copyright © 2011-2022 走看看