《数据结构与算法分析java语言描述》学习笔记二

一、抽象数据类型

 抽象数据类型(abstract data type,ADT)是带有一组操作的一些对象的集合。

二、ArrayList 的实现

自定义ArrayList 实现代码如下:

package com.caitang.mjq;

import java.util.Iterator;
/**
 * 自定义实现链表   问题:
 * 1.何时使用theSize,何时使用size();
 * 2.为何要扩容至两倍;
 * @author Administrator
 *
 * @param <AnyType>
 */
public class MyArrayList <AnyType>implements Iterable<AnyType>
{
	/**
	 * 自定义链表的默认容量    10
	 */
	private static final int DEFAULT_CAPACITY = 10;
	/**
	 * 链表的大小——当前链表中的 元素的个数
	 */
	private int theSize;
	/**
	 * 用于链表实现的数组  
	 */
	private  AnyType [] theItems;
	/**
	 * 构造方法
	 */
	public MyArrayList()
	{
		doClear();
	}
	/**
	 * 清空链表
	 */
	public void clear()
	{
		doClear();
	}
	/**
	 * 清空链表
	 */
	private void doClear()
	{
		//设置链表元素个数为 0 
		theSize = 0;
		//链表初始化方法,确保不发生异常
		ensureCapacity(DEFAULT_CAPACITY);
	}
	/**
	 * 返回当前链表的元素个数
	 * @return
	 */
	public int size()
	{
		return theSize;
	}
	/**
	 * 返回当前链表是不是空表(元素个数是否为0)
	 * @return
	 */
	public boolean isEmpty()
	{
		return theSize == 0;
	}
	/**
	 * 将链表数组大小修改为元素个数大小,以避免空间资源浪费
	 */
	public void trimToSize()
	{
		ensureCapacity(size());
	}
	/**
	 * 获取某个指定索引位置上的元素
	 * @param idx 索引参数
	 * @return
	 */
	public AnyType get(int idx)
	{
		//如果索引参数小于0或者大于链表元素最大索引(size()-1,从零开始,等于链表元素个数-1);则抛出数组越界异常
		if(idx<0||idx>=size())
		{
			throw new ArrayIndexOutOfBoundsException();
		}
		return theItems[idx];
	}
	/**
	 * 修改链表中指定索引位置处的元素的值为指定的值
	 * @param idx 索引参数
	 * @param newVal 新的元素值
	 * @return 原来的元素值
	 */
	public AnyType set(int idx,AnyType newVal)
	{
		if(idx<0||idx>=size())
		{
			throw new ArrayIndexOutOfBoundsException();
		}
		AnyType old = theItems[idx];
		theItems [idx] = newVal;
		return old;
	}
	/**
	 * 对链表容量进行扩充,以保证不会发生数组越界。
	 * @param newCapacity 扩充后的容量
	 */
	@SuppressWarnings("unchecked")
	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];
		}
	}
	/**
	 * 在指定索引位置新增元素
	 * @param idx 索引参数
	 * @param x 新增元素
	 */
	public void add(int idx,AnyType x)
	{
		//如果链表数组还剩下一个元素的空位,则将链表容量扩容至两倍
		if(theItems.length==size())
		{
			ensureCapacity(size()*2+1);
		}
		//从索引位置开始,其后每个元素都向后移动一个位置
		for(int i = theSize;i>idx;i--)
		{
			theItems[i]=theItems[i-1];
		}
		//设置 位置索引为 idx处的元素的值为x
		theItems[idx] = x;
		//链表大小(元素个数)+1
		theSize++;
	}
	/**
	 * 向链表最后端添加元素
	 * @param x 添加的新元素
	 * @return 是否添加成功
	 */
	public boolean add(AnyType x)
	{
		add(size(),x);
		return true;
	}
	/**
	 * 删除指定索引处的元素
	 * @param idx 位置索引参数
	 * @return 被删除的元素值
	 */
	public AnyType remove(int idx)
	{
		if(idx<0||idx>=size())
		{
			throw new ArrayIndexOutOfBoundsException();
		}
		AnyType removedItem = theItems[idx];
		for(int i=idx;i<size()-1;i++)
		{
			theItems[i]=theItems[i+1];
		}
		theSize --;
		return removedItem;
	}
	/**
	 * 链表 迭代器 返回自定义迭代器
	 */
	@Override
	public Iterator<AnyType> iterator() 
	{
		return new ArrayListIterator();
	}
	/**
	 * 内部类 实现Iterator
	 * @author Administrator
	 *
	 */
	private class ArrayListIterator implements java.util.Iterator<AnyType>
	{
		/**
		 * 迭代器当前指针位置——与链表数组的索引对应
		 */
		private int current = 0;
		

		/**
		 * 是否有下一个元素
		 */
		@Override
		public boolean hasNext()
		{
			return current < size();
		}
		/**
		 * 返回下一个元素(当前索引+1 处)
		 */
		@Override
		public AnyType next() 
		{
			if(!hasNext())
			{
				throw new java.util.NoSuchElementException();
			}
			return theItems[current++];
		}
		/**
		 * 迭代器 删除链表元素;循环中直接使用链表方法进行元素删除会抛出异常,需要使用迭代器的删除方法
		 * 问题:迭代器删除方法同样是调用链表删除元素的方法,为什么使用迭代器删除方法就不会报错,而使用链表删除方法就会报错?
		 */
		public void remove()
		{
			MyArrayList.this.remove(--current);
		}
	}
}

单元测试代码如下:

package com.caitang.mjq.test;

import org.junit.Before;
import org.junit.Test;

import com.caitang.mjq.MyArrayList;

public class TestMyArrayList 
{
	/**
	 * 自定义链表测试对象
	 */
	private MyArrayList<Integer> list = new MyArrayList<Integer>();

	@Before
    public void add()
    {
    	list.add(1);
    	list.add(2);
    	list.add(3);
    	list.add(4);
    	assert list.size() == 3 :"链表新增元素,大小异常";
    }
    @Test
	public void create()
    {
    	assert list.size() == 0:"链表初始化大小异常";
    }
    /**
     * 
     */
    @Test
    public void isEmpty()
    {
    	boolean b = list.isEmpty();
    	assert b == true : "是否是空链表异常";
    }
    @Test
    public void get()
    {
    	assert list.get(2)==3 : "链表获取元素,元素值异常";
    	
    }
    @Test
    public void remove()
    {
    	list.remove(0);
    	assert list.get(0) == 2;
    	assert list.get(1) == 3;
    	assert list.size() == 3;
    	list.remove(2);
    	assert list.get(1) == 3;
    	assert list.size() == 2;
    }
    
    @Test
    public void set()
    {
    	list.set(1, 1);
    	assert list.get(1) == 1;
    }
    /**
     * 
     */@Test
    public void clear()
    {
    	list.clear();
    	assert list.size() == 0;
    }
    
}
单元测试运行结果如下:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值