欢迎光临散文网 会员登陆 & 注册

java模拟单向链表

2022-08-05 14:20 作者:虚云幻仙  | 我要投稿

/**
* 自定义链表
*/

public interface CustomizeList<E> extends Collection<E> {
   //先自定义List接口,增加使用索引的方法
   E remove(int index);
   E set(int index,E e);
   E get(int index);
}

class CustomizeOneWayLinkedList<E> implements CustomizeList<E>{
   //自定义单向链表

   private static final class Node<E> {
       //结点 内部类
       E item;
       Node<E> next;
       //单向链表只有直接后继结点一个指针
       public Node(E item, Node<E> next) {
           this.item = item;
           this.next = next;
       }
   }

   private Node<E> first;
   private int size;

   private void indexCheck(int index){
       //执行需要索引的方法时都先进行索引检查
       if (index<0||index>=size) throw new IndexOutOfBoundsException("index:"+index+" size:"+size);
       //对现有结点进行操作时范围为[0,size),执行插入操作时范围为[0,size]
   }

   private Node<E> getNode(int index){
       Node<E> n = first;
       for (int i = 0;i<index;i++){
           n = n.next;
       }
       return n;
   }

   @Override
   public E remove(int index) {
       indexCheck(index);
       //先进行索引检查,包括空容器index=0时也会报索引越界,所以能通过检查说明容器内有元素
       Node<E> temp;
       if (index==0){
           //单向链表的删除结点是将前驱结点跳过当前结点链到后继结点上,所以先要判断是否存在前驱结点,单向链表没有prev属性,只能用index-1来调用,当index=0时-1会报错,所以要单独判断
           temp = first;
           first = first.next;
       }else {
           Node<E> prev = getNode(index-1);
           temp = prev.next;
           prev.next = temp.next;
       }
       //用temp缓存要删除的结点
       E e = temp.item;
       temp.item = null;
       temp.next = null;
       size--;
       return e;
   }

   @Override
   public E set(int index, E e) {
       indexCheck(index);
       Node<E> n = getNode(index);
       E oldE = n.item;
       n.item = e;
       return oldE;
   }

   @Override
   public E get(int index) {
       indexCheck(index);
       return getNode(index).item;
   }

   @Override
   public int size() {
       return size;
   }

   @Override
   public boolean isEmpty() {
       return size==0;
   }

   public int indexOf(Object o){
       if (o==null)return -1;
       Node<E> n = first;
       for (int i = 0 ;i<size;i++,n = n.next){
           //size=0时不执行循环
           if (o.equals(n.item))return i;
       }
       return  -1;
   }

   @Override
   public boolean contains(Object o) {
       return indexOf(o)!=-1;
   }

   @Override
   public Iterator<E> iterator() {
       return new Iterator<E>() {
           //匿名内部类
           int next = -1;
           int cursor = 0;
           @Override
           public boolean hasNext() {
               return cursor!=size;
           }

           @Override
           public E next() {
               next = cursor++;
               return CustomizeOneWayLinkedList.this.get(next);
           }

           @Override
           public void remove() {
               CustomizeOneWayLinkedList.this.remove(next);
               //外部类的remove方法中已经size--了
               next = -1;
               //将next变为-1,禁止连续删除
               cursor--;
           }
       };
   }

   @Override
   public Object[] toArray() {
       Object[] o = new Object[size];
       Node<E> n = first;
       for (int i = 0;i<size;i++,n = n.next){
           o[i] = n.item;
       }
       return o;
   }

   @Override
   public <T> T[] toArray(T[] a) {
       if (a.length<size) {
           a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
           //Array类的方法.newInstance(Class<T>,int)生成一个新的数组,数组类型为T[],将新数组作为Object对象返回,所以需要对返回值强转回T[]
           //.getClass()返回对象的类的类对象Class<T[]>   .getComponentType()返回数组类对象的组成成分/元素的类对象Class<T>

       }
       Node<E> n = first;
       for (int i = 0; i < size; i++, n = n.next) {
           a[i] = (T) n.item;
       }
       if (a.length>size){
           a[size] = null;
       }
       return a;
   }

   @Override
   public boolean add(E e) {
       if (isEmpty()) {
           first = new Node<>(e, null);
       }else {
           getNode(size-1).next = new Node<>(e,null);
           //将结点链至表尾
       }
       size++;
       return true;
   }


   @Override
   public boolean remove(Object o) {
       if (o==null)return false;
       Node<E> p = null;
       for (Node<E> m = first;m!=null;p=m,m=m.next){
           //first==null时不执行循环
           if (o.equals(m.item)){
               if (p==null){
                   //当m为first时p还没有赋值,判断p==null即判断m==first
                   first=first.next;
               }else {
                   p.next = m.next;
               }
               m.item=null;
               m.next=null;
               size--;
               return true;
           }
       }
       return false;
   }

   @Override
   public boolean containsAll(Collection<?> c) {
       if (c==null||c.isEmpty()||isEmpty())return false;
       for (Object o :
               c) {
           if (!contains(o)) return false;
       }
       return true;
   }

   @Override
   public boolean addAll(Collection<? extends E> c) {
       //形参类型为Collection接口,只要元素同类或子类就可以使不同类型的容器取并集
       if (c==null||c.isEmpty())return false;
       Node<E> n;
       Iterator<? extends E> itr = c.iterator();
       //使用迭代器来添加
       if (isEmpty()){
           first = new Node<>(itr.next(),null);
           n = first;
       }else {
           n = getNode(size-1);
           //要调用size-1所以需要单独处理size=0的情况
       }
       while (itr.hasNext()){
           n.next = new Node<>(itr.next(),null);
           //将元素从原容器中取出封入新的结点中添加至表尾
           n = n.next;
       }
       size += c.size();
       return true;
   }

   @Override
   public boolean removeAll(Collection<?> c) {
       if (c == null||c.isEmpty()||isEmpty())return false;
       boolean modified = false;
       for (Object o :
               c) {
           while (remove(o)) {
               //remove()方法中已经将size--了,这里不需要再次修改size
               modified = true;
           }
       }
       return modified;
   }

   @Override
   public boolean retainAll(Collection<?> c) {
       if (c==null||c.isEmpty()||isEmpty())return false;
       boolean modified = false;
       for (Iterator<E> it = iterator();it.hasNext();){
           if (!c.contains(it.next())) {
               it.remove();
               modified = true;
           }
       }
       return modified;
   }

   @Override
   public void clear() {
       for (Node<E> n = first;first!=null;n =first){
           first = first.next;
           n.item = null;
           n.next = null;
       }
       size =0;
   }

   @Override
   public String toString() {
       if (isEmpty())return "[]";
       StringBuilder str = new StringBuilder("[");
       for (Node<E> n = first;;){
           //循环条件空着为死循环,迭代因子放在语句内
           str.append(n.item);
           n=n.next;
           if (n==null){
               return str.append("]").toString();
           }
           str.append(", ");
       }
   }

   //单向链表实现栈容器方法
   public boolean empty(){
       return first==null;
   }
   public E pop(){
       if (empty()){
           return null;
       }
       Node<E> n = first;
       first = first.next;
       E e = n.item;
       n.item = null;
       n.next = null;
       size--;
       return e;
   }
   public E peek(){
       return empty()?null:first.item;
   }
   public void push(E e){
       first = new Node<>(e,first);
       size++;
   }
   public int search(E e){
       if (empty()||e==null)return -1;
       int i = 1;
       for (Node<E> n = first;n!=null;n = n.next){
           if (e.equals(n.item))return i;
           i++;
       }
       return -1;
   }


   public static void main(String[] args) {
       CustomizeOneWayLinkedList<String> ll1 = new CustomizeOneWayLinkedList<>();
       CustomizeOneWayLinkedList<String> ll2 = new CustomizeOneWayLinkedList<>();
       //测试略
   }
}

java模拟单向链表的评论 (共 条)

分享到微博请遵守国家法律