diff --git a/group01/765324639/src/zavier/week01/basic/LinkedList.java b/group01/765324639/src/zavier/week01/basic/LinkedList.java index c876b48f1b..5f2a191739 100644 --- a/group01/765324639/src/zavier/week01/basic/LinkedList.java +++ b/group01/765324639/src/zavier/week01/basic/LinkedList.java @@ -145,4 +145,230 @@ private static class Node { next = null; } } + + // =========================第三周作业========================= + + /** + * 把该链表逆置 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + Node reverseNode = null; + while (head != null) { + Node temp = head; + head = head.next; + temp.next = reverseNode; + reverseNode = temp; + } + head = reverseNode; + } + + /** + * 删除一个单链表的前半部分 例如:list = 2->5->7->8 , 删除以后的值为 7->8 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + int newStartIndex = size / 2; + for (int i = 0; i < newStartIndex; i++) { + head = head.next; + } + size = size - newStartIndex; + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + if (i < 0) { + throw new IllegalArgumentException(); + } + if (i + length >= size) { + length = size - i; + } + + if (i == 0) { + for (int j = 0; j < length; j++) { + head = head.next; + } + } else { + Node beforeRemoveStartNode = head; + for (int j = 0; j < i - 1; j++) { + beforeRemoveStartNode = beforeRemoveStartNode.next; + } + + Node removeEndNode = beforeRemoveStartNode; + for (int j = 0; j < length; j++) { + removeEndNode = removeEndNode.next; + } + + beforeRemoveStartNode.next = removeEndNode.next; + } + + size = size - length; + } + + /** + * 假定当前链表和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) { + checkList(list); + + int[] dest = new int[list.size]; + int arrayNum = 0; + Node temp = head; + int n = (int) list.get(0); + for (int i = 0; i < n; i++) { + temp = temp.next; + } + dest[arrayNum++] = (int) temp.data; + + for (int i = 1; i < list.size; i++) { + int num = (int) list.get(i) - (int) list.get(i - 1); + for (int j = 0; j < num; j++) { + temp = temp.next; + } + dest[arrayNum++] = (int) temp.data; + } + return dest; + } + + private void checkList(LinkedList list) { + for (int i = 0; i < list.size; i++) { + if ((int) list.get(i) < 0 || (int) list.get(i) >= size) { + throw new IllegalArgumentException("list中的元素位置越界"); + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 从当前链表中中删除在list中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + if (list == null || list.size == 0 || this.size == 0) { + return; + } + + int thisIndex = 0; + int listIndex = 0; + Node temp = head; + while (true) { // 后续需要优化替换remove()方法 + if ((int) temp.data < (int) list.get(listIndex)) { + temp = temp.next; + thisIndex++; + } else if ((int) temp.data == (int) list.get(listIndex)) { + this.remove(thisIndex); + temp = temp.next; + thisIndex++; + listIndex++; + } else { + listIndex++; + } + + if (thisIndex >= this.size || listIndex >= list.size) { + break; + } + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + if (this.size == 0) { + return; + } + + Node subHead = head; + Node subTail = head; + + while (true) { + if (subTail == null) { + break; + } + if ((int) subTail.data == (int) subHead.data) { + if (!(subTail == subHead)) { // 判断两个指针是否指向同一个地方 + this.size--; + } + subTail = subTail.next; + } else { + subHead.next = subTail; + subHead = subHead.next; + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + if (this.size == 0) { + return; + } + + if ((int) head.data > max) { + throw new IllegalArgumentException(); + } + + int length = 0; + Node subList = new Node(null); + Node temp = subList; + while (true) { + if (head == null) { + break; + } + if ((int) head.data <= min || (int) head.data >= max) { + temp.next = head; + temp = temp.next; + length++; + } + head = head.next; + } + temp.next = null; // 去掉尾部多余数据 + head = subList.next; + size = length; + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + if (this.size == 0 || list.size == 0) { + return null; + } + + Node tempHead = head; + int listIndex = 0; + + LinkedList newList = new LinkedList(); + while (true) { + if (tempHead == null || listIndex >= list.size) { + break; + } + + if ((int) tempHead.data < (int) list.get(listIndex)) { + tempHead = tempHead.next; + } else if ((int) tempHead.data > (int) list.get(listIndex)) { + listIndex++; + } else { + newList.add(tempHead.data); + + tempHead = tempHead.next; + listIndex++; + } + } + + return newList; + } } diff --git a/group01/765324639/src/zavier/week01/test/LinkedListTest.java b/group01/765324639/src/zavier/week01/test/LinkedListTest.java index de7436a350..ea1f077704 100644 --- a/group01/765324639/src/zavier/week01/test/LinkedListTest.java +++ b/group01/765324639/src/zavier/week01/test/LinkedListTest.java @@ -106,4 +106,154 @@ public void testRemoveLast() { Assert.assertEquals(498, linkedList.size()); } + // =========================第三周作业========================= + + @Test + public void testReverse() { + linkedList.reverse(); + for (int i = 0; i < linkedList.size(); i++) { + Assert.assertEquals(499 - i, linkedList.get(i)); + } + Assert.assertEquals(500, linkedList.size()); + } + + @Test + public void testRemoveFirstHalfOfEven() { + linkedList.removeFirstHalf(); + for (int i = 250; i < 500; i++) { + Assert.assertEquals(i, linkedList.get(i - 250)); + } + Assert.assertEquals(250, linkedList.size()); + } + + @Test + public void testRemoveFirstHalfOfOdd() { + linkedList.add(500); + linkedList.removeFirstHalf(); + for (int i = 250; i < 501; i++) { + Assert.assertEquals(i, linkedList.get(i - 250)); + } + Assert.assertEquals(251, linkedList.size()); + } + + @Test + public void testRemoveIntInt() { + linkedList.remove(10, 10); + Assert.assertEquals(0, linkedList.get(0)); + Assert.assertEquals(20, linkedList.get(10)); + Assert.assertEquals(490, linkedList.size()); + } + + @Test(expected = IllegalArgumentException.class) + public void testIllegalIRemoveIntInt() { + linkedList.remove(-10, 10); + } + + @Test + public void testIllegalLengthRemoveIntInt() { + linkedList.remove(0, 10); + Assert.assertEquals(490, linkedList.size()); + Assert.assertEquals(10, linkedList.get(0)); + + linkedList.remove(300, 500); + Assert.assertEquals(300, linkedList.size()); + for (int i = 0; i < 300; i++) { + Assert.assertEquals(i + 10, linkedList.get(i)); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testGetElements() { + LinkedList list = new LinkedList(); + list.add(5); + list.add(10); + list.add(202); + list.add(305); + Assert.assertArrayEquals(new int[] {5, 10, 202, 305}, linkedList.getElements(list)); + + Assert.assertEquals(500, linkedList.size()); + + list.add(500); + linkedList.getElements(list); + } + + @Test + public void testSubtract() { + LinkedList list1 = new LinkedList(); + list1.add(1); + list1.add(5); + list1.add(8); + list1.add(10); + LinkedList list2 = new LinkedList(); + list2.add(2); + list2.add(5); + list2.add(7); + list2.add(11); + list1.subtract(list2); + + Assert.assertEquals(1, list1.get(0)); + Assert.assertEquals(8, list1.get(1)); + Assert.assertEquals(10, list1.get(2)); + Assert.assertEquals(3, list1.size()); + } + + @Test + public void testRemoveDuplicateValues() { + LinkedList list = new LinkedList(); + list.add(1); + list.add(2); + list.add(2); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + list.add(6); + list.add(6); + list.add(7); + list.add(7); + list.add(7); + + list.removeDuplicateValues(); + for (int i = 0; i < 7; i++) { + Assert.assertEquals(i + 1, list.get(i)); + } + Assert.assertEquals(7, list.size()); + } + + @Test + public void testRemoveRange() { + linkedList.removeRange(100, 300); + Assert.assertEquals(301, linkedList.size()); + for (int i = 0; i < 100; i++) { + Assert.assertEquals(i, linkedList.get(i)); + } + for (int i = 300; i < 500; i++) { + Assert.assertEquals(i, linkedList.get(i - 199)); + } + } + + @Test + public void testIntersection() { + LinkedList list1 = new LinkedList(); + list1.add(1); + list1.add(2); + list1.add(5); + list1.add(7); + list1.add(9); + + LinkedList list2 = new LinkedList(); + list2.add(0); + list2.add(2); + list2.add(9); + list2.add(10); + list2.add(19); + + LinkedList intersection = list1.intersection(list2); + Assert.assertNotNull(intersection); + Assert.assertEquals(2, intersection.size()); + Assert.assertEquals(2, (int) intersection.get(0)); + Assert.assertEquals(9, (int) intersection.get(1)); + + + } } diff --git a/group01/765324639/src/zavier/week03/coderising/download/DownloadThread.java b/group01/765324639/src/zavier/week03/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..f94c97b8b1 --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/DownloadThread.java @@ -0,0 +1,44 @@ +package zavier.week03.coderising.download; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import zavier.week03.coderising.download.api.Connection; + +public class DownloadThread extends Thread { + + Connection conn; + int startPos; + int endPos; + + + public DownloadThread(Connection conn, int startPos, int endPos) { + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + + } + + @Override + public void run() { + byte[] data = new byte[endPos - startPos]; + try { + data = conn.read(startPos, endPos); + } catch (IOException e) { + e.printStackTrace(); + } + writeToFile(data); + } + + private void writeToFile(byte[] data) { + RandomAccessFile file; + try { + file = new RandomAccessFile("download20170311.jpg", "rw"); + file.seek(startPos); + file.write(data, 0, data.length); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/group01/765324639/src/zavier/week03/coderising/download/FileDownloader.java b/group01/765324639/src/zavier/week03/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..ff2db12f50 --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/FileDownloader.java @@ -0,0 +1,87 @@ +package zavier.week03.coderising.download; + +import zavier.week03.coderising.download.api.Connection; +import zavier.week03.coderising.download.api.ConnectionException; +import zavier.week03.coderising.download.api.ConnectionManager; +import zavier.week03.coderising.download.api.DownloadListener; + + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + 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方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + + DownloadThread downloadThread1 = new DownloadThread(conn, 0, length / 3); + downloadThread1.start(); + DownloadThread downloadThread2 = + new DownloadThread(conn, length / 3 + 1, length / 3 * 2); + downloadThread2.start(); + DownloadThread downloadThread3 = + new DownloadThread(conn, length / 3 * 2 + 1, length - 1); + downloadThread3.start(); + try { + downloadThread1.join(); + downloadThread2.join(); + downloadThread3.join(); + listener.notifyFinished(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } catch (ConnectionException e) { + e.printStackTrace(); + } finally { + if (conn != null) { + conn.close(); + } + } + + + + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + + + public void setConnectionManager(ConnectionManager ucm) { + this.cm = ucm; + } + + public DownloadListener getListener() { + return this.listener; + } + +} diff --git a/group01/765324639/src/zavier/week03/coderising/download/FileDownloaderTest.java b/group01/765324639/src/zavier/week03/coderising/download/FileDownloaderTest.java new file mode 100644 index 0000000000..bf67e8d494 --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/FileDownloaderTest.java @@ -0,0 +1,62 @@ +package zavier.week03.coderising.download; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import zavier.week03.coderising.download.api.ConnectionManager; +import zavier.week03.coderising.download.api.DownloadListener; +import zavier.week03.coderising.download.impl.ConnectionManagerImpl; + +public class FileDownloaderTest { + boolean downloadFinished = false; + + @Before + public void setUp() throws Exception {} + + @After + public void tearDown() throws Exception {} + + @Test + public void testDownload() { + + String url = "http://121.42.185.101/forum/test.jpg"; + + FileDownloader downloader = new FileDownloader(url); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + new Thread() { + @Override + public void run() { + downloader.execute(); + } + }.start(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + // 休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} diff --git a/group01/765324639/src/zavier/week03/coderising/download/api/Connection.java b/group01/765324639/src/zavier/week03/coderising/download/api/Connection.java new file mode 100644 index 0000000000..4763202fab --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/api/Connection.java @@ -0,0 +1,26 @@ +package zavier.week03.coderising.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos, int endPos) throws IOException; + + /** + * 得到数据内容的长度 + * + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionException.java b/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..5df32804de --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package zavier.week03.coderising.download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionManager.java b/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..81f5f34f72 --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionManager.java @@ -0,0 +1,11 @@ +package zavier.week03.coderising.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group01/765324639/src/zavier/week03/coderising/download/api/DownloadListener.java b/group01/765324639/src/zavier/week03/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..f72ecd263d --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package zavier.week03.coderising.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionImpl.java b/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..b297beef54 --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,64 @@ +package zavier.week03.coderising.download.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import zavier.week03.coderising.download.api.Connection; + +public class ConnectionImpl implements Connection { + + private URL url = null;; + + private HttpURLConnection conn = null; + + public ConnectionImpl(String url) { + try { + this.url = new URL(url); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + try { + conn = (HttpURLConnection) url.openConnection(); + } catch (IOException e) { + e.printStackTrace(); + } + conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + InputStream inputStream = conn.getInputStream(); + byte[] result = new byte[endPos - startPos + 1]; + byte[] data = new byte[1024]; + int read = -1; + int i = 0; + while ((read = inputStream.read(data, 0, data.length)) != -1) { + System.arraycopy(data, 0, result, i, read); + i += read; + } + return result; + } + + @Override + public int getContentLength() { + HttpURLConnection openConnection = null; + try { + openConnection = (HttpURLConnection) url.openConnection(); + } catch (IOException e) { + e.printStackTrace(); + } + int contentLength = openConnection.getContentLength(); + openConnection.disconnect(); + return contentLength; + } + + @Override + public void close() { + conn.disconnect(); + conn = null; + } + +} diff --git a/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionManagerImpl.java b/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..d6828e7ae8 --- /dev/null +++ b/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,14 @@ +package zavier.week03.coderising.download.impl; + +import zavier.week03.coderising.download.api.Connection; +import zavier.week03.coderising.download.api.ConnectionException; +import zavier.week03.coderising.download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + return new ConnectionImpl(url); + } + +}