自己用java实现LinkList和arrayList
2017-08-08 15:33
239 查看
为了加深理解,我就自己写了下LinkList和arrayList。
下面贴下代码
双链表头尾放置两个值为null的Node对象,这样使头尾节点的处理也正常化,不会是删除头尾元素成为特别的情况存在。双链表还有就是每个节点存储上下两个节点的信息。删除的开销,在链表来,只是修改删除元素首尾节点的指向而已。而且由于是双链表可以从两端开始遍历,这样,用getNode方法,确认元素是在哪个半段。这样能用最快的速度来遍历。后面的迭代器实现,主要是用modcount参数,来保证链表的一致性的。
数组相较于上面的链表感觉删除就比较坑了,毕竟不知道要删除哪个元素。如果删除头元素,那么整个数组都要进行一次循环赋值,很坑的。其他的两者基本上都有点类似了。
下面贴下代码
链表代码 public class MyTwoLinkedList<AnyType> implements Iterable<AnyType> { private int theSize; private int modCount = 0; private Node<AnyType> beginMarker; private Node<AnyType> endMarker; private static class Node<AnyType> { public AnyType data; public Node<AnyType> prev; public Node<AnyType> next; public Node(AnyType d, Node<AnyType> p, Node<AnyType> n) { data = d; prev = p; next = n; } } public MyTwoLinkedList() { clear(); } public void clear() { beginMarker = new Node<AnyType>(null, null, null); endMarker = new Node<AnyType>(null, beginMarker, null); beginMarker.next = endMarker; theSize = 0; modCount++; } public int size() { return theSize; } public Boolean add(AnyType x) { add(size(), x); return true; } public void add(int idx, AnyType x) { addBefore(getNode(idx), x); } //搜索节点,先判断节点在前半段还是后半段,略提高效率,双链表可以从两个方向查找 private Node<AnyType> getNode(int idx) { Node<AnyType> p;//一个引用 if (idx < 0 || idx > size()) throw new IndexOutOfBoundsException(); if (idx < size() / 2) { p = beginMarker.next; for (int i = 0; i < idx; i++) p = p.next; } else { p = endMarker; for (int i = size(); i > idx; i--) p = p.prev; } return p; } private void addBefore(Node<AnyType> p, AnyType x) { Node<AnyType> newNode = new Node<AnyType>(x, p.prev, p);//双链表,新增节点插入指向前后 //前后两个节点的指向变化 newNode.prev.next = newNode; p.prev = newNode; theSize++; //修改次数+1 modCount++; } public AnyType get(int idx) { return getNode(idx).data; } public AnyType set(int idx, AnyType newVal) { //一个引用,改变节点值 Node<AnyType> p = getNode(idx); AnyType oldVal = p.data; p.data = newVal; return oldVal; } public AnyType remove(int idx) { return remove(getNode(idx)); } private AnyType remove(Node<AnyType> p) { p.next.prev = p.prev; p.prev.next = p.next; theSize--; //修改次数仍+1 modCount++; return p.data; } public java.util.Iterator<AnyType> iterator() { //返回一个实例化的内部类,该类是迭代器,内部实现 return new MyTwoLinkedList.LinkedListIterator(); } //实现Iterator接口 private class LinkedListIterator implements java.util.Iterator<AnyType> { //在内部指向第一个元素 private Node<AnyType> current = beginMarker.next; //检测在迭代期间集合被修改的情况,分别在next()和迭代器自己的remove()中检查,如果修改次数不同说明在迭代器迭代之外发生了修改行为 //迭代器自己的remove()调用外层类的remove,其中有modCount++,迭代器做出remove()动作后将expectecModCount++,保证迭代期间二者保持一致 private int expectedModCount = modCount; //okToRemove在next()执行后被置为true,在迭代器自己的remove()执行完后置为false,迭代器自己的remove()执行前检查其是否为true才执行,保证迭代一次才能删除一个,没有其他迭代时删除的方式 private boolean okToRemove = false; public boolean hasNext() { return current != endMarker; } public AnyType next() { if (modCount != expectedModCount) //同一时间修改冲突异常!! throw new java.util.ConcurrentModificationException(); if (!hasNext()) throw new java.util.NoSuchElementException(); //用一个引用指向并从外部类获取前一个元素数据 AnyType nextItem = current.data; //实际是改变一个引用的指向使其前进 current = current.next; okToRemove = true; return nextItem; } public void remove() { if (modCount != expectedModCount) 4000 throw new java.util.ConcurrentModificationException(); //不是迭代期间调用此迭代器remove()方法 if (!okToRemove) throw new IllegalStateException(); //调用外部类方法 //next()使current先指向下一元素,这里移除current前一个元素,这样边迭代边移除,先后移后删除前一个元素 MyTwoLinkedList.this.remove(current.prev); okToRemove = false; expectedModCount++; } } }
双链表头尾放置两个值为null的Node对象,这样使头尾节点的处理也正常化,不会是删除头尾元素成为特别的情况存在。双链表还有就是每个节点存储上下两个节点的信息。删除的开销,在链表来,只是修改删除元素首尾节点的指向而已。而且由于是双链表可以从两端开始遍历,这样,用getNode方法,确认元素是在哪个半段。这样能用最快的速度来遍历。后面的迭代器实现,主要是用modcount参数,来保证链表的一致性的。
ArrayList代码 public class MyTestArrayList<AnyType> implements Iterable<AnyType> { // //默认容器 private static final int DEFAULT_CAPACITY = 10; private int theSize; private AnyType[] theItems; public MyTestArrayList() { clear(); } public void clear() { theSize = 0; ensureCapacity(DEFAULT_CAPACITY); } public void ensureCapacity(int newCapacity) { if (newCapacity < theSize) { return; } AnyType[] old = theItems; theItems = (AnyType[]) new Object[newCapacity]; for (int i = 0; i < size(); i++) { theItems[i] = old[i]; } } public Boolean add(AnyType x) { add(size(), x); return true; } public void add(int idx, AnyType x) { if (idx > size()) { throw new IndexOutOfBoundsException("Index:" + idx + " Size :" + size()); } if (theItems.length == size()) ensureCapacity(size() * 2); for (int i = theSize; i > idx; i--) theItems[i] = theItems[i - 1]; theItems[idx] = x; theSize++; } public AnyType get(int idx) { if (idx < 0 || idx > size()) throw new ArrayIndexOutOfBoundsException(); return theItems[idx]; } public AnyType set(int idx, AnyType x) { if (idx < 0 || idx > size()) throw new ArrayIndexOutOfBoundsException(); AnyType oldValue = theItems[idx]; theItems[idx] = x; return oldValue; } public Boolean isEmpty() { return size() == 0; } public int size() { return theSize; } public AnyType remove(int idx) { AnyType deleteItem = theItems[idx]; for (int i = idx; i < size() - 1; i++) { theItems[i] = theItems[i + 1]; } // theSize--; theItems[--theSize] = null; return deleteItem; } public java.util.Iterator<AnyType> iterator(){ return new ArrayListIterator(); } public class ArrayListIterator implements java.util.Iterator<AnyType> { private int current = 0; public boolean hasNext() { return current < size(); } public AnyType next(){ if(!hasNext()) throw new java.util.NoSuchElementException(); return theItems[current++]; } public void remove(){ //MyArraList.this代表外层类MyArrayList的对象 //--current这里暂解释为remove在next方法后调用,next让current++, //这里让current回到原来位置,删除它 //因为如果不调用next直接remove,current会出现<0情况 MyTestArrayList.this.remove(--current); } } }
数组相较于上面的链表感觉删除就比较坑了,毕竟不知道要删除哪个元素。如果删除头元素,那么整个数组都要进行一次循环赋值,很坑的。其他的两者基本上都有点类似了。
相关文章推荐
- [JAVA]集合框架之自己实现一个具有基本增查删改功能的ArrayList
- 数据结构—顺序表(自己实现Java的ArrayList)
- Java -- 自己实现数组列表(Arraylist)
- java自己实现顺序线性表ArrayList
- Java中SJBArrayList自己简单实现ArrayList
- Java自己实现双向链表LinkList
- 自己理解的java.util.ArrayList(二)实现类
- java中自己实现一个ArrayList
- Java自己实现双向链表LinkList
- Java之实现自己的ArrayList与LinkedList
- JAVA--自己实现ArrayList
- 【java集合】自己实现简易的ArrayList
- java 集合ArrayList及LinkList源码分析
- 自己理解的java.util.ArrayList(一)设计及接口
- 使用BlazeDS实现java与flex传对象时,RemoteClass中包含自己写的类,后台无法转换的问题
- 深入Java集合学习系列:ArrayList的实现原理
- java:ArrayList,Vector,LinkedList的实现
- 自己琢磨的 图像相似度算法 JAVA版实现
- java 集合ArrayList及LinkList源码分析
- 深入Java集合学习系列:ArrayList的实现原理