• 自定义(单链表)集合类


    类的结构

    接口:MyList

     1 package day2_19.inter;
     2 
     3 /**
     4  * 将arryList 和 linkedList 共性的方法进行抽取 --->保证体系的完整性
     5  *
     6  * @Author Tianhao
     7  * @create 2021-02-19-17:26
     8  */
     9 
    10 public interface MyList<E>{
    11 
    12 
    13     public int size();
    14 
    15 
    16     public boolean isEmpty();
    17 
    18 
    19     public boolean contains(Object o);
    20 
    21 
    22     public boolean add(E e);
    23 
    24     public void add(int index, E element);
    25 
    26     public E remove(int index);
    27 
    28     public E get(int index);
    29 
    30 
    31     public E set(int index, E element);
    32 
    33 
    34     public int indexOf(Object o);
    35 
    36     public void clear();
    37 
    38     String toString();
    39 
    40 
    41 //    public boolean remove(Object o);
    42 
    43 
    44 //    public Iterator<E> iterator();
    45 
    46 
    47 //    public Object[] toArray();
    48 
    49 
    50 //    public <T> T[] toArray(T[] a);
    51 
    52 
    53 //    public boolean containsAll(Collection<?> c);
    54 //
    55 //
    56 //    public boolean addAll(Collection<? extends E> c);
    57 //
    58 //
    59 //    public boolean addAll(int index, Collection<? extends E> c) ;
    60 //
    61 //
    62 //    public boolean removeAll(Collection<?> c);
    63 //
    64 //
    65 //    public boolean retainAll(Collection<?> c);
    66 
    67 
    68 //    public int lastIndexOf(Object o);
    69 //
    70 //
    71 //    public ListIterator<E> listIterator();
    72 //
    73 //
    74 //    public ListIterator<E> listIterator(int index);
    75 //
    76 //
    77 //    public List<E> subList(int fromIndex, int toIndex);
    78 
    79 }

    抽象类:MyAbstractList

     1 package day2_19.abstractClass;
     2 
     3 import day2_19.inter.MyList;
     4 
     5 /**
     6  *
     7  * 用于实现arryList 和 linkedList中那些相同的方法
     8  *
     9  * @Author Tianhao
    10  * @create 2021-02-19-17:46
    11  */
    12 
    13 public abstract class MyAbstractList<E> implements MyList<E> {
    14     protected int size;
    15 
    16     /**
    17      * 获取元素个数
    18      * @return 元素个数
    19      */
    20     @Override
    21     public int size() {
    22         return size;
    23     }
    24 
    25     /**
    26      * 判断集合是否为空
    27      * @return
    28      */
    29     @Override
    30     public boolean isEmpty() {
    31         return size == 0;
    32     }
    33 
    34     /**
    35      * 判断集合是否包含指定元素
    36      * indexOf(Object o):寻找对应的元素,如果找到了返回元素的索引,如果没有找到返回 -1
    37      * @param o
    38      * @return
    39      */
    40     @Override
    41     public boolean contains(Object o) {
    42         return indexOf(o) != -1;
    43     }
    44 
    45 
    46     /**
    47      * 在集合的最后添加一个元素,也就是在索引为size处添加一个元素
    48      * @param e
    49      * @return
    50      */
    51     @Override
    52     public boolean add(E e) {
    53         add(size,e);
    54         return true;
    55     }
    56 }

    自定义(单链表)集合类:

      1 package day2_19.linked;
      2 
      3 import day2_19.abstractClass.MyAbstractList;
      4 
      5 /**
      6  * 
      7  * 自定义(单链表)集合类
      8  *
      9  * @Author Tianhao
     10  * @create 2021-02-19-18:01
     11  */
     12 public class MyLinkedList<E> extends MyAbstractList<E> {
     13 
     14     private Node<E> first;
     15 
     16     private static class Node<E>{
     17         E element;
     18         Node<E> next;
     19         Node(E element,Node<E> next){
     20             this.element = element;
     21             this.next = next;
     22         }
     23     }
     24 
     25 
     26 
     27     /**
     28      * 在指定索引index处插入指定元素
     29      * @param index 注意:index >= 0 && index <= size (是可以插入到最后一个元素的下一个位置的)
     30      * @param element
     31      */
     32     @Override
     33     public void add(int index, E element) {
     34         checkPositionIndex(index);//判断index >=0 && index <= size
     35         if (index == 0) {//这里不管first是否为null,都是没有问题的
     36             //如果最开始的first为null,则插入的节点为node(element,null),被first指向
     37             //如果最开始的first不为null,则插入的节点为node(element,first),除了被first指向,它还指向最开始的那个first
     38             first = new Node(element, first);
     39         } else {//插入位置索引不是0
     40             Node<E> pre = node(index - 1);//前一个节点
     41             Node<E> next = pre.next;//后一个节点
     42             pre.next = new Node(element,next);//前一个节点指向插入的节点,这个插入的节点指向后一个节点
     43         }
     44         size++;
     45     }
     46 
     47 
     48     private void checkPositionIndex(int index) {
     49         if (!isPositionIndex(index)) {
     50             throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
     51         }
     52     }
     53 
     54     private boolean isPositionIndex(int index) {
     55         return index >= 0 && index <= size;
     56     }
     57 
     58     /**
     59      * 移除集合中指定索引的元素,并返回这个元素
     60      * @param index
     61      * @return
     62      */
     63     @Override
     64     public E remove(int index) {
     65         checkElementIndex(index);
     66         Node<E> oldNode;
     67         if (index==0) {
     68             oldNode = first;
     69             first = first.next;
     70             size--;
     71             return oldNode.element;
     72         }
     73         //先从一般的规律入手,写下来,再看特殊情况,
     74         //如果index=0,那么index-1就为负数,肯定是不行的,所以才有上面if (index==0) 的情况
     75         Node<E> pre = node(index - 1);
     76         oldNode = pre.next;
     77         pre.next = oldNode.next;
     78         size--;
     79         return oldNode.element;
     80     }
     81 
     82     /**
     83      * 获取指定索引(节点)处的元素
     84      * 因为增删改都是基于先找到元素,所以这个方法最先实现比较好
     85      * @param index
     86      * @return
     87      */
     88     @Override
     89     public E get(int index) {
     90         checkElementIndex(index);
     91         return node(index).element;
     92 
     93     }
     94 
     95     /**
     96      * 检查指定索引,如果集合中不存在这个指定索引,则抛出异常
     97      * @param index
     98      */
     99     private void checkElementIndex(int index) {
    100         if (!isElementIndex(index)) {
    101             throw new IndexOutOfBoundsException("Index: " + index + ",Size: " + size);
    102         }
    103     }
    104 
    105     /**
    106      * 找到指定索引index对应的Node节点
    107      * @param index
    108      * @return
    109      */
    110     private Node<E> node(int index) {
    111         //获取集合第一个元素first
    112         Node<E> x = first;
    113         //通过x.next,循环遍历找到指定索引index对应的Node节点
    114         for (int i = 0; i < index; i++) {
    115             x = x.next;
    116         }
    117         return x;
    118     }
    119 
    120     /**
    121      * 判断集合中是否存在指定索引
    122      * @param index
    123      * @return
    124      */
    125     private boolean isElementIndex(int index) {
    126         return index >= 0 && index < size;
    127     }
    128 
    129 
    130     /**
    131      * 将指定索引处的元素替换为指定的元素
    132      * @param index 指定的索引
    133      * @param element 将要替换到指定索引处的元素
    134      * @return 返回指定索引处被替换的元素
    135      */
    136     @Override
    137     public E set(int index, E element) {
    138         checkElementIndex(index);
    139         Node<E> node = node(index);
    140         E oldEle = node.element;
    141         node.element = element;
    142         return oldEle;
    143     }
    144 
    145     /**
    146      * 查找第一次出现指定元素o的索引位置
    147      * @param o
    148      * @return 如果有,返回o在集合中的索引;如果没有,返回-1
    149      */
    150     @Override
    151     public int indexOf(Object o) {
    152         int index = 0;
    153         if (o == null) {
    154             //多去理解这种遍历思维
    155             for (Node<E> x = first; x != null; x = x.next) {
    156                 if (x.element == o) {
    157                     return index;
    158                 }
    159                 //还有这种返回索引的思维也要多学习
    160                 index++;
    161             }
    162         } else {
    163             for (Node<E> x = first; x != null; x = x.next) {
    164                 if (o.equals(x.element)) {
    165                     return index;
    166                 }
    167                 index++;
    168             }
    169         }
    170         return -1;
    171     }
    172 
    173     /**
    174      * 清空集合的所有元素
    175      *
    176      * 可达性算法:判断对象是否是一个垃圾的标准
    177      *  选取一个节点,作为GC ROOTS顶点,其他对象或者引用去指向这个GC ROOTS顶点,如果这些对象
    178      *  能够到达这个GC ROOTS顶点,那么这些对象不是垃圾,反之就是。
    179      *
    180      */
    181     @Override
    182     public void clear() {
    183         size = 0;
    184         first = null;
    185     }
    186 
    187     @Override
    188     public String toString() {
    189         if (size == 0) {
    190             return "[]";
    191         }
    192         StringBuilder sb= new StringBuilder();
    193         sb.append('[');
    194         for( Node<E> x = first;x!=null;x=x.next){
    195             sb.append(x.element);
    196             if (x.next == null) {
    197                 return sb.append(']').toString();
    198             }
    199             sb.append(',').append(' ');
    200         }
    201         return sb.toString();
    202     }
    203 }
  • 相关阅读:
    数据库无限分级(分类表)
    从SQLserver中导出表数据到Access
    C# 对JS解析AJX请求JSON并绑定到html页面的一些心得
    高效的SQLSERVER分页查询(转载)
    Entity Framework自用的DataBase基类
    简单SVN使用方法
    CMD终端关于pip报错,scrapy报错的一种处理方法
    [原创]使用python对视频/音频文件进行详细信息采集,并进行去重操作
    Primer C++第五版 读书笔记(一)
    分享一个编程学习网站:https://github.com/justjavac/free-programming-books-zh_CN
  • 原文地址:https://www.cnblogs.com/zui-ai-java/p/14422828.html
Copyright © 2020-2023  润新知