package com.github.miniyk2012.coding2017.basic; import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.Objects; import org.omg.CORBA.PRIVATE_MEMBER; import com.sun.tracing.dtrace.ArgsAttributes; import utils.ArrayUtils; public class LinkedList implements List { private Node head; private int size = 0; /** * node接收的index一定是范围内的值,不可能越界 * @param index * @return a Node */ Node node(int index) { Node x = head; for (int i=0; i<index; i++) { x = x.next; } return x; } public void add(Object o){ add(size, o); } public void add(int index , Object o){ checkPositionIndex(index); Node after = node(index); Node newNode = new Node(o, after); if (index == 0) { head = newNode; } else { Node before = node(index-1); before.next = newNode; } size++; } public Object get(int index){ checkElementIndex(index); Node thisNode = node(index); return thisNode.data; } public Object remove(int index){ checkElementIndex(index); Node toRemove = node(index); if (index == 0) head = toRemove.next; else { Node before = node(index-1); before.next = toRemove.next; } size--; return toRemove.data; } public int size(){ return size; } public void addFirst(Object o){ add(0, o); } public void addLast(Object o){ add(o); } public Object removeFirst(){ return remove(0); } public Object removeLast(){ return remove(size-1); } public Iterator iterator(){ Iterator iterator = new IteratorImp(this); return iterator; } private static class Node{ Object data; Node next; Node(){} Node(Object data, Node next) { this.data = data; this.next = next; } } private void checkElementIndex(int index) { if (index < 0 || index >= size) throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size); } private void checkPositionIndex(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size); } /** * 把该链表逆置 * 例如链表为 3->7->10 , 逆置后变为 10->7->3 */ public void reverse(){ // 自感写的还行,没有多余代码 Node previous = null; while (head != null) { Node next = head.next; head.next = previous; previous = head; head = next; } head = previous; } /** * 删除一个单链表的前半部分 * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 */ public void removeFirstHalf(){ int halfIndex = size() / 2; head = node(halfIndex); size = size() - halfIndex; } /** * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 * @param i * @param length * @throws Exception */ public void remove(int i, int length) throws Exception{ if (length <0 || i <0 || i>=size()) throw new Exception(); if (length == 0) return; if (i+length>size()) throw new Exception(); Node after = (i+length==size()?null:node(i+length)); if (i>=1) { node(i-1).next = after; } else { head = after; } size -= length; } /** * 假定当前链表和list均包含已升序排列的整数 * 从当前链表中取出那些list所指定的元素 * 例如当前链表 = 11->101->201->301->401->501->601->701 * listB = 1->3->4->6 * 返回的结果应该是[101,301,401,601] * @param list * @throws Exception */ public int[] getElements(LinkedList list) throws Exception { // 不允许用get方法取得当前链表的元素,重分利用当前链表和list的有序性 if (list.size == 0) return new int[0]; if ((int)list.get(0)<0 || (int)list.get(list.size-1)>=size) { throw new Exception(); } java.util.LinkedList<Integer> aStandardList = new java.util.LinkedList<>(); Node current = head; for (int i=0,j=0; i<list.size(); i++) // i是list的下标,j是当前链表的下标 { while(j < (int)list.get(i)) { current = current.next; j++; } aStandardList.add((Integer)current.data); } return ArrayUtils.list2Array(aStandardList); } /** * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 * 从当前链表中中删除在list中出现的元素 * @param list */ public void subtract(LinkedList list){ if (list == null || list.size() == 0 || size == 0) return; Iterator it = list.iterator(); while (it.hasNext()) { int ele = (int) it.next(); removeBySort(ele); } } /** * 当前链表为有序时,删除值为ele的所有元素;无序链表的行为未定义 * @param ele */ private void removeBySort(int ele) { boolean compare = false; // 找到第一个相等元素 Node previous = null; Node current = head; while (current != null) { int data = (int) current.data; compare = Objects.equals(data, ele); if (compare) break; previous = current; current = current.next; } if (!compare) { return; } int subNum = 0; // 删除的元素个数 // 把所有从current开始的连续的相同的元素删除 if (previous == null) { while(head != null) { head = head.next; subNum++; if (head==null || !Objects.equals(ele, head.data)) { size -= subNum; return; } } } else { while(current != null) { current = current.next; previous.next = current; subNum++; if (current==null || !Objects.equals(ele, current.data)) { size -= subNum; return; } } } } /** * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) */ public void removeDuplicateValues(){ if (size() == 0) return; Node first = head; Node last = head; while (last != null) { int data = (int) first.data; while (true) { size--; last = last.next; if (last == null) { size++; first.next = null; return; } if (!Objects.equals(data, last.data)) { size++; first.next = last; break; } } first = last; } } /** * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) * @param min * @param max */ public void removeRange(int min, int max){ if (size() == 0) return; if (max < min) return; // [head, *, *, before, (.. delete ..), after] Node before = head; // before是最后一个小于等于min的数 while (before.next != null && (int) before.next.data <= min) { before = before.next; } if (before.next == null) { return; } Node after = before.next; // after是第一个大于等于max的数 while (after !=null && (int) after.data < max) { after = after.next; size--; } if (after == null) size--; before.next = after; } /** * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 * @param list */ public LinkedList intersection(LinkedList list){ if (list == null) return null; LinkedList cList = new LinkedList(); // 为了方便起见,先各自复制并去重,虽然效率不高,以后有时间再优化 LinkedList aList = LinkedList.copy(this); LinkedList bList = LinkedList.copy(list); aList.removeDuplicateValues(); bList.removeDuplicateValues(); int a = 0; // 用于遍历a链表 int b = 0; // 用于遍历b链表 while (a < aList.size() && b < bList.size()) { int aValue = (int)aList.get(a); int bValue = (int)bList.get(b); if (aValue > bValue) { b++; } else if (aValue < bValue) { a++; } else { cList.add(a); a++; b++; } } return cList; } public static LinkedList copy(LinkedList list) { LinkedList copy = new LinkedList(); Iterator it = list.iterator(); while (it.hasNext()) { copy.add(it.next()); } return copy; } public static void main(String args[]) throws Exception { LinkedList aLinkedList = new LinkedList(); for (int i=0; i<4; i=i*i) { aLinkedList.add(i); // [0,1,4,9] } LinkedList bLinkedList = new LinkedList(); int[] z1 = aLinkedList.getElements(bLinkedList); // [] System.out.println(Arrays.toString(z1)); } }