diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/LinkedList.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/LinkedList.java index a91f03573a..01ba928128 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/LinkedList.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/LinkedList.java @@ -20,6 +20,7 @@ public LinkedList() { } + private static class Node { T element; Node next; @@ -75,6 +76,15 @@ public void addFirst(E element) { size++; } + /** + * Appends the specified element to the end of this list. + * + * @param element element to be appended to this list. + */ + public void addLast(E element) { + add(element); + } + /** * Inserts the specified element at the specified position in this list. @@ -115,20 +125,27 @@ public void add(int index, E element) { * * @throws RuntimeException if the list is empty. */ - public void remove() { + public E removeLast() { if (size == 0) throw new RuntimeException("linkList size should greater than or equal to 1"); + E element; Node next = first.next; if (next == null) { + element = first.element; + first = null; } else { Node last = first; while (last.next != null) last = last.next; last.prev.next = null; + + element = last.element; + last = null; // help GC } size--; + return element; } @@ -163,6 +180,7 @@ public E removeFirst() { return element; } + /** * Returns the element at the specified position in this list. * @@ -229,6 +247,232 @@ public String toString() { return sb.toString(); } + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + Node next; + Node current = first; + for (int i = 0; i < size; i++) { + next = current.next; + current.next = current.prev; + current.prev = next; + if (next != null) { + current = next; + } + } + first = current; + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + int index = size() / 2; + Node current = first; + Node prev; + for (int i = 0; i < index; i++) { + prev = current; + current = current.next; + delete(prev); + } + current.prev = null; + first = current; + size = size - index; + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + checkElementIndex(i); + if (length + i > size()) { + throw new IllegalArgumentException("Length + i should less than or equal " + size()); + } + Node head = first; + Node tail = first; + if (i == 0 && length == size()) { + first = null; + } else if (i == 0 && length < size()) { + for (int j = 0; j < length; j++) { + head = head.next; + } + head.prev = null; + first = head; + } else { + for (int j = 0; j < i; j++) { + head = head.next; + } + head = head.prev; + for (int j = 0; j < length + i; j++) { + tail = tail.next; + } + head.next = tail; + if (tail != null) { + tail.prev = head; + } + } + 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) { + int[] newArray = new int[list.size()]; + Node mapNode = list.first; + Node valueNode = this.first; + int indexOfList = 0; + int indexOfArray = 0; + while (mapNode != null && valueNode != null) { + int mapValue = (int) mapNode.element; + if (mapValue == indexOfList) { + newArray[indexOfArray] = (int) valueNode.element; + mapNode = mapNode.next; + valueNode = valueNode.next; + indexOfArray++; + } else { + mapNode = mapNode.next; + } + indexOfList++; + } + return newArray; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + Node pNode = first; + Node qNode = list.first; + Node prev = null; + Node deletedNode; + while (pNode != null && qNode != null) { + if ((int) qNode.element < (int) pNode.element) { + qNode = qNode.next; + } else if ((int) qNode.element > (int) pNode.element) { + prev = pNode; + pNode = pNode.next; + } else { + if (prev == null) { // 头结点 + first = pNode.next; + } else { + prev.next = pNode.next; + } + deletedNode = pNode; + pNode = pNode.next; + qNode = qNode.next; + delete(deletedNode); + size--; + } + } + + } + + private void delete(Node node) { + node.element = null; + node.prev = null; + node.next = null; + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + Node current = first; + Node next = current.next; + while (next != null) { + if (current.element == next.element) { + current.next = next.next; + if (next.next != null) { + next.next.prev = current; + } + delete(next); + next = current.next; + size--; + } else { + current = current.next; + next = next.next; + } + + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + Node current = first; + Node prev = null; + Node deletedNode; + while (current != null) { + if ((int) current.element >= max) { + break; + } + if ((int) current.element > min && (int) current.element < max) { + if (prev == null) { // 头结点 + first = current.next; + } else { + prev.next = current.next; + } + deletedNode = current; + current = current.next; + delete(deletedNode); // help gc + size--; + } else { + prev = current; + current = current.next; + } + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + LinkedList l = new LinkedList(); + Node pNode = first; + Node qNode = list.first; + while (pNode != null && qNode != null) { + if ((int) pNode.element < (int) qNode.element) { + pNode = pNode.next; + } else if ((int) pNode.element > (int) qNode.element) { + qNode = qNode.next; + } else { + l.add(pNode.element); + pNode = pNode.next; + qNode = qNode.next; + } + } + return l; + } + + /** * Constructs an IndexOutOfBoundsException detail message. * Of the many possible refactorings of the error handling code, diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/LinkedListTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/LinkedListTest.java index d09362cdf9..9a72c0d54a 100644 --- a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/LinkedListTest.java +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/LinkedListTest.java @@ -3,6 +3,9 @@ import org.junit.Before; import org.junit.Test; +import java.util.Arrays; + +import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; @@ -17,6 +20,18 @@ public class LinkedListTest { private LinkedList linkList4; private LinkedList linkList5; private LinkedList linkList6; + private LinkedList linkList7; + private LinkedList linkList8; + private LinkedList linkList9; + private LinkedList linkList10; + private LinkedList linkList11; + private LinkedList linkList12; + private LinkedList linkList13; + private LinkedList linkList14; + private LinkedList linkList15; + private LinkedList linkList16; + private LinkedList linkList17; + private LinkedList linkList18; @Before public void setUp() throws Exception { @@ -26,6 +41,18 @@ public void setUp() throws Exception { linkList4 = new LinkedList<>(); linkList5 = new LinkedList<>(); linkList6 = new LinkedList<>(); + linkList7 = new LinkedList<>(); + linkList8 = new LinkedList<>(); + linkList9 = new LinkedList<>(); + linkList10 = new LinkedList<>(); + linkList11 = new LinkedList<>(); + linkList12 = new LinkedList<>(); + linkList13 = new LinkedList<>(); + linkList14 = new LinkedList<>(); + linkList15 = new LinkedList<>(); + linkList16 = new LinkedList<>(); + linkList17 = new LinkedList<>(); + linkList18 = new LinkedList<>(); } @Test @@ -56,12 +83,12 @@ public void testAddFirst() { } @Test - public void testRemove() { + public void testRemoveLast() { for (int i = 0; i < 2; i++) { linkList4.addFirst(i); } - linkList4.remove(); - linkList4.remove(); + linkList4.removeLast(); + linkList4.removeLast(); assertThat(linkList4.size(), equalTo(0)); } @@ -88,4 +115,103 @@ public void testRemoveFirst() { assertThat(linkList6.get(0), equalTo(0)); } + @Test + public void testReverse() { + linkList7.add(3); + linkList7.add(7); + linkList7.add(10); + linkList7.reverse(); + assertThat(linkList7.toString(), containsString("10→7→3")); + } + + @Test + public void testRemoveFirstHalf() { + linkList8.add(2); + linkList8.add(5); + linkList8.add(7); + linkList8.add(8); + linkList8.add(10); + linkList8.removeFirstHalf(); + assertThat(linkList8.toString(), containsString("7→8→10")); + } + + @Test + public void testRemove() { + for (int i = 1; i < 6; i++) { + linkList9.add(i); + } + linkList9.remove(0, 4); + assertThat(linkList9.toString(), containsString("5")); + } + + @Test + public void testRemoveDuplicateValues() { + linkList11.add(1); + linkList11.add(1); + linkList11.add(1); + linkList11.add(2); + linkList11.add(3); + linkList11.add(3); + linkList11.removeDuplicateValues(); + assertThat(linkList11.toString(), containsString("1→2→3")); + } + + @Test + public void testRemoveRange() { + linkList10.add(1); + linkList10.add(1); + linkList10.add(2); + linkList10.add(3); + linkList10.add(4); + linkList10.add(5); + linkList10.add(6); + linkList10.removeRange(1, 4); + assertThat(linkList10.toString(), containsString("4→5→6")); + } + + @Test + public void testIntersection() { + for (int i = 1; i < 6; i++) { + linkList12.add(i); + } + for (int i = 3; i < 9; i++) { + linkList13.add(i); + } + assertThat(linkList12.intersection(linkList13).toString() + , containsString("3→4→5")); + } + + @Test + public void testGetElements() { + linkList15.add(1); + linkList15.add(3); + linkList15.add(4); + linkList15.add(6); + linkList14.add(11); + linkList14.add(101); + linkList14.add(201); + linkList14.add(301); + linkList14.add(401); + linkList14.add(501); + linkList14.add(601); + linkList14.add(701); + linkList14.getElements(linkList15); + assertThat(Arrays.toString(linkList14.getElements(linkList15)) + , containsString("[101, 301, 401, 601]")); + } + + @Test + public void testSubtract() { + for (int i = 1; i < 5; i++) { + linkList17.add(i); + } + for (int i = 1; i < 4; i++) { + linkList18.add(i); + } + linkList17.subtract(linkList18); + assertThat(linkList17.toString() + , containsString("4")); + + } + } \ No newline at end of file