packagecom.madooei.cb;/*** @title CS226List** Generic List ADT.** @param <T> the type of elements stored in this list** 请注意:这是骨架代码,请不要修改。如需改动,请复制一份。*/publicinterfaceCS226List<T>extendsIterable<T>{voidadd(T element);Tget(int index);voidremove(int index);intsize();// Inherited from Iterable<T>:// Iterator<T> iterator();}
带哨兵节点的双链表类
packagecom.madooei.cb;importjava.util.Iterator;importjava.util.NoSuchElementException;/*** @title SDLList* @description 带哨兵节点的双链表** Sentinel Double Linked List** 注意:不是环形链表**/publicclassSDLList<T>implementsCS226List<T>{// 内部类privateclassNode{T data;Node prev;Node next;publicNode(T data){this.data = data;this.prev =null;this.next =null;}publicNode(){this.data =null;this.prev =null;this.next =null;}}privateNode head;privateNode tail;privateint size;// head->sentinelHead->sentinelTail// tail->sentinelTail->sentinelHeadpublicSDLList(){head =newNode();tail =newNode();head.next = tail;tail.prev = head;size =0;}@Overridepublicvoidadd(T element){addLast(element);}//初始:空链表// head->sentinelHead->sentinelTail// tail->sentinelTail->sentinelHead//操作:插入a//目标:// sentinelHead->a->sentinelTail// sentinelTail->a->sentinelHead//操作:插入b//目标:// sentinelHead->b->a->sentinelTail// sentinelTail->a->b->sentinelHeadpublicvoidaddFirst(T element){Node newNode =newNode(element);newNode.next = head.next;head.next.prev = newNode;newNode.prev = head;head.next = newNode;size++;}//初始:空链表// head->sentinelHead->sentinelTail// tail->sentinelTail->sentinelHead//操作:插入a//目标:// sentinelHead->a->sentinelTail// sentinelTail->a->sentinelHead//操作:插入b//目标:// sentinelHead->a->b->sentinelTail// sentinelTail->b->a->sentinelHeadpublicvoidaddLast(T element){Node newNode =newNode(element);newNode.prev = tail.prev;tail.prev.next = newNode;newNode.next = tail;tail.prev = newNode;size++;}@OverridepublicTget(int index){if(index <0|| index >= size){thrownewIndexOutOfBoundsException("数组越界#index="+index+"#size="+size);}Node current = head.next;for(int i =0; i < index; i++){current = current.next;}return current.data;}@Overridepublicvoidremove(int index){if(index <0|| index >= size){thrownewIndexOutOfBoundsException("数组越界#index="+index+"#size="+size);}Node current = head.next;for(int i =0; i < index; i++){current = current.next;}deleteNode(current);size--;}publicbooleanremove(T element){Node current = head.next;while(current !=null){if(current.data.equals(element)){deleteNode(current);// Helper methodsize--;returntrue;}current = current.next;}returnfalse;}privatevoiddeleteNode(Node target){target.prev.next = target.next;target.next.prev = target.prev;}@Overridepublicintsize(){return size;}@OverridepublicIterator<T>iterator(){returnnewLinkedListIterator();}privateclassLinkedListIteratorimplementsIterator<T>{privateNode current = head.next;@OverridepublicbooleanhasNext(){return current != tail;}@OverridepublicTnext(){if(!hasNext()){// 检查是否还有元素thrownewNoSuchElementException("No more elements in iterator");}T element = current.data;current = current.next;return element;}}publicvoidcheckInvariants(){// 1. head 和 tail 必须存在if(head ==null|| tail ==null)thrownewAssertionError("Sentinels missing");// 2. head.prev 和 tail.next 必须为 nullif(head.prev !=null)thrownewAssertionError("head.prev must be null");if(tail.next !=null)thrownewAssertionError("tail.next must be null");// 3. 检查 next.prev 一致性Node current = head;while(current.next !=null){if(current.next.prev != current)thrownewAssertionError("Broken next.prev at node "+ current);current = current.next;}// 4. 检查 prev.next 一致性current = tail;while(current.prev !=null){if(current.prev.next != current)thrownewAssertionError("Broken prev.next at node "+ current);current = current.prev;}// 5. 遍历计数与 size 一致int count =0;current = head.next;while(current != tail){count++;current = current.next;}if(count != size)thrownewAssertionError("Size mismatch: expected "+ size +", found "+ count);}}
带哨兵节点的双链表测试类
packagecom.madooei.cb;importorg.junit.jupiter.api.Assertions;importorg.junit.jupiter.api.Test;importjava.util.Iterator;importjava.util.NoSuchElementException;importjava.util.Random;/*** @title SDLListTest* @description 带哨兵节点的双链表测试类*/publicclassSDLListTest{@TestpublicvoidtestEmpty(){SDLList<String> list =newSDLList<>();Assertions.assertEquals(0, list.size());list.checkInvariants();}@TestpublicvoidtestAdd(){SDLList<String> list =newSDLList<>();Assertions.assertEquals(0, list.size());list.add("a");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals(1, list.size());list.add("b");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals("b", list.get(1));Assertions.assertEquals(2, list.size());list.add("c");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals("b", list.get(1));Assertions.assertEquals("c", list.get(2));Assertions.assertEquals(3, list.size());}@TestpublicvoidtestFrontAdd(){SDLList<String> list =newSDLList<>();Assertions.assertEquals(0, list.size());list.addFirst("a");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals(1, list.size());list.addFirst("b");list.checkInvariants();Assertions.assertEquals("b", list.get(0));Assertions.assertEquals("a", list.get(1));Assertions.assertEquals(2, list.size());list.addFirst("c");list.checkInvariants();Assertions.assertEquals("c", list.get(0));Assertions.assertEquals("b", list.get(1));Assertions.assertEquals("a", list.get(2));Assertions.assertEquals(3, list.size());}@TestpublicvoidtestTailAdd(){SDLList<String> list =newSDLList<>();Assertions.assertEquals(0, list.size());list.addLast("a");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals(1, list.size());list.addLast("b");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals("b", list.get(1));Assertions.assertEquals(2, list.size());list.addLast("c");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals("b", list.get(1));Assertions.assertEquals("c", list.get(2));Assertions.assertEquals(3, list.size());}@TestpublicvoidtestFrontRemove(){SDLList<String> list =newSDLList<>();Assertions.assertEquals(0, list.size());list.add("a");list.add("b");list.add("c");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals("b", list.get(1));Assertions.assertEquals("c", list.get(2));Assertions.assertEquals(3, list.size());int rnd =0;list.remove(rnd);list.checkInvariants();Assertions.assertEquals(2, list.size());list.remove(rnd);list.checkInvariants();Assertions.assertEquals(1, list.size());list.remove(rnd);list.checkInvariants();Assertions.assertEquals(0, list.size());}@TestpublicvoidtestRandomIndexRemove(){SDLList<String> list =newSDLList<>();Assertions.assertEquals(0, list.size());list.add("a");list.add("b");list.add("c");list.checkInvariants();Assertions.assertEquals("a", list.get(0));Assertions.assertEquals("b", list.get(1));Assertions.assertEquals("c", list.get(2));Assertions.assertEquals(3, list.size());Random random =newRandom();int rnd = random.nextInt(list.size());list.remove(rnd);Assertions.assertEquals(2, list.size());list.checkInvariants();rnd = random.nextInt(list.size());list.remove(rnd);Assertions.assertEquals(1, list.size());list.checkInvariants();rnd = random.nextInt(list.size());list.remove(rnd);Assertions.assertEquals(0, list.size());list.checkInvariants();}@TestpublicvoidtestGetOutOfBounds(){SDLList<Integer> list =newSDLList<>();list.add(1);list.add(2);Assertions.assertThrows(IndexOutOfBoundsException.class,()-> list.get(-1));Assertions.assertThrows(IndexOutOfBoundsException.class,()-> list.get(2));}@TestpublicvoidtestRemoveOutOfBounds(){SDLList<Integer> list =newSDLList<>();list.add(1);Assertions.assertThrows(IndexOutOfBoundsException.class,()-> list.remove(-1));Assertions.assertThrows(IndexOutOfBoundsException.class,()-> list.remove(1));}@TestpublicvoidtestRemoveObjectNotFound(){SDLList<String> list =newSDLList<>();list.add("a");list.add("b");Assertions.assertFalse(list.remove("c"));list.checkInvariants();Assertions.assertEquals(2, list.size());}@TestpublicvoidtestRemoveObjectFound(){SDLList<String> list =newSDLList<>();list.add("a");list.add("b");Assertions.assertTrue(list.remove("a"));list.checkInvariants();Assertions.assertEquals(1, list.size());Assertions.assertEquals("b", list.get(0));}@TestpublicvoidtestIteratorForward(){SDLList<String> list =newSDLList<>();list.add("a");list.add("b");list.add("c");Iterator<String> it = list.iterator();Assertions.assertTrue(it.hasNext());Assertions.assertEquals("a", it.next());Assertions.assertEquals("b", it.next());Assertions.assertEquals("c", it.next());Assertions.assertFalse(it.hasNext());}@TestpublicvoidtestIteratorEmptyList(){SDLList<String> list =newSDLList<>();Iterator<String> it = list.iterator();Assertions.assertFalse(it.hasNext());Assertions.assertThrows(NoSuchElementException.class, it::next);}@TestpublicvoidtestIteratorNextBeyondEnd(){SDLList<String> list =newSDLList<>();list.add("x");Iterator<String> it = list.iterator();Assertions.assertEquals("x", it.next());Assertions.assertThrows(NoSuchElementException.class, it::next);}@TestpublicvoidtestMixedOperations(){SDLList<Integer> list =newSDLList<>();list.addFirst(1);// 1list.addLast(2);// 1,2list.addFirst(0);// 0,1,2list.checkInvariants();Assertions.assertEquals(3, list.size());Assertions.assertEquals(0, list.get(0));Assertions.assertEquals(2, list.get(2));list.remove(1);// remove 1 -> 0,2list.checkInvariants();Assertions.assertEquals(2, list.size());}}