您的位置:首页 > 理论基础 > 数据结构算法

[Java]常见数据结构的实现(持续更新)

2016-05-19 21:16 453 查看
1.ArrayList的自定义实现

代码:

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

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: