diff --git a/group02/527705641/src/com/github/fei9009/coderising0305/download/DownloadThread.java b/group02/527705641/src/com/github/fei9009/coderising0305/download/DownloadThread.java new file mode 100644 index 0000000000..11f7837324 --- /dev/null +++ b/group02/527705641/src/com/github/fei9009/coderising0305/download/DownloadThread.java @@ -0,0 +1,37 @@ +package com.github.fei9009.coderising0305.download; + +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import com.github.fei9009.coderising0305.download.api.Connection; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + CyclicBarrier barrier; + String localFile; + + public DownloadThread( Connection conn, int startPos, int endPos, String localFile, CyclicBarrier barrier){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.localFile = localFile; + this.barrier = barrier; + } + public void run(){ + try{ + byte[] buffer = conn.read(startPos, endPos); + RandomAccessFile file = new RandomAccessFile(localFile,"rw"); + file.seek(startPos); + file.write(buffer); + file.close(); + conn.close(); + barrier.await(); + }catch(Exception e){ + e.printStackTrace(); + } + } +} diff --git a/group02/527705641/src/com/github/fei9009/coderising0305/download/FileDownloader.java b/group02/527705641/src/com/github/fei9009/coderising0305/download/FileDownloader.java new file mode 100644 index 0000000000..fbdc122a7a --- /dev/null +++ b/group02/527705641/src/com/github/fei9009/coderising0305/download/FileDownloader.java @@ -0,0 +1,112 @@ +package com.github.fei9009.coderising0305.download; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import com.github.fei9009.coderising0305.download.api.Connection; +import com.github.fei9009.coderising0305.download.api.ConnectionException; +import com.github.fei9009.coderising0305.download.api.ConnectionManager; +import com.github.fei9009.coderising0305.download.api.DownloadListener; + +public class FileDownloader { + + private String url; + private String localFile; + DownloadListener listener; + ConnectionManager cm; + + //At most 3 threads + private static final int DOWNLOAD_TRHEAD_NUM = 3; + + public FileDownloader(String _url, String localFile) { + this.url = _url; + this.localFile = localFile; + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_TRHEAD_NUM , new Runnable(){ + public void run(){ + listener.notifyFinished(); + } + }); + Connection conn = null; + + try { + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + createPlaceHolderFile(this.localFile, length); + + int[][] ranges = allocateDownloadRange(DOWNLOAD_TRHEAD_NUM, length); + + for(int i=0; i< DOWNLOAD_TRHEAD_NUM; i++){ + DownloadThread thread = new DownloadThread(cm.open(url), ranges[i][0], ranges[i][1], localFile, barrier); + thread.start(); + } + + } catch (Exception e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + } + + private void createPlaceHolderFile(String fileName, int contentLen) throws IOException{ + + RandomAccessFile file = new RandomAccessFile(fileName,"rw"); + for(int i=0; i totalLen){ + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, totalLen); + } + return baos.toByteArray(); + } + + @Override + public int getContentLength() { + + URLConnection con; + try { + con = url.openConnection(); + return con.getContentLength(); + + } catch (IOException e) { + e.printStackTrace(); + } + return -1; + } + + @Override + public void close() { + + + } + +} diff --git a/group02/527705641/src/com/github/fei9009/coderising0305/download/impl/ConnectionManagerImpl.java b/group02/527705641/src/com/github/fei9009/coderising0305/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..8ef431ce0c --- /dev/null +++ b/group02/527705641/src/com/github/fei9009/coderising0305/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,15 @@ +package com.github.fei9009.coderising0305.download.impl; + +import com.github.fei9009.coderising0305.download.api.Connection; +import com.github.fei9009.coderising0305.download.api.ConnectionException; +import com.github.fei9009.coderising0305.download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + + return new ConnectionImpl(url); + } + +} diff --git a/group02/527705641/src/com/github/fei9009/coding2017/basic/LinkedList.java b/group02/527705641/src/com/github/fei9009/coding2017/basic/LinkedList.java index 1ed5923ee9..c1e8691a66 100644 --- a/group02/527705641/src/com/github/fei9009/coding2017/basic/LinkedList.java +++ b/group02/527705641/src/com/github/fei9009/coding2017/basic/LinkedList.java @@ -88,4 +88,135 @@ private static class Node{ } } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + int length = size/ 2; + for (int i = 0; i < length; i++) { + head = head.next; + } + size = size - length; + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + if (i == 0) { + while (i < length) { + if (head == null) { + size = 0; + break; + } + head = head.next; + i++; + } + } + } + /** + * 假定当前链表和list均包含已升序排列的整数 + * 从当前链表中取出那些list所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + int[] result = new int[list.size]; + for (int i = 0; i < result.length; i++) { + result[i] = (int)get((int)list.get(i)); + } + return result; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在list中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + while (head.next != null && head.data == head.next.data) { + head = head.next; + size--; + } + Node dummy = head; + while (dummy.next != null) { + if (dummy.data == dummy.next.data) { + dummy.next = dummy.next.next; + size --; + } else { + dummy = dummy.next; + } + } + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + if ((int)head.data > max) { + return ; + } + if ((int)get(size-1) < min) { + return; + } + while ((int)head.data > min && (int) head.data < max) { + head = head.next; + size--; + if (head == null) { + break; + } + } + Node dummy = head; + if (dummy == null) { + return; + } + while (dummy.next != null) { + if ((int)dummy.next.data > min && (int) dummy.next.data < max) { + dummy.next = dummy.next.next; + size --; + }else { + dummy = dummy.next; + } + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } } diff --git a/group02/527705641/src/com/github/fei9009/coding2017/basic/LinkedListTest.java b/group02/527705641/src/com/github/fei9009/coding2017/basic/LinkedListTest.java index 1eb379a020..4f42f62e0a 100644 --- a/group02/527705641/src/com/github/fei9009/coding2017/basic/LinkedListTest.java +++ b/group02/527705641/src/com/github/fei9009/coding2017/basic/LinkedListTest.java @@ -1,16 +1,16 @@ package com.github.fei9009.coding2017.basic; import static org.junit.Assert.*; - import org.junit.Before; import org.junit.Test; -public class LinkedListTest { +public class LinkedListTest extends ListTest { + + private LinkedList aLinkedList; -private LinkedList aLinkedList; - @Before public void setUpLinkedList() { + aList = new LinkedList(); aLinkedList = new LinkedList(); } @@ -18,75 +18,331 @@ public void setUpLinkedList() { public void testAddFirst() { aLinkedList.addFirst(5); assertEquals(5, aLinkedList.get(0)); - + aLinkedList.addFirst(6); assertEquals(6, aLinkedList.get(0)); assertEquals(5, aLinkedList.get(1)); assertEquals(2, aLinkedList.size()); } - + @Test public void testAddLast() { aLinkedList.addLast("hello"); assertEquals("hello", aLinkedList.get(0)); - + aLinkedList.addLast("world"); assertEquals("hello", aLinkedList.get(0)); assertEquals("world", aLinkedList.get(1)); assertEquals(2, aLinkedList.size()); } - + @Test public void testRemoveFirst() { aLinkedList.addLast("hello"); aLinkedList.addLast("world"); - + aLinkedList.removeFirst(); assertEquals("world", aLinkedList.get(0)); assertEquals(1, aLinkedList.size()); - + aLinkedList.removeFirst(); assertEquals(0, aLinkedList.size()); } - + @Test public void testRemoveLast() { aLinkedList.addFirst("world"); aLinkedList.addFirst("hello"); - + aLinkedList.removeLast(); assertEquals("hello", aLinkedList.get(0)); assertEquals(1, aLinkedList.size()); - + aLinkedList.removeLast(); assertEquals(0, aLinkedList.size()); } - + @Test public void testLinkedListFunctional() { - for (int i=1; i<4; i++) { - aLinkedList.add(i); // [1,2,3] + for (int i = 1; i < 4; i++) { + aLinkedList.add(i); // [1,2,3] } - aLinkedList.remove(1); // [1,3] - - aLinkedList.add(1, 0); // [1,0,3] - for (int i=4; i<6; i++) { - aLinkedList.addFirst(i); // [5, 4, 1, 0, 3] + aLinkedList.remove(1); // [1,3] + + aLinkedList.add(1, 0); // [1,0,3] + for (int i = 4; i < 6; i++) { + aLinkedList.addFirst(i); // [5, 4, 1, 0, 3] } assertEquals(5, aLinkedList.size()); assertEquals(5, aLinkedList.get(0)); assertEquals(1, aLinkedList.get(2)); assertEquals(0, aLinkedList.get(3)); - - aLinkedList.remove(3); // [5, 4, 1, 3] - assertEquals(3, aLinkedList.get(aLinkedList.size()-1)); - aLinkedList.removeLast(); // [5, 4, 1] - assertEquals(1, aLinkedList.get(aLinkedList.size()-1)); - aLinkedList.removeFirst(); // [4,1] - + + aLinkedList.remove(3); // [5, 4, 1, 3] + assertEquals(3, aLinkedList.get(aLinkedList.size() - 1)); + aLinkedList.removeLast(); // [5, 4, 1] + assertEquals(1, aLinkedList.get(aLinkedList.size() - 1)); + aLinkedList.removeFirst(); // [4,1] + assertEquals(4, aLinkedList.get(0)); assertEquals(1, aLinkedList.get(1)); assertEquals(2, aLinkedList.size()); } + @Test + public void testReverse() { + // 测试当aLinkedList为空时的情况 + aLinkedList.reverse(); + assertEquals(0, aLinkedList.size()); + + // 测试当aLinkedList长度为1时的情况 + aLinkedList.add(4); + aLinkedList.reverse(); + assertEquals(1, aLinkedList.size()); + assertEquals(4, aLinkedList.get(0)); + + for (int i = 1; i < 4; i++) { + aLinkedList.add(i); // [4,1,2,3] + } + aLinkedList.reverse(); + assertEquals(4, aLinkedList.size()); + assertEquals(3, aLinkedList.get(0)); + assertEquals(2, aLinkedList.get(1)); + assertEquals(1, aLinkedList.get(2)); + assertEquals(4, aLinkedList.get(3)); + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10, 删除以后的值为7,8,10 + */ + @Test + public void testRemoveFirstHalf() { + aLinkedList.removeFirstHalf(); + assertEquals(0, aLinkedList.size()); + + aLinkedList.add(2); + aLinkedList.add(5); + aLinkedList.add(7); + aLinkedList.add(8); // [2,5,7,8] + + aLinkedList.removeFirstHalf(); // [7,8] + assertEquals(2, aLinkedList.size()); + assertEquals(7, aLinkedList.get(0)); + assertEquals(8, aLinkedList.get(1)); + + aLinkedList.add(10); // [7,8,10] + + aLinkedList.removeFirstHalf(); // [8,10] + assertEquals(2, aLinkedList.size()); + assertEquals(8, aLinkedList.get(0)); + assertEquals(10, aLinkedList.get(1)); + + aLinkedList.removeFirstHalf(); // [10] + aLinkedList.removeFirstHalf(); // [10] + assertEquals(1, aLinkedList.size()); + assertEquals(10, aLinkedList.get(0)); + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + @Test + public void testRemoveIntInt() { + for (int i = 0; i < 4; i++) { + aLinkedList.add(i); // [0,1,2,3] + } + + expectedEx.expect(Exception.class); + aLinkedList.remove(1, -1); + + expectedEx.expect(Exception.class); + aLinkedList.remove(-1, 1); + + aLinkedList.remove(0, 2); // [2,3] + assertEquals(2, aLinkedList.size()); + assertEquals(2, aLinkedList.get(0)); + assertEquals(3, aLinkedList.get(1)); + + aLinkedList.remove(1, 0); + aLinkedList.remove(0, 0); + assertEquals(2, aLinkedList.size()); + + aLinkedList.remove(1, 1); // [2] + assertEquals(1, aLinkedList.size()); + assertEquals(2, aLinkedList.get(0)); + + aLinkedList.remove(0, 1); // [] + assertEquals(0, aLinkedList.size()); + + expectedEx.expect(Exception.class); + aLinkedList.remove(1, 3); + } + + /** + * 假定当前链表和list均包含已升序排列的整数 从当前链表中取出那些list所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * + * @param list + */ + @Test + public void testGetElements() { + for (int i = 0; i < 4; i++) { + aLinkedList.add(i * i); // [0,1,4,9] + } + + LinkedList bLinkedList = new LinkedList(); + int[] z1 = aLinkedList.getElements(bLinkedList); // [] + assertArrayEquals(new int[0], z1); + + bLinkedList.add(1); + bLinkedList.add(3); // [1, 3] + + z1 = aLinkedList.getElements(bLinkedList); // [1, 9] + assertArrayEquals(new int[] { 1, 9 }, z1); + + bLinkedList.add(1, 2); // bLinkedList = [1, 2, 3] + z1 = aLinkedList.getElements(bLinkedList); // [1, 4, 9] + assertArrayEquals(new int[] { 1, 4, 9 }, z1); + + bLinkedList.add(0, 0); // bLinkedList = [0, 1, 2, 3] + z1 = aLinkedList.getElements(bLinkedList); // [0, 1, 4, 9] + assertArrayEquals(new int[] { 0, 1, 4, 9 }, z1); + + // aLinkedList不应该变化 + assertEquals(4, aLinkedList.size()); + for (int i = 0; i < 4; i++) { + assertEquals(i * i, aLinkedList.get(i)); // [0,1,4,9] + } + + // Exception + bLinkedList.add(5); // bLinkedList = [0, 1, 2, 3, 5] + expectedEx.expect(Exception.class); + z1 = aLinkedList.getElements(bLinkedList); + } + + @Test + public void TestSubtract() { + // 传进的list为null,什么都不干 + LinkedList list = null; + for (int i = 0; i < 6; i++) { + aLinkedList.add(i); // [0,1,2,3,4,5] + } + aLinkedList.subtract(list); + assertEquals(6, aLinkedList.size()); + for (int i = 0; i < 6; i++) { + assertEquals(i, aLinkedList.get(i)); // [0,1,2,3,4,5] + } + + // 传进的list为空链表 + list = new LinkedList(); + aLinkedList.subtract(list); + assertEquals(6, aLinkedList.size()); + for (int i = 0; i < 6; i++) { + assertEquals(i, aLinkedList.get(i)); // [0,1,2,3,4,5] + } + + aLinkedList.add(1, 1); // [0,1,1,2,3,4,5] + aLinkedList.add(4, 3); // [0, 1, 1, 2, 3, 3, 4, 5] + + // list添加元素[0, 1, 3, 7] + list.add(0); + list.add(1); + list.add(3); + list.add(7); + + aLinkedList.subtract(list); // [2, 4, 5] + + assertEquals(3, aLinkedList.size()); + assertEquals(2, aLinkedList.get(0)); + assertEquals(4, aLinkedList.get(1)); + assertEquals(5, aLinkedList.get(2)); + } + + @Test + public void testRemoveDuplicateValues() { + aLinkedList.add(3); + aLinkedList.add(3); + aLinkedList.add(3); + aLinkedList.add(4); + aLinkedList.add(5); + aLinkedList.add(6); + aLinkedList.add(6); // [3, 3, 3, 4, 5, 6, 6] + + aLinkedList.removeDuplicateValues(); // [3, 4, 5, 6] + + assertEquals(4, aLinkedList.size()); + assertEquals(3, aLinkedList.get(0)); + assertEquals(4, aLinkedList.get(1)); + assertEquals(5, aLinkedList.get(2)); + assertEquals(6, aLinkedList.get(3)); + } + + @Test + public void testRemoveRange() { + for (int i = 0; i < 6; i++) { + aLinkedList.add(i); // [0, 1, 2, 3, 4, 5] //考虑重复元素 + } + aLinkedList.addFirst(0); // [0, 0, 1, 2, 3, 4, 5] + aLinkedList.add(3, 2); // [0, 0, 1, 2, 2, 3, 4, 5] + + aLinkedList.removeRange(1, 4); // 大于1小于4 [0, 0, 1, 4, 5] + + assertEquals(5, aLinkedList.size()); + assertEquals(0, aLinkedList.get(0)); + assertEquals(0, aLinkedList.get(1)); + assertEquals(1, aLinkedList.get(2)); + assertEquals(4, aLinkedList.get(3)); + assertEquals(5, aLinkedList.get(4)); + + // 若出现 min >= max的情况,什么都不做 + aLinkedList.removeRange(4, 1); + assertEquals(5, aLinkedList.size()); + assertEquals(0, aLinkedList.get(0)); + assertEquals(0, aLinkedList.get(1)); + assertEquals(1, aLinkedList.get(2)); + assertEquals(4, aLinkedList.get(3)); + assertEquals(5, aLinkedList.get(4)); + + // 将整个链表中的元素删除 + aLinkedList.removeRange(-1, 9); + assertEquals(0, aLinkedList.size()); + } + + @Test + public void testIntersection() { + for (int i = 0; i < 6; i++) { + aLinkedList.add(i); + } + aLinkedList.add(6); + aLinkedList.add(7); // [0, 1, 2, 3, 4, 5, 6, 7] + // list为null + LinkedList list = null; + LinkedList newList1 = aLinkedList.intersection(list); + assertNull(newList1); + + // list为空链表 + list = new LinkedList(); + LinkedList newList2 = aLinkedList.intersection(list); + assertEquals(0, newList2.size()); + + list.add(0); + list.add(3); + list.add(4); + list.add(7); + list.add(8); // [0, 3, 4, 7, 8] + LinkedList newList3 = aLinkedList.intersection(list); + + assertEquals(4, newList3.size()); + assertEquals(0, newList3.get(0)); + assertEquals(3, newList3.get(1)); + assertEquals(4, newList3.get(2)); + assertEquals(7, newList3.get(3)); + } } diff --git a/group02/527705641/src/com/github/fei9009/coding2017/basic/ListTest.java b/group02/527705641/src/com/github/fei9009/coding2017/basic/ListTest.java new file mode 100644 index 0000000000..acd43051f3 --- /dev/null +++ b/group02/527705641/src/com/github/fei9009/coding2017/basic/ListTest.java @@ -0,0 +1,93 @@ +package com.github.fei9009.coding2017.basic; + +import static org.junit.Assert.assertEquals; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + + +public class ListTest { + + protected static List aList; + + @Test + public void testFunctional() { + aList.add(1); + aList.add(2); + assertEquals(1, aList.get(0)); + assertEquals(2, aList.get(1)); + + aList.add(3); + aList.add(0, 5); + aList.add(2, 11); + assertEquals(5, aList.get(0)); + assertEquals(11, aList.get(2)); + + aList.add("hi"); + assertEquals("hi", aList.get(5)); + assertEquals(6, aList.size()); + + aList.remove(1); + assertEquals(11, aList.get(1)); + assertEquals(2, aList.get(2)); + + assertEquals(5, aList.size()); + } + + @Test + public void testAdd() { + for (int i = 0; i < 1000; i++) + aList.add(i); + assertEquals(0, aList.get(0)); + assertEquals(100, aList.get(100)); + assertEquals(999, aList.get(999)); + } + + @Test + public void testRemove() { + aList.add(1); + aList.add(2); + aList.add(3); + int u = (Integer)aList.remove(2); + assertEquals(3, u); + assertEquals(2, aList.size()); + + aList.add(1, 5); + u = (Integer)aList.remove(0); + assertEquals(1, u); + assertEquals(5, aList.get(0)); + assertEquals(2, aList.get(1)); + assertEquals(2, aList.size()); + + aList.remove(0); + aList.remove(0); + assertEquals(0, aList.size()); + + + } + + @Test + public void testSize() { + for (int i = 0; i < 10; i++) + aList.add(i * 2); + assertEquals(10, aList.size()); + } + + @Rule + public ExpectedException expectedEx = ExpectedException.none(); + + @Test + public void testException() { + expectedEx.expect(Exception.class); + aList.remove(1); + + aList.add(3); + + expectedEx.expect(Exception.class); + aList.add(2, 5); + } + + + +}