From b1a58617cf720378c0e75618b7fac333707f92fc Mon Sep 17 00:00:00 2001 From: brucejiao1 Date: Sun, 26 Feb 2017 18:10:04 +0800 Subject: [PATCH] =?UTF-8?q?0226=E4=BD=9C=E4=B8=9A=EF=BC=9A=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0ArrayList,LinkedList,Stack,Queue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bruce/homework0226/ArrayListV00.java | 177 +++++++++++++++ .../src/com/bruce/homework0226/JuintTest.java | 141 ++++++++++++ .../com/bruce/homework0226/LinkedListV00.java | 204 ++++++++++++++++++ .../src/com/bruce/homework0226/QueueV00.java | 117 ++++++++++ .../src/com/bruce/homework0226/StackV00.java | 144 +++++++++++++ .../src/com/bruce/utils/MyException.java | 29 +++ 6 files changed, 812 insertions(+) create mode 100644 group15/1510_739253131/src/com/bruce/homework0226/ArrayListV00.java create mode 100644 group15/1510_739253131/src/com/bruce/homework0226/JuintTest.java create mode 100644 group15/1510_739253131/src/com/bruce/homework0226/LinkedListV00.java create mode 100644 group15/1510_739253131/src/com/bruce/homework0226/QueueV00.java create mode 100644 group15/1510_739253131/src/com/bruce/homework0226/StackV00.java create mode 100644 group15/1510_739253131/src/com/bruce/utils/MyException.java diff --git a/group15/1510_739253131/src/com/bruce/homework0226/ArrayListV00.java b/group15/1510_739253131/src/com/bruce/homework0226/ArrayListV00.java new file mode 100644 index 0000000000..3137c7568b --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0226/ArrayListV00.java @@ -0,0 +1,177 @@ +package com.bruce.homework0226; + +import com.bruce.utils.MyException; + +import java.io.Serializable; +import java.util.Arrays; + +/** + * 用数组实现ArrayList基本功能:add,remove,size,contains,toArray方法 + * @Version: 0.0 + * Created by Bruce.Jiao on 17-2-23. + */ +public class ArrayListV00 implements Serializable { + + /** + * 存放集合元素的数组 + */ + private transient Object[] elementData; + /** + * 集合中元素的个数 + */ + private int size; + + /** + * 空构造,默认数组长度为10 + */ + public ArrayListV00() throws MyException { + this(10); + } + + /** + * 有参构造 + * + * @param initCapacity + * 用户传入的集合大小,底层数组的初始化大小 + */ + public ArrayListV00(int initCapacity) throws MyException{ + if(initCapacity < 0){ + throw new MyException("集合大小不能小于0"); + } + elementData = new Object[initCapacity]; + } + + /** + * 向集合中添加元素 + * + * @param value + * 添加的元素,允许添加null + * @return true:添加成功 ; false:添加失败 + */ + public boolean add(Object value) { + // 添加元素之前,对数组长度进行判断,此处需要传入当前元素个数+1, + ensureCapacity(size + 1); + elementData[size++] = value; + return true; + } + + /** + * 返回指定位置的元素 数组和集合,下标从1开始 + * + * @param index + * 用户指定的位置 + * @return + */ + public Object get(int index) throws MyException { + // 判断是否越界,注意:此处判断依据是size,而不能是elementData.length, + // 集合元素个数size小于等于elementData.length + if (index >= size || index < 0) { + throw new MyException("给定数值超出集合范围"); + } + return elementData[index]; + } + + /** + * 删除指定位置的元素 + * + * @param index + * 用户指定位置,从0开始 + * @return 返回删除掉的指定位置的元素 + */ + public Object remove(int index) throws MyException { + if (index >= size || index < 0) { + throw new MyException("给定数值超出集合范围"); + } + Object value = elementData[index]; + // 数组中被删除元素后边的所有元素的个数,此处不能使用elementData.length + int length = size - 1 - index; + // 被删除位置后还有元素,将数组中被删除位置往后(不包含被删除位置)的所有元素往前移动一位 + if (length > 0) { + System.arraycopy(elementData, index + 1, elementData, index, length); + } + elementData[--size] = null; + return value; + } + + /** + * 判断集合中是否包含指定的元素 + * + * @param value + * 用户制定的元素 + * @return true:包含指定元素;false:不包含指定元素 + */ + public boolean contains(Object value) { + for (int i = 0; i < elementData.length; i++) { + if (value == null) { + if (elementData[i] == null) { + return true; + } + } else { + if (value.equals(elementData[i])) { + return true; + } + } + } + return false; + } + + /** + * 得到集合对应的静态数组 + * + * @return 底层数组 + */ + public Object[] toArray() { + //elementData可能会包含null元素,不能直接返回,需返回一个包含集合所有元素的新数组 +// return elementData; + return Arrays.copyOf(elementData,size); + } + + /** + * 返回集合大小 + * + * @return + */ + public int size() { + return size; + } + + /** + * 传入的数值与数组长度进行比较,长度小于传入数值,对数组进行扩容 + * + * @param minCapacity + * 传入的数值 + */ + public void ensureCapacity(int minCapacity) { + int oldCapacity = elementData.length; + // 如果传入数值大于现有数组长度,对现有数组进行扩容 + if (minCapacity > oldCapacity) { + // 此处用新的局部变量引用指向原有数组的内存地址,仅为了避免复制数组元素到新数组时候,发生原有数组内存地址被覆盖的情况 + Object[] oldArray = elementData; + // 先得到现有数组长度1.5倍的值 + int newCapacity = oldCapacity + oldCapacity >> 1; + // 如果增加1.5倍后的数值仍然小于传入的数值,将传入的数值赋给新数组长度 + if (minCapacity > newCapacity) { + newCapacity = minCapacity; + } + // 将elementData引用指向一个新的扩容后的数组,并且将原有数组的元素复制到新数组中 + elementData = Arrays.copyOf(elementData, newCapacity); + } + } + + /** + * 重写toString方法,查看集合具体内容 + * @return + */ + @Override + public String toString() { + return Arrays.toString(elementData); + } + + /** + * 仅仅作为自己查看底层数组长度的方法, + * @return + */ + int arrayLength() { + return elementData.length; + } +} diff --git a/group15/1510_739253131/src/com/bruce/homework0226/JuintTest.java b/group15/1510_739253131/src/com/bruce/homework0226/JuintTest.java new file mode 100644 index 0000000000..b0aa452f6d --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0226/JuintTest.java @@ -0,0 +1,141 @@ +package com.bruce.homework0226; + +import com.bruce.utils.MyException; +import junit.framework.TestCase; +import org.junit.Test; +import java.util.Arrays; +import java.util.Random; + +/** + * Created by Bruce.Jiao on 17-2-23. + */ +public class JuintTest extends TestCase{ + + @Test + public void testArrayList(){ + try { + ArrayListV00 arrayList = new ArrayListV00(0); + arrayList.add("aaa"); + arrayList.add("bbb"); + arrayList.add("ccc"); + arrayList.add("fff"); + arrayList.add("ggg"); + System.out.println("集合下标2处的元素:"+arrayList.get(2)); + System.out.println("是否包含ccc这个元素:"+arrayList.contains("ccc")); + System.out.println("是否包含ddd这个元素:"+arrayList.contains("ddd")); + System.out.println("删除前集合大小为:"+arrayList.size()); + System.out.println("删除下标2处元素前底层数组:"+arrayList); + arrayList.remove(2); + System.out.println("删除下标2处元素后底层数组:"+arrayList); + System.out.println("删除一个元素后集合大小为:"+arrayList.size()); + arrayList.remove(2); + System.out.println("再删除下标2处元素后底层数组:"+arrayList); + System.out.println("集合为:"+ Arrays.toString(arrayList.toArray())); + System.out.println("集合底层数组长度:"+ arrayList.arrayLength()); +// System.out.println("集合下标-1处的元素:"+arrayList.get(-1)); + } catch (MyException e) { + System.out.println("发生异常>>>"+e); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testLinkedList(){ + try { + LinkedListV00 linkedList = new LinkedListV00<>(); + linkedList.add("aaa"); + linkedList.add("bbb"); + linkedList.add("ccc"); + linkedList.add("ddd"); + System.out.println("删除index=2的元素前:"+linkedList); + System.out.println("链表尺寸"+linkedList.size()); + System.out.println("拿到index=2的元素"+linkedList.get(2)); + linkedList.remove(2); + System.out.println("删除index=2的元素后:"+linkedList); + } catch (MyException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testStack(){ + try { + StackV00 stack = new StackV00(); + stack.push("ccc"); + stack.push(null); + stack.push("bbb"); + stack.push("aaa"); + System.out.println("栈的大小:"+stack.size()); + System.out.println("栈是否为空:"+stack.isEmpty()); + System.out.println("栈是否为空:"+stack); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + stack.clear(); + System.out.println("清空后,栈大小:"+stack.size()); + System.out.println("栈是否为空:"+stack.isEmpty()); + } catch (MyException e) { + System.out.println(e); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testQueue(){ + try { + QueueV00 queue = new QueueV00(); + System.out.println("队列是否为空:"+queue.isEmpty()); + queue.add("aaa"); + queue.add("bbb"); + queue.add("ccc"); + queue.add("ddd"); + System.out.println(queue); + System.out.println("queue.peek结果:"+queue.peek()); + System.out.println("peek后队列长度:"+queue.length()); + System.out.println("queue.poll结果:"+queue.poll()); + System.out.println("poll后队列长度:"+queue.length()); + System.out.println("队列是否为空:"+queue.isEmpty()); + } catch (MyException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testArrayLinked(){ + try { + ArrayListV00 arrayList = new ArrayListV00(); + LinkedListV00 linkedList = new LinkedListV00(); + long start1 = System.currentTimeMillis(); + for(int i = 0;i<10000;i++){ + arrayList.add("abc"+i); + } + long end1 = System.currentTimeMillis(); + for(int i = 0;i<10000;i++){ + linkedList.add("abc"+i); + } + long end2 = System.currentTimeMillis(); + System.out.println("ArrayList的时间:"+(end1-start1)); + System.out.println("LinkedList的时间:"+(end2-end1)); + } catch (MyException e) { + e.printStackTrace(); + } + } + + public String getRandomString(int length){ + String base = "abcdefghijklmnopqrstuvwxyz0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for(int i = 0;i implements Serializable { + + /** + * 双向链表中节点实例的个数 + */ + private transient int size = 0; + + /** + * 前一个节点 + */ + private transient Node first; + + /** + * 后一个节点 + */ + private transient Node last; + + /** + * 空构造 + */ + public LinkedListV00(){} + + /** + * 添加一个节点 + * @param element + * @return + */ + public boolean add(E element){ + linkNext(element); + return true; + } + + /** + * 拿到制定位置的元素 + * @param index + * @return + */ + public E get(int index) throws MyException{ + if(index < 0 || index > size){ + throw new MyException("索引越界"); + } + return node(index).element; + } + + /** + * 删除指定位置的元素 + * 将index-1处节点的next指向index+1处节点,将index+1处节点的previous指向index-1节点 + * @param index 节点位置 + * @return 删除节点的element数据 + */ + public E remove(int index) throws MyException{ + if(index < 0 || index > size){ + throw new MyException("节点索引越界"); + } + return unlink(node(index)); + } + + /** + * 返回链表的长度 + * @return 双向链表中节点实例的个数 + */ + public int size(){ + return size; + } + + /** + * 拿到链表对应的数组 + * @return 链表各节点的element元素组成的数组 + */ + public Object[] toArray(){ + Object[] array = new Object[size]; + for(int i = 0;i x = first; x != null; x = x.next) +// result[i++] = x.element; +// return result; + } + + /** + * 表示一个节点的内部类 + * @param 链表元素泛型 + */ + private static class Node{ + E element; + Node previous; + Node next; + Node(Node previous,E element,Node next){ + this.element = element; + this.previous = previous; + this.next = next; + } + } + + /** + * 根据索引拿对应的节点 + * @param index 索引号 + * @return 索引号对应的节点 + */ + private Node node(int index){ + Node x; + //如果index小于size的一半,即目标节点在链表前半部分 + if(index < (size >> 1)){ + //从第一个节点挨个向后查找,一直到(index-1)处,将其next赋值给x + x = first; + for(int i = 0; iindex;i--){ + x = x.previous; + } + } + //返回x + return x; + } + + /** + * 链接下一个 + * @param e 新节点的element + */ + private void linkNext(E e){ + //将当前的last节点赋值给n + final Node n = last; + //创建一个新的Node节点,其previous为n,next为null + final Node newNode = new Node(n,e,null); + //创建一个新的节点后,则last更新为新节点newNode + last = newNode; + //如果n为null,说明还是一个空的双向链表,将新节点newNode赋值给first + //否则,将newNode赋值给n的next + if(n == null){ + first = newNode; + }else{ + n.next = newNode; + } + //添加一个新节点后,size加1 + size++; + } + + /** + * 从链表解除一个节点 + * @param node 将要被链表接触关联的目标节点 + * @return 目标节点的element元素 + */ + private E unlink(Node node){ + //拿到传入节点的元素 + final E element = node.element; + //拿到传入节点的next节点 + final Node next = node.next; + //拿到传入节点的previous节点 + final Node previous = node.previous; + //如果传入节点的previous=null,说明是第一个节点 + if(previous == null){ + //将链表第一个节点指向本节点的下一个节点next,即把原有的第一个节点解除 + first = next; + }else{ + //将本节点前一个节点的next指向本节点后一个节点,即跳过了本节点 + previous.next = next; + //将本节点的previous节点设置为null + node.previous = null; + } + //如果传入节点的next=null,说明是最后一个节点 + if(next == null){ + //将链表最后一个节点指向本节点的前一个节点,即把原来的最后一个节点解除 + last = previous; + }else{ + //将本节点下一个节点的previous节点指向本节点的前一个节点,即跳过了本节点 + next.previous = previous; + //本节点的next节点设置为null + node.next = null; + } + node.element = null; + size--; + return element; + } + + /** + * 仅作为临时方法,打印链表元素使用,方面查看 + * @return + */ + @Override + public String toString() { + return Arrays.toString(toArray()); + } +} diff --git a/group15/1510_739253131/src/com/bruce/homework0226/QueueV00.java b/group15/1510_739253131/src/com/bruce/homework0226/QueueV00.java new file mode 100644 index 0000000000..7e86244d66 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0226/QueueV00.java @@ -0,0 +1,117 @@ +package com.bruce.homework0226; + +import com.bruce.utils.MyException; + +import java.util.Arrays; + +/** + * 实现Queue的基本功能:peek,poll,add,length,isEmpty + * Created by Bruce.Jiao on 2017/2/25. + */ +public class QueueV00 { + /** + * 队列元素的数组 + */ + private Object[] elementData; + + /** + * 队列容量 + */ + private int max_size; + + /** + * 队列头,允许删除 + */ + private int head; + + /** + * 队列尾,允许插入 + */ + private int tail; + + /** + * 无参构造,默认的初始长度10 + */ + public QueueV00() throws MyException{ + this(10); + } + + /** + * 有参构造 + * @param initCapacity 用户自定的初始长度 + */ + public QueueV00(int initCapacity) throws MyException{ + if(initCapacity < 0){ + throw new MyException("队列长度不能为负数"); + } + this.max_size = initCapacity; + elementData = new Object[initCapacity]; + head = tail = 0; + } + + /** + * 向队列里添加元素 + * @param value 添加的元素 + * @return true:添加成功;false:添加失败 + * @throws MyException 加入添加完成后元素个数超过队列最大尺寸,抛出异常 + */ + public boolean add(Object value) throws MyException{ + if(tail == max_size){ + throw new MyException("队列已满,不能继续插入"); + } + elementData[tail++] = value; + return true; + } + + /** + * 返回队列的第一个元素,但不从队列中删除该元素 + * @return 队列的第一个元素,以插入顺序为先后标准 + */ + public Object peek() throws MyException{ + if(isEmpty()){ + throw new MyException("队列为空队列"); + } + return elementData[head]; + } + + /** + * 返回队列的第一个元素,并且从队列中将该元素删除 + * @return 队列的第一个元素 + * @throws MyException 队列为空,抛出异常 + */ + public Object poll() throws MyException{ + if(isEmpty()){ + throw new MyException("队列为空队列"); + } + //将队列的第一个元素暂存 + Object result = elementData[head]; + //将队列的第一个元素设置为null,并且将head加1 + elementData[head++] = null; + return result; + } + + /** + * 队列长度 + * @return 队列中元素个数 + */ + public int length(){ + return tail-head; + } + + /** + * 判断队列是否为空 + * @return true:队列为空;false:队列不为空 + */ + public boolean isEmpty(){ + return tail == head; + } + + /** + * 临时方法,仅作为测试阶段打印队列元素使用 + * @return + */ + @Override + public String toString() { + return Arrays.toString(Arrays.copyOf(elementData,length())); + } +} diff --git a/group15/1510_739253131/src/com/bruce/homework0226/StackV00.java b/group15/1510_739253131/src/com/bruce/homework0226/StackV00.java new file mode 100644 index 0000000000..29cfe7e9fd --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0226/StackV00.java @@ -0,0 +1,144 @@ +package com.bruce.homework0226; + +import com.bruce.utils.MyException; + +import java.io.Serializable; +import java.util.Arrays; + +/** + * 用数组实现一个栈的基本功能:push,pop,isEmpty,size,clear方法 + * @Version: 0.0 + * Created by Bruce.Jiao on 17-2-24. + */ +public class StackV00 implements Serializable{ + + /** + * 底层存放栈元素的数组 + */ + private Object[] elementData; + + /** + * 栈中元素的个数 + */ + private int size; + + /** + * 每次扩容增加的大小 + */ + private int capacityIncrement; + + /** + * 空构造,数组初始长度为10 + */ + public StackV00() throws MyException{ + this(10); + } + + /** + * 有参构造 + * @param initCapacity 用户指定的栈空间初始大小(底层数组的初始大小) + * @throws MyException 对传入参数进行判断,不符合要求抛出异常 + */ + public StackV00(int initCapacity) throws MyException{ + this(initCapacity,0); + } + + /** + * 有参构造 + * @param initCapacity 用户指定的栈空间初始大小(底层数组的初始大小) + * @param capacityIncrement 用户指定的每次扩容大小(当空间不足时,每一次扩容增加的大小) + * @throws MyException 对传入参数进行判断,不符合要求抛出异常 + */ + public StackV00(int initCapacity, int capacityIncrement) throws MyException{ + if(initCapacity < 0 || capacityIncrement <0){ + throw new MyException(initCapacity < 0?"栈空间大小不能为负数":"扩容参数不能为负数"); + } + elementData = new Object[initCapacity]; + } + + /** + * 向栈中添加元素 + * @param value 添加的元素,可以为null + * @return 添加成功后的元素 + */ + public Object push(Object value){ + ensureCapacity(size+1); + //将新增的元素放在size索引处,并且将size加1 + elementData[size++] = value; + return value; + } + + /** + * 从栈中获取元素,拿到当前所有元素中最后添加进来的元素 + * @return 最后的元素 + */ + public Object pop(){ + //拿到最后的元素,在栈中将该元素删除,将size减1 + return elementData[--size]; + } + + /** + * 判断栈是否为空 + * @return true:空栈,无元素;false:有元素 + */ + public boolean isEmpty(){ + return size == 0; + } + + /** + * 获取栈大小(元素数量,包括null元素) + * @return 栈中元素大小 + */ + public int size(){ + return size; + } + + /** + * 清空栈中元素 + */ + public void clear(){ + int oldCapacity = elementData.length; + size = 0; + elementData = new Object[oldCapacity]; + } + + /** + * 判断数组尺寸 + * @param minCapacity + */ + public void ensureCapacity(int minCapacity){ + int oldCapacity = elementData.length; + //如果传入值大于当前数组尺寸,对数组进行扩容 + if(minCapacity > oldCapacity){ + //如果capacityIncrement大于0,每次扩容用户指定的大小,否则每次将当前数组尺寸扩大一倍 + int newCapacity = oldCapacity + capacityIncrement > 0 ? capacityIncrement : oldCapacity; + //元素数组扩容,并且将原有的元素复制到新数组中 + elementData = Arrays.copyOf(elementData,newCapacity); + } + } + + /** + * 拿到底层的静态数组 + * @return 底层元素数组 + */ + public Object[] toArray(){ + return Arrays.copyOf(elementData,size); + } + + /** + * toString方法,可以直接打印出栈底层的数组 + * @return + */ + @Override + public String toString() { + return Arrays.toString(toArray()); + } + + /** + * 仅仅作为自己查看底层数组长度的方法, + * @return 数组长度,大于等于元素个数 + */ + int arrayLength() { + return elementData.length; + } +} diff --git a/group15/1510_739253131/src/com/bruce/utils/MyException.java b/group15/1510_739253131/src/com/bruce/utils/MyException.java new file mode 100644 index 0000000000..2e2fa7833e --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/utils/MyException.java @@ -0,0 +1,29 @@ +package com.bruce.utils; + +/** + * Created by Bruce.Jiao on 15-6-23. + */ +public class MyException extends Exception{ + private int code; + private String message; + + public MyException() { + } + + public MyException(String message) { + this.message = message; + } + + public MyException(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public String getMessage() { + return message; + } +}