使用单向链表实现LinkedList

来源:互联网 发布:mysql数据库ip怎么查询 编辑:程序博客网 时间:2024/06/01 21:58

单向链表是指节点中的指针域只有一个,指针域只能沿着同一个方向移动的链表。Java.util包中提供了LinkedList,此LinkedList是基于双向链表实现的。本文基于单向链表实现LinkedList中的某些方法,主要是学习使用下单向链表这种数据结构。
首先给出节点类,节点类中包含数据域value,和指针域next,以及三个构造函数。

class Entry {          E value;//数据域          Entry next;//指针域          Entry() {}          Entry (E value){              this.value = value;          }          Entry (E value, Entry next){              this.value = value;              this.next = next;          }

}

为了方便处理链表中的插入,删除和查找操作,在链表的开始结点之前,增加一个head节点,此head节点指向开始结点。这样好处为:

  1. 开始结点的地址存放在了head节点中,这样开始结点的操作和其他节点的操作一样,无需特殊处理。
  2. 不论链表是否为空,其头结点的指针是指向开始节点的非空节点(只不过空链表时,头结点的指针域next为null)。空链表的处理和非空链表一样了。
我们将LinkedList类实现java.util.List<E>接口,尽可能的实现java.util.List<E>中的方法。实现的java.util.List<E>接口方法如下

返回值方法说明booleanadd(E e)将特定元素e添加到List中void  add(int index, E element)在索引index处添加给定的元素booleanaddAll(Colleaction<? extends E> c)将集合c中的元素全部加入List中booleanaddAll(intindex, Collection<?extendsE> c)在给定位置,添加集合c中的元素intsize()返回链表中的元素个数Eget(int index)获取下标为index的元素booleanisEmpty()List为空时,返回truebooleanremove(Object o)移除链表中第一个元素值为o的元素。booleanremoveAll(Collection<?> c)从链表中移除c中所有的元素。Eremove(int index)删除index处的元素Eset(int index, E element)将index处的值设置为元素element。int

indexOf(Object o)

返回元素o在链表中第一次出现的索引位置,未出现返回-1booleancontains(Object o)如果List中包含元素o则,返回true;否则falsebooleancontainsAll(Collection<?> c)List中是否包含集合c中的全部元素,是返回true,否则falsevoidclear()清空List中的值Object[]toArray()将链表转换为数组,返回Object[]T[]toArray(T[] a)将链表转换为类型为T的数组intlastIndexOf(Object o) 返回链表中value等于o的倒数第一个索引值。booleanretainAll(Collection<?> c)从链表中移除所有不在集合c中的元素。Iterator<E>iterator()返回链表的迭代子


下面看下LinkedList类的具体实现。

LinkedList类成员域

     LinkedList中除了有包含开始节点的head节点之外,还需要一个整型域count,此属性记录了链表中的节点个数。LinkedList类的成员域如下
//头指针。private Entry head = new Entry();//节点个数private int count = 0;

add(E e)

     向链表中插入节点时,是从开始节点插入:将新增节点指向开始节点,head指向新增节点
public boolean add(E e) {          //新增节点          Entry addE = new Entry(e);                  addE.next = head.next;          head.next = addE;          count++;          return true;     }

add(int index, E element)

     在特定位置,加入某个元素。
     使用变量tmp表示当前处理的节点,变量pre表示当前节点的前趋,用i记录移动的元素个数。当i=index时,将前趋节点指针域指向新节点,新节点的指针域指向当前节点。
/*      * 特定位置加入某个元素      */     @Override     public void add(int index, E element) {          if(index < 0 || index >= count) {              throw new RuntimeException("index越界");          }          int i = 0;          Entry tmp = head.next;          Entry pre = head;          while(i != index) {              tmp = tmp.next;              pre = pre.next;              i++;          }          Entry add = new Entry(element);          pre.next = add;          add.next = tmp;          count++;     }

addAll(Collection<?extendsE> c)

    将集合c中的所有元素添加到链表中。利用集合c的迭代子循环增加元素
public boolean addAll(Collection<? extends E> c) {          Iterator<? extends E> it = c.iterator();          while(it.hasNext()) {              add(it.next());          }          return true;

addAll(intindex, Collection<?extendsE> c)

 在特定位置,向链表中添加集合c中的元素.
   分两种情况:1、index<count,记录下前趋节点,将c中的元素追加到前趋节点的末尾,将追加的最后一个元素的指针域指向原index处的节点
    2、index=count,即在末尾节点添加集合c中的元素。循环将c中的元素追加到末尾节点
public boolean addAll(int index, Collection<? extends E> c) {          if(index < 0 || index > count) {              throw new RuntimeException("index越界");          }          /*           * 如果index等于count大小,需要单独处理           */          if(index == count) {              Entry tmp = head;              while(null != tmp.next) {                   tmp = tmp.next;              }              //循环将c中的元素追加到末尾              Iterator<? extends E> it = c.iterator();              while(it.hasNext()) {                   Entry add = new Entry(it.next());                   tmp.next = add;                   tmp = tmp.next;                   count++;              }              return true;          }          /*           * 如果index < count,则按以下逻辑处理。           * 记录下前趋节点,移动到index处时,将c中的元素追加到前趋节点末尾           */          int i = 0;          Entry tmp = head.next;          Entry pre = head;          while(i != index) {              tmp = tmp.next;              pre = pre.next;              i++;          }          //循环将c中的元素追加到pre的末尾          Iterator<? extends E> it = c.iterator();          while(it.hasNext()) {              Entry add = new Entry(it.next());              pre.next = add;              pre = pre.next;              count++;          }          //将pre的指针域指向原index处的节点tmp          pre.next = tmp;          return true;     }

size()

    返回链表中的元素个数   
public int size() {          return count; }

get(int index)

获取下标为index的元素。
    1 通过head指针,循环去访问后继元素
    2 因为插入时,是从开始结点插入的。获取时,后插入的先获取(栈)
/** 获取下标为index的元素*/public E get(int index) {          if(index < 0 || index >= size()){              throw new RuntimeException("IndexOutOfBounds");          }          //获取头指针          Entry headTemp = head;          //开始节点          Entry target = headTemp.next;          int i = 0;          while(i != index) {              target = target.next;              i++;          }          return target.value;     }

isEmpty() 

    空链表判断
public boolean isEmpty() {          return size() == 0;     }

remove(Object o)

    移除链表中第一个元素值为o的元素。
    记下当前节点的前趋节点,循环判断,如果移除的o与value相同,则将当前前趋节点的next指向
当前节点的next.
public boolean remove(Object o) {          Entry tmp = head.next;          if(null == tmp || null == o) {              return false;          }          //tmp的前趋节点          Entry pre = head;          while(null != tmp) {              Object v = tmp.value;              if(o.equals(v)) {                   pre.next = tmp.next;                   count--;                   return true;              }              pre = tmp;              tmp = tmp.next;          }          return false;     }

remove(intindex)

  删除index处的元素
public E remove(int index) {          if(index < 0 || index >= count) {              throw new RuntimeException("index越界");          }          //开始节点          Entry tmp = head.next;          int i = 0;          while(i != index) {              tmp = tmp.next;              i++;          }          return tmp.value;     }

removeAll(Collection<?> c)

    从链表中移除c中所有的元素。
    利用集合c的迭代子,循环移除
public boolean removeAll(Collection<?> c) {          Iterator<?> it =  c.iterator();          while(it.hasNext()) {              boolean re = remove(it.next());              if(re != true) {                   return false;              }          }          return true;     }

set(int index, E element)

     将index处的值设置为元素element。
public E set(int index, E element) {          if(index < 0 || index >= size()){              throw new RuntimeException("IndexOutOfBounds");          }          //获取头指针          Entry headTemp = head;          //开始节点          Entry target = headTemp.next;          int i = 0;          while(i != index) {              target = target.next;              i++;          }          E oldValue = target.value;          target.value = element;          return oldValue;     }

indexOf(Object o)

    获取某个值的索引。
    元素o为null和不为null时分开处理。
public int indexOf(Object o) {          Entry tmp = head.next;          int index = 0;          if(o == null) {//o为null              while(tmp != null && tmp.value != null) {                   tmp = tmp.next;                   index++;              }          } else {//o不为null              while(tmp != null && !o.equals(tmp.value)) {                   tmp = tmp.next;                   index++;              }          }                    if(null == tmp) {              return -1;          } else {              return index;          }     }

contains(Object o)和containsAll(Collection<?> c)

     链表中是否包含某个元素

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

   链表中是否包含集合c中的所有元素

public boolean containsAll(Collection<?> c) {          Iterator<?> it =  c.iterator();          while(it.hasNext()) {              boolean re = contains(it.next());              if(re != true) {                   return false;              }          }          return true;     }

clear()

        清空链表。只是让头节点指向了null。内存中真正的节点,并为消失
public void clear() {          head.next = null;          count = 0;     }

toArray()和toArray(T[] a)

     将链表转换为数组
public Object[] toArray() {          Object[] arr = new Object[count];          Entry tmp = head.next;          int i = 0;          while(null != tmp) {              arr[i] = tmp.value;              tmp = tmp.next;          }          return arr;     }

将链表转换为类型为T的数组,如果给定的a长度不够,则将重新实例化一个T数组。
public <T> T[] toArray(T[] a) {          //如果a的长度不够,则重新实例化一个数组          if (a.length < count)            a = (T[])java.lang.reflect.Array.newInstance(                                a.getClass().getComponentType(), count);          Object[] re = a;          Entry tmp = head.next;          int i = 0;          while(null != tmp) {              re[i] = tmp.value;              i++;              tmp = tmp.next;          }          //多出部分填充为null          if(a.length > count) {              a[count] = null;          }          return a;     }

lastIndexOf(Object o)

    返回链表中value等于o的倒数第一个索引值。
    逻辑:将链表向后移动判断每个value值,并使用一个变量lastIndex存储value与o最后一次相等的索引地址,当链表移动到末尾时,如果lastIndex值为-1,说明链表中不存在value为o的节点,否则,返回lastIndex的值。o为null时和不为null时,分开处理
public int lastIndexOf(Object o) {          Entry tmp = head.next;          int index = 0;          int lastIndex = -1;          if(o == null) {              while(tmp != null) {                   if(tmp.value != null) {                        tmp = tmp.next;                        index++;                   } else {                        lastIndex = index;                        tmp = tmp.next;                        index++;                   }              }          } else {              while(tmp != null) {                   if(!o.equals(tmp.value)) {//如果元素o与value不相等,则继续向后移动。                        tmp = tmp.next;                        index++;                   } else {//如果元素o与value相等,则记录下此处的索引,继续向后移动,寻找是否还有值与o相等。                        lastIndex = index;                        tmp = tmp.next;                        index++;                   }              }          }                    if(-1 == lastIndex) {              return -1;          } else {              return lastIndex;          }     }

retainAll(Collection<?> c)

    从链表中移除所有不在集合c中的元素。
public boolean retainAll(Collection<?> c) {          Entry tmp = head.next;          Entry pre = head;//tmp的前趋节点,移除时使用          while(null != tmp) {              E value = tmp.value;              if(!c.contains(value)) {//如果c中不包含value,则移除对应的节点,并将tmp指向tmp.next,pre指针不动。                   pre.next = tmp.next;                   count--;                         tmp = tmp.next;                   continue;              }              //如果c中包含value,则将tmp指向tmp.next,pre指向tmp。              pre = tmp;              tmp = tmp.next;          }          return true;     }

iterator()

    获取链表的迭代子
public Iterator<E> iterator() {          class Itr implements Iterator<E> {              //迭代类中,所处理元素的当前索引位置。起始为-1              private int cur = -1;                            @Override              public boolean hasNext() {                   return cur + 1 < size();              }              //获取迭代类中当前索引的元素              @Override              public E next() {                   cur++;                   E tmp = get(cur);                   return tmp;              }              @Override              public void remove() {                   //必须调用过next()方法                   if(cur < 0) {                        throw new RuntimeException("cur<0");                   }                                      //移除cur处的元素                   Entry tmp = head.next;                   Entry pre = head;                   int i = 0;                   while(cur != i && tmp != null) {//cur与i不相等且没有移动到末尾                        tmp = tmp.next;                        pre = pre.next;                        i++;                   }                   //当移动到当前处理的节点cur时,进行移除处理                   if(cur == i) {                        if(tmp != null) {                            //移除的为非末尾节点                             pre.next = tmp.next;                             count--;                             cur--;//迭代子处理的元素位置减1                             return;                        } else {                            //移除的为末尾节点                             pre.next = null;                             count--;                             cur--;//迭代子处理的元素位置减1                             return;                        }                   } else {                        throw new RuntimeException("找不到remove的元素");                   }              }                        }          return new Itr();     }