您的位置:首页 > 编程语言 > Java开发

自己用java实现LinkList和arrayList

2017-08-08 15:33 239 查看
为了加深理解,我就自己写了下LinkList和arrayList。

下面贴下代码

链表代码

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