[Java]常见数据结构的实现(持续更新)
2016-05-19 21:16
453 查看
1.ArrayList的自定义实现
代码:
测试:
结果:
cn.itcast.alg.MyArrayList@1c78e57
aaa
cn.itcast.alg.MyArrayList@1c78e57
12335
cn.itcast.alg.MyArrayList@1c78e57
sdfljsdl
cn.itcast.alg.MyArrayList@1c78e57
3
cn.itcast.alg.MyArrayList@1c78e57
AAA
cn.itcast.alg.MyArrayList@1c78e57
3950
cn.itcast.alg.MyArrayList@1c78e57
X
cn.itcast.alg.MyArrayList@1c78e57
2.LinkedList的自定义实现
代码:
测试:
代码:
package cn.itcast.alg; public class MyArrayList<AnyType> implements Iterable<AnyType> { //默认容量 private static final int DEFAULT_CAPACITY=10; private int theSize; private AnyType[] theItems; public MyArrayList(){ clear(); } public void clear(){ theSize=0; ensureCapacity(DEFAULT_CAPACITY); } public int size(){ return theSize; } public boolean isEmpty(){ return size()==0; } public void trimToSize(){ ensureCapacity(size()); } public AnyType get(int idx){ if(idx<0 || idx>=size()) throw new ArrayIndexOutOfBoundsException(); return theItems[idx]; } public AnyType set(int idx,AnyType newVal){ if(idx<0 || idx>=size()) throw new ArrayIndexOutOfBoundsException(); AnyType old=theItems[idx]; theItems[idx]=newVal; return old; } 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; } //真正赋予size()和theItems.length意义的 public void add(int idx,AnyType x){ //实际大小达到默认数组长度,先扩容 if(theItems.length==size()) ensureCapacity(size()*2+1); //不用考虑细微情况,逻辑合理就没错 //加一个元素,最后一个元素下标变成theSize,扩了容,实际大小+1,不越界 for(int i=theSize;i>idx;i--) theItems[i]=theItems[i-1]; theItems[idx]=x; theSize++;//真正大小+1 } public AnyType remove(int idx){ AnyType removedItem=theItems[idx]; for(int i=idx;i<size()-1;i++) theItems[i]=theItems[i+1]; //写成了++,造成后面测试错误!太蠢了!!! theSize--; return removedItem; } public java.util.Iterator<AnyType> iterator(){ return new ArrayListIterator();//直接返回这个内部类的实例 } //内部类实现迭代器 private class ArrayListIterator implements java.util.Iterator<AnyType>{ private int current=0; public boolean hasNext(){ return current<size(); } //实现了Iterator<AnyType>接口, //但如果将ArrayListIterator定义为泛型,这里就需要将返回的AnyType再强转为AnyType,不知道为什么! //可能是因为AnyType是外部那个类的泛型,又是这里这个类的泛型(迭代器参数类型) //返回的外部类的AnyType对于ArrayListIterator<AnyType>来说是Object类型 public AnyType next(){ if(!hasNext()) throw new java.util.NoSuchElementException(); //这里实现+1,是后+1,所以这里current实际代表next return theItems[current++]; } //这里返回void是遵循Iterator<AnyType>接口规范 public void remove(){ //MyArraList.this代表外层类MyArrayList的对象 //--current这里暂解释为remove在next方法后调用,next让current++, //这里让current回到原来位置,删除它 //因为如果不调用next直接remove,current会出现<0情况 MyArrayList.this.remove(--current); } } }
测试:
package cn.itcast.alg; public class TestMyArrayList { public static void main(String[] args){ MyArrayList mal=new MyArrayList(); mal.add("12335"); mal.add("sdfljsdl"); mal.add("3"); mal.add("aaa"); mal.add("AAA"); mal.add("3950"); mal.add("X"); System.out.println(mal); System.out.println(mal.remove(3)); System.out.println(mal); for(java.util.Iterator<String> its=mal.iterator();its.hasNext();){ System.out.println(its.next()); its.remove(); //这里要看到元素,得自己实现toString方法然后调用! System.out.println(mal); } } }
结果:
cn.itcast.alg.MyArrayList@1c78e57
aaa
cn.itcast.alg.MyArrayList@1c78e57
12335
cn.itcast.alg.MyArrayList@1c78e57
sdfljsdl
cn.itcast.alg.MyArrayList@1c78e57
3
cn.itcast.alg.MyArrayList@1c78e57
AAA
cn.itcast.alg.MyArrayList@1c78e57
3950
cn.itcast.alg.MyArrayList@1c78e57
X
cn.itcast.alg.MyArrayList@1c78e57
2.LinkedList的自定义实现
代码:
import java.util.*; //自定义双向链表 //实现Iterable接口,可迭代 public class MyLinkedList<AnyType> implements Iterable<AnyType> { //声明为static,嵌套类,类的一部分,并且独立于外围类对象存在 private static class Node<AnyType> { //初始化:值,前驱和后继节点 public Node(AnyType d,Node<AnyType> p,Node<AnyType> n) { data=d; prev=p; next=n; } //外围均可访问 public AnyType data; public Node<AnyType> prev; public Node<AnyType> next; } public MyLinkedList() { clear(); } public void clear() { beginMarker=new Node<AnyType>(null,null,null); endMarker=new Node<AnyType>(null,beginMarker,null); //endMarker后于beginMarker定义,初始化时指向beginMarker,beginMarker无法在初始化时指向endMarker beginMarker.next=endMarker; theSize=0; modCount++; } public int size() { return theSize; } public boolean isEmpty() { return size()==0; } //加到末尾 public boolean add(AnyType x) { add(size(),x); return true; } public void add(int idx,AnyType x) { addBefore(getNode(idx),x); } 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 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++; } private AnyType remove(Node<AnyType> p) { p.next.prev=p.prev; p.prev.next=p.next; theSize--; //修改次数仍+1 modCount++; return p.data; } //搜索节点,先判断节点在前半段还是后半段,略提高效率,双链表可以从两个方向查找 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; } public java.util.Iterator<AnyType> iterator() { //返回一个实例化的内部类,该类是迭代器,内部实现 return new 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) throw new java.util.ConcurrentModificationException(); //不是迭代期间调用此迭代器remove()方法 if(!okToRemove) throw new IllegalStateException(); //调用外部类方法 //next()使current先指向下一元素,这里移除current前一个元素,这样边迭代边移除,先后移后删除前一个元素 MyLinkedList.this.remove(current.prev); okToRemove=false; expectedModCount++; } } private int theSize; private int modCount=0; private Node<AnyType> beginMarker; private Node<AnyType> endMarker; }
测试:
import java.util.*; class TestMyLinkedList { public static void main(String[] args) { MyLinkedList<String> list=new MyLinkedList<String>(); list.add("dslfjsld"); list.add("3947fo"); list.add("flds34"); list.add("0"); list.add("xYz"); list.add("A"); list.add("a"); list.add("bdc"); list.add("B39vdslfjl"); for(Iterator iter=list.iterator();iter.hasNext();) //注意是迭代器的而不是集合的next()方法!! System.out.println(iter.next()); System.out.println("----------------Hello World!--------------------"); //实现Iterable就可以用高级for循环 //每次都会new一个新的Iterator对象指向第一个元素 //要用泛型 for(String str:list) System.out.println(str); } }错误记录及修改后正确执行结果:
/* D:\java\practice5>javac MyLinkedList.java MyLinkedList.java:29: 找不到符号 符号: 变量 beginMarker 位置: 类 MyLinkedList<AnyType> beginMarker=new Node<AnyType>(null,null,null); ^ MyLinkedList.java:30: 找不到符号 符号: 变量 endMarker 位置: 类 MyLinkedList<AnyType> endMarker=new Node<AnyType>(null,beginMarker,null); ^ MyLinkedList.java:30: 找不到符号 符号: 变量 beginMarker 位置: 类 MyLinkedList<AnyType> endMarker=new Node<AnyType>(null,beginMarker,null); ^ MyLinkedList.java:32: 找不到符号 符号: 变量 beginMarker 位置: 类 MyLinkedList<AnyType> beginMarker.next=endMarker; ^ MyLinkedList.java:32: 找不到符号 符号: 变量 endMarker 位置: 类 MyLinkedList<AnyType> beginMarker.next=endMarker; ^ MyLinkedList.java:34: 找不到符号 符号: 变量 theSize 位置: 类 MyLinkedList<AnyType> theSize=0; ^ MyLinkedList.java:35: 找不到符号 符号: 变量 modCount 位置: 类 MyLinkedList<AnyType> modCount++; ^ MyLinkedList.java:40: 找不到符号 符号: 变量 theSize 位置: 类 MyLinkedList<AnyType> return theSize; ^ MyLinkedList.java:80: 找不到符号 符号: 变量 prev 位置: 类 MyLinkedList<AnyType> Node<AnyType> newNode=new Node<AnyType>(x,p,prev,p);//双链表,新 增节点插入指向前后 ^ MyLinkedList.java:80: 内部错误;无法将位于 MyLinkedList.Node<AnyType> 的 MyLinke dList.Node.<init> 实例化为 () Node<AnyType> newNode=new Node<AnyType>(x,p,prev,p);//双链表,新 增节点插入指向前后 ^ MyLinkedList.java:84: 找不到符号 符号: 变量 theSize 位置: 类 MyLinkedList<AnyType> theSize++; ^ MyLinkedList.java:86: 找不到符号 符号: 变量 modCount 位置: 类 MyLinkedList<AnyType> modCount++; ^ MyLinkedList.java:93: 找不到符号 符号: 变量 theSize 位置: 类 MyLinkedList<AnyType> theSize--; ^ MyLinkedList.java:95: 找不到符号 符号: 变量 modCount 位置: 类 MyLinkedList<AnyType> modCount++; ^ MyLinkedList.java:108: 找不到符号 符号: 变量 beginMarker 位置: 类 MyLinkedList<AnyType> p=beginMarker.next; ^ MyLinkedList.java:114: 找不到符号 符号: 变量 endMarker 位置: 类 MyLinkedList<AnyType> p=endMarker; ^ MyLinkedList.java:130: 找不到符号 符号: 变量 beginMarker 位置: 类 MyLinkedList<AnyType>.LinkedListIterator private Node<AnyType> current=beginMarker.next; ^ MyLinkedList.java:134: 找不到符号 符号: 变量 modCount 位置: 类 MyLinkedList<AnyType>.LinkedListIterator private int expectedModCount=modCount; ^ MyLinkedList.java:141: 找不到符号 符号: 变量 endMarker 位置: 类 MyLinkedList<AnyType>.LinkedListIterator return current!=endMarker; ^ MyLinkedList.java:146: 找不到符号 符号: 变量 modCount 位置: 类 MyLinkedList<AnyType>.LinkedListIterator if(modCount!=expectedModCount) ^ MyLinkedList.java:161: 找不到符号 符号: 变量 modCount 位置: 类 MyLinkedList<AnyType>.LinkedListIterator if(modCount!=expectedModCount) ^ 21 错误 D:\java\practice5>javac MyLinkedList.java MyLinkedList.java:80: 找不到符号 符号: 变量 prev 位置: 类 MyLinkedList<AnyType> Node<AnyType> newNode=new Node<AnyType>(x,p,prev,p);//双链表,新 增节点插入指向前后 ^ MyLinkedList.java:80: 内部错误;无法将位于 MyLinkedList.Node<AnyType> 的 MyLinke dList.Node.<init> 实例化为 () Node<AnyType> newNode=new Node<AnyType>(x,p,prev,p);//双链表,新 增节点插入指向前后 ^ 2 错误 D:\java\practice5>javac MyLinkedList.java D:\java\practice5>javac TestMyLinkedList.java TestMyLinkedList.java:17: 找不到符号 符号: 类 Iterator 位置: 类 TestMyLinkedList for(Iterator iter=list.iterator();iter.hasNext();) ^ TestMyLinkedList.java:18: 找不到符号 符号: 方法 next() 位置: 类 MyLinkedList System.out.println(list.next()); ^ TestMyLinkedList.java:22: 不兼容的类型 找到: java.lang.Object 需要: java.lang.String for(String str:list) ^ TestMyLinkedList.java:23: 找不到符号 符号: 方法 next() 位置: 类 MyLinkedList System.out.println(list.next()); ^ 注意:TestMyLinkedList.java 使用了未经检查或不安全的操作。 注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。 4 错误 D:\java\practice5>javac TestMyLinkedList.java TestMyLinkedList.java:27: 找不到符号 符号: 方法 next() 位置: 类 MyLinkedList<java.lang.String> System.out.println(list.next()); ^ 1 错误 D:\java\practice5>javac TestMyLinkedList.java D:\java\practice5>java TestMyLinkedList dslfjsld 3947fo flds34 0 xYz A a bdc B39vdslfjl ----------------Hello World!-------------------- dslfjsld 3947fo flds34 0 xYz A a bdc B39vdslfjl */
相关文章推荐
- SDUT3334数据结构实验之栈七:出栈序列判定
- PAT 团体程序设计天梯赛-练习集 L2-006. 树的遍历【数据结构】
- 栈和队列测试题
- [数据结构]Binary_tree | Binary_search_tree | avl_tree
- HYSBZ 1012
- 【数据结构】串 YTU 2297 KMP算法(3)next
- 【数据结构】串 YTU 2296 KMP算法(2)next
- 【数据结构】串 YTU 2295 KMP算法(1)next
- 数据结构与算法分析(3)算法分析
- 数据结构之红黑树
- Redis各种数据结构内存占用测试
- MySQL索引背后的数据结构及算法原理
- C/C++,java 数据结构---线性链表存储数据:获取数据慢,增删快
- java 数据结构和泛型
- 数据结构之排序
- 【数据结构】平衡二叉树—AVL树
- Java 容器类内部使用的数据结构
- 数据结构提纲
- Windows内核中的数据结构与函数调用
- 链表List