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

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



*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值