proj1A 数据结构
skeleton地址
开始这个proj之前,至少应该对SLList, DLList,AList
有所了解
介绍
在proj1A里要用 list和Array 来创建“Double Ended Queue” ,在接下来的proj1B里要对应编写测试。LinkedListDeque.java and ArrayDeque.java
是这个proj里边要操作的文件, 推荐使用intelliJ。
找到课程提供的skeleton
找到proj1a的文件夹(反正找到就行,按照课程网页介绍可不一定能找到emmmm),里边应该有个LinkedListDequeTest.java
文件,应该像这个样子:示范/或者说没找到哦在这里能找到
LinkedListDequeTest.java
文件 中包含了一些测试示范,你可以仿照编写来测试你的程序。 这里貌似没有JUnit的使用痕迹。
课程提供的LinkedListDequeTest.java
文件仅仅包含了课程认为必要的测试内容,请根据其内容至少编写两条测试。
否则会出现测试没有覆盖所有 API的情况。
The Deque API /Deque的API介绍
Deque非常像 课程视频里介绍的SLList and AList ,这有一个cpp(网站上)版本的介绍 。
emmm,如果你忘记了SLList和AList,可以去看看这里
Deque就是Double-ended queues
的缩写,可长可短,动态变化,可以在首/尾增加或减少元素,Deque普遍包含下列的API:
- public void addFirst(T item): Adds an item of type T to the front of the deque.
- public void addLast(T item): Adds an item of type T to the back of the deque.
- public boolean isEmpty(): Returns true if deque is empty, false otherwise.
- public int size(): Returns the number of items in the deque.
- public void printDeque(): Prints the items in the deque from first to last, separated by a space.
- public T removeFirst(): Removes and returns the item at the front of the deque. If no such item exists, returns null.
- public T removeLast(): Removes and returns the item at the back of the deque. If no such item exists, returns null.
- public T get(int index): Gets the item at the given index, where 0 is the front, 1 is the next item, and so forth. If no such item exists, returns null. Must not alter the deque!
要编写泛型而不是固定某个类型的Deque,如何编写可以看这里:cs61B lecture5
看这个视频也行:cs61B 第6?5节视频
对于泛型类vs sentinel的具体处理 ,可以看这个博文:CS61B資料結構及演算法筆記:(二)單向串列及雙向串列
开始任务
1. Linked List Deque /链表Deque
注意课程第4-5节(5-6?)已经包含了所有完成本项目的内容。
先在项目文件夹中创建LinkedListDeque.java
文件,随后编写一个以链表作为存储载体的Deque,具体要求如下:
add
andremove
operations must not involve any looping or recursion. A single such operation must take “constant time”, i.e. execution time should not depend on the size of the deque.get
must use iteration, not recursion.size
must take constant time.- 使用内存数量和Deque实际存储数据的数量应该差不多,比如你加了10000个元素,又减了9999个,那使用内存数量应该是更趋向于1而不是10000,而且注意不允许“已经被删除的”对象在内存里常驻,做好对“已经被删除的”对象的引用管理。
- 要完成前文已经提到的api,并还要完成下面两个:
- public LinkedListDeque(): Creates an empty linked list deque.
- public T getRecursive(int index): Same as get, but uses recursion.
- 可以增加private(helper)方法或者private类
可以参考课程上关于doubly linked lists
的内容,可以参考关于sentinel node
的内容,推荐用circular sentinel,下面是参考的ppt:
two sentinel topology,Double sentinel
and circular sentinel topology.
You are not allowed to use Java’s built in LinkedList data structure (or any data structure from java.util.*) in your implementation.
不让用Java自带的链表什么的类似数据结构
下方是作为参考的程序,不一定对,emmmmm。
SLList
public class SLList<ItemType> {
private static class ItemNode<ItemType> {
public ItemType item ;
public ItemNode next;
public ItemNode(ItemType f, ItemNode n){
item=f;
next=n;
}
}
public int size;
private ItemNode<ItemType> sentinel ;
public SLList(){
sentinel = new ItemNode<ItemType>(null,null);
}
public SLList(ItemType item){
sentinel = new ItemNode<ItemType>(null,null);
sentinel.next=new ItemNode(item,null);
size+=1;
}
public void addFirst(ItemType item){
size+=1;
sentinel.next=new ItemNode<>(item,sentinel.next);
}
public void addLast(ItemType item){
size+=1;
ItemNode<ItemType> tmpPtr= sentinel.next;
while(tmpPtr.next!=null){
tmpPtr=tmpPtr.next;
}
tmpPtr.next=new ItemNode(item,null);
}
public static void main(String[] args) {
SLList<Integer> list = new SLList(5);
list.addFirst(4);
list.addFirst(3);
list.addFirst(2);
list.addLast(6);
list.addFirst(1);
list.addLast(7);
}
}
DLList
public class DLList<ItemType> {
// Doubly linked list 每个 node上需要有双向的“通道”
// 建议使用一个sentinel 规避 last可能指向sentinel 也可能指向正常节点的情况。
private static class ItemNode<ItemType> {
public ItemType item;
public ItemNode next;
public ItemNode prev;
public ItemNode(ItemNode p, ItemType i, ItemNode n) {
prev = p;
item = i;
next = n;
}
}
/**
* 为了让sentinel 更加明显,且不会被轻易修改
*/
private static class SentinelNode<ItemType> extends ItemNode {
public final ItemType item;
public ItemNode next;
public ItemNode prev;
public SentinelNode(ItemNode p, ItemType i, ItemNode n) {
super(p,i,n);
prev = p;
item = i;
next = n;
}
}
public int size;
private SentinelNode<String> sentinel;
public DLList() {
//initialization sentinel
sentinel = new SentinelNode<String>(null, "this is sentinel,don't change its value", null);
sentinel.prev = sentinel;
sentinel.next = sentinel;
}
public DLList(ItemType item) {
//initialization sentinel
sentinel = new SentinelNode<String>(null, "this is sentinel,don't change its value", null);
sentinel.prev = sentinel;
sentinel.next = sentinel;
ItemNode<ItemType> newNode = new ItemNode(null, item, null);
sentinel.next = newNode;
newNode.next=sentinel;
sentinel.prev=newNode;
newNode.prev=sentinel;
size += 1;
}
public void addFirst(ItemType item) {
ItemNode<ItemType> newNode = new ItemNode<>(null,item, null);
if(size==0){
sentinel.next=newNode;
sentinel.prev=newNode;
newNode.prev=sentinel;
newNode.next=sentinel;
}
else {
ItemNode oldFirstNode= sentinel.next;
newNode.next=oldFirstNode;
newNode.prev=sentinel;
sentinel.next=newNode;
oldFirstNode.prev=newNode;
}
size += 1;
}
public void addLast(ItemType item) {
ItemNode<ItemType> newNode = new ItemNode<>(null,item, null);
if(size==0){
sentinel.next=newNode;
sentinel.prev=newNode;
newNode.prev=sentinel;
newNode.next=sentinel;
}
else {
ItemNode oldLastNode= sentinel.prev;
newNode.next=sentinel;
newNode.prev=oldLastNode;
sentinel.prev=newNode;
oldLastNode.next=newNode;
}
size += 1;
}
public static void main(String[] args) {
DLList list = new DLList(5);
list.addFirst(4);
list.addFirst(3);
list.addFirst(2);
list.addLast(6);
list.addFirst(1);
list.addLast(7);
}
}
LinkedListDeque
public class LinkedListDeque<ItemType> {
private static class ItemNode<ItemType> {
public ItemType item;
public ItemNode next;
public ItemNode prev;
public ItemNode(ItemNode p, ItemType i, ItemNode n) {
prev = p;
item = i;
next = n;
}
}
/**
* 为了让sentinel 更加明显,且不会被轻易修改
*/
private static class SentinelNode<ItemType> extends ItemNode {
public final ItemType item;
public ItemNode next;
public ItemNode prev;
public SentinelNode(ItemNode p, ItemType i, ItemNode n) {
super(p,i,n);
prev = p;
item = i;
next = n;
}
}
private int size;
public SentinelNode<String> sentinel;
public LinkedListDeque(){
// in this situation ,size is 0,because ,it's empty.
sentinel = new SentinelNode<String>(null,"this is a sentinel ,don't mess with it",null);
sentinel.prev=sentinel;
sentinel.next=sentinel;
}
public LinkedListDeque(ItemType item){
// in this situation ,size is 1 ,because during the initialization ,an item is added into the list.
sentinel = new SentinelNode<String>(null,"this is a sentinel ,don't mess with it",null);
ItemNode<ItemType> newNode= new ItemNode<>(null,item,null);
sentinel.prev=newNode;
sentinel.next=newNode;
size+=1;
}
public void addFirst(ItemType item){
// 初始化一个Node,随后插入到要插入的位置
ItemNode<ItemType> newNode= new ItemNode<>(null,item,null);
// 如果是空列表
if(size==0){
sentinel.next=newNode;
sentinel.prev=newNode;
newNode.prev=sentinel;
newNode.next=sentinel;
}
// 如果不是空列表
else{
ItemNode<ItemType> oldFirstNode = sentinel.next;
sentinel.next=newNode;
newNode.prev=sentinel;
newNode.next=oldFirstNode;
oldFirstNode.prev=newNode;
}
size+=1;
}
public void addLast(ItemType item){
// 初始化一个Node,随后插入到要插入的位置
ItemNode<ItemType> newNode= new ItemNode<>(null,item,null);
// 如果是空列表
if(size==0){
sentinel.next=newNode;
sentinel.prev=newNode;
newNode.prev=sentinel;
newNode.next=sentinel;
}
// 如果不是空列表
else{
ItemNode<ItemType> oldLastNode = sentinel.prev;
sentinel.prev=newNode;
newNode.next=sentinel;
newNode.prev=oldLastNode;
oldLastNode.next=newNode;
}
size+=1;
}
public boolean isEmpty(){
return size==0;
}
public int size(){
return size;
}
public String printDeque(){
String resultStr="";
if(size==0){
System.out.println("");
return resultStr;
}
else{
ItemNode tmpPtr= sentinel.next;
while(tmpPtr.next!=null){
System.out.print(tmpPtr.item+" ");
resultStr+=tmpPtr.item+" ";
tmpPtr=tmpPtr.next;
if(tmpPtr.next==null){
System.out.println();
}
}
}
return resultStr;
}
// 不准有 loitering ,no 废弃对象不被处理
public ItemType removeFirst(){
if(size==0){
return null;
}
ItemNode<ItemType> oldFirstNode = sentinel.next;
sentinel.next=oldFirstNode.next;
oldFirstNode.next.prev=sentinel;
oldFirstNode.prev=null;
oldFirstNode.next=null;
size-=1;
return oldFirstNode.item;
}
public ItemType removeLast(){
if(size==0){
return null;
}
ItemNode<ItemType> oldLastNode = sentinel.prev;
sentinel.prev=oldLastNode.prev;
oldLastNode.prev.next=sentinel;
oldLastNode.prev=null;
oldLastNode.next=null;
size-=1;
return oldLastNode.item;
}
public ItemType get(int index){
if(index>size-1||index<0){
return null;
}
ItemNode<ItemType> tmpPtr =sentinel.next;
while(index!=0){
index-=1;
tmpPtr=tmpPtr.next;
}
return tmpPtr.item;
}
public ItemType getRecursive(int index){
if(index>size-1||index<0){
return null;
}
ItemNode<ItemType> tmpPtr =sentinel.next;
if(index==0){
return tmpPtr.item;
}
else {
return gRHelper(tmpPtr.next,index-1);
}
}
private ItemType gRHelper(ItemNode ptr,int idx){
ItemNode<ItemType> tmpPtr =ptr;
if(idx==0){
return tmpPtr.item;
}
return gRHelper(ptr.next,idx-1);
}
public static void main(String[] args) {
}
}
LinkedListDequeTest
/** Performs some basic linked list tests. */
public class LinkedListDequeTest {
/* Utility method for printing out empty checks. */
public static boolean checkEmpty(boolean expected, boolean actual) {
if (expected != actual) {
System.out.println("isEmpty() returned " + actual + ", but expected: " + expected);
return false;
}
return true;
}
/* Utility method for printing out empty checks. */
public static boolean checkSize(int expected, int actual) {
if (expected != actual) {
System.out.println("size() returned " + actual + ", but expected: " + expected);
return false;
}
return true;
}
/* Prints a nice message based on whether a test passed.
* The \n means newline. */
public static void printTestStatus(boolean passed) {
if (passed) {
System.out.println("Test passed!\n");
} else {
System.out.println("Test failed!\n");
}
}
/** Adds a few things to the list, checking isEmpty() and size() are correct,
* finally printing the results.
*
* && is the "and" operation. */
public static void addIsEmptySizeTest() {
System.out.println("Running add/isEmpty/Size test.");
// System.out.println("Make sure to uncomment the lines below (and delete this print statement).");
LinkedListDeque<String> lld1 = new LinkedListDeque<String>();
boolean passed = checkEmpty(true, lld1.isEmpty());
lld1.addFirst("front");
// The && operator is the same as "and" in Python.
// It's a binary operator that returns true if both arguments true, and false otherwise.
passed = checkSize(1, lld1.size()) && passed;
passed = checkEmpty(false, lld1.isEmpty()) && passed;
lld1.addLast("middle");
passed = checkSize(2, lld1.size()) && passed;
lld1.addLast("back");
passed = checkSize(3, lld1.size()) && passed;
System.out.println("Printing out deque: ");
lld1.printDeque();
printTestStatus(passed);
}
/** Adds an item, then removes an item, and ensures that dll is empty afterwards. */
public static void addRemoveTest() {
System.out.println("Running add/remove test.");
// System.out.println("Make sure to uncomment the lines below (and delete this print statement).");
LinkedListDeque<Integer> lld1 = new LinkedListDeque<Integer>();
// should be empty
boolean passed = checkEmpty(true, lld1.isEmpty());
lld1.addFirst(10);
// should not be empty
passed = checkEmpty(false, lld1.isEmpty()) && passed;
lld1.removeFirst();
// should be empty
passed = checkEmpty(true, lld1.isEmpty()) && passed;
printTestStatus(passed);
}
/*
* check add and remove function
*
* */
public static void addRemoveTest2(){
LinkedListDeque<Integer> lld1 = new LinkedListDeque<Integer>();
// should be empty
boolean passed = checkEmpty(true, lld1.isEmpty());
lld1.addFirst(5);
lld1.addFirst(4);
lld1.addLast(3);
lld1.addFirst(6);
lld1.addLast(2);
lld1.addFirst(7);
lld1.addLast(1);
// 7 6 5 4 3 2 1
passed=checkEmpty(false, lld1.isEmpty())&&passed;
printTestStatus(passed);
lld1.removeFirst();
lld1.removeLast();
lld1.removeLast();
lld1.removeFirst();
String expectedRemainList = "453";
System.out.println("result should be "+expectedRemainList);
System.out.print("and actual is");
String actualResult =lld1.printDeque().replaceAll("\\s+", "");
passed= expectedRemainList.equals(actualResult);
System.out.println();
printTestStatus(passed);
}
public static void getTest(){
LinkedListDeque<Integer> lld1 = new LinkedListDeque<Integer>();
System.out.println("Running get test.");
lld1.addFirst(4);
lld1.addFirst(5);
lld1.addLast(3);
lld1.addFirst(6);
lld1.addLast(2);
lld1.addLast(0);
lld1.removeLast();
lld1.addFirst(7);
lld1.addLast(1);
System.out.println("Printing out deque: ");
System.out.println("should be: \n7 6 5 4 3 2 1\nand actual is:");
lld1.printDeque();
// should be 1
System.out.println("the last item is this method get is "+lld1.get(6));
boolean passed = lld1.get(6)==1;
printTestStatus(passed);
}
public static void getReTest(){
LinkedListDeque<Integer> lld1 = new LinkedListDeque<Integer>();
System.out.println("Running getRecursive test.");
lld1.addFirst(4);
lld1.addFirst(5);
lld1.addLast(3);
lld1.addFirst(6);
lld1.addLast(2);
lld1.addLast(0);
lld1.removeLast();
lld1.addFirst(7);
lld1.addLast(1);
System.out.println("Printing out deque: ");
System.out.println("should be: \n7 6 5 4 3 2 1\nand actual is:");
lld1.printDeque();
// should be 1
System.out.println("the last item this method get is "+lld1.getRecursive(6));
boolean passed = lld1.getRecursive(6)==1;
printTestStatus(passed);
}
public static void main(String[] args) {
System.out.println("Running tests.\n");
// addIsEmptySizeTest();
// addRemoveTest();
// addRemoveTest2();
// getTest();
getReTest();
}
}
2. Array Deque 数组作为存储载体的 Deque
在project directory 创建ArrayDeque.java
, ArrayDeque 类
要使用数组作为核心存储数据结构(就是用array存元素,没办法,我的翻译水平无力,但是懂得自然懂,懂linkedList的人都知道这里面门道有多深!)
add
andremove
must take constant time, except during resizing operations.add
和remove
也要消耗恒定时间,除了 resize操作的时候get
andsize
must take constant time. get 和size方法应该消耗恒定时间(那肯定就是特别短的意思)- The starting size of your array should be 8. 初始数组长度是8
- 内存使用应该和元素数量相匹配,(load factor啊,就是实际元素个数/数组总长度)占用率不应低于25%,
包含下列API(就是上面)有过的
- public void addFirst(T item): Adds an item of type T to the front of the deque.
- public void addLast(T item): Adds an item of type T to the back of the deque.
- public boolean isEmpty(): Returns true if deque is empty, false otherwise.
- public int size(): Returns the number of items in the deque.
- public void printDeque(): Prints the items in the deque from first to last, separated by a space.
- public T removeFirst(): Removes and returns the item at the front of the deque. If no such item exists, returns null.
- public T removeLast(): Removes and returns the item at the back of the deque. If no such item exists, returns null.
- public T get(int index): Gets the item at the given index, where 0 is the front, 1 is the next item, and so forth. If no such item exists, returns null. Must not alter the deque!
- public ArrayDeque():Creates an empty array deque.
课程墙裂建议使用circular 的解决方案,据说会避免很多special coner cases,resize操作可能很麻烦,要自己好好思考。
在开始ArrayDeque之前,类似的,可以参考AList, 在lectureCode中可以找到AList,如下:
AList 课程原版
/** Array based list.
* @author Josh Hug
*/
public class AList {
/** Creates an empty list. */
public AList() {
}
/** Inserts X into the back of the list. */
public void addLast(int x) {
}
/** Returns the item from the back of the list. */
public int getLast() {
return 0;
}
/** Gets the ith item in the list (0 is the front). */
public int get(int i) {
return 0;
}
/** Returns the number of items in the list. */
public int size() {
return 0;
}
/** Deletes item from back of the list and
* returns deleted item. */
public int removeLast() {
return 0;
}
}
AList 课程原版实现
implementation:
/** Array based list.
* @author Josh Hug
*/
// 0 1 2 3 4 5 6 7
// items: [6 9 -1 2 0 0 0 0 ...]
// size: 5
/* Invariants:
addLast: The next item we want to add, will go into position size
getLast: The item we want to return is in position size - 1
size: The number of items in the list should be size.
*/
public class AList<Item> {
private Item[] items;
private int size;
/** Creates an empty list. */
public AList() {
items = (Item[]) new Object[100];
size = 0;
}
/** Resizes the underlying array to the target capacity. */
private void resize(int capacity) {
Item[] a = (Item[]) new Object[capacity];
System.arraycopy(items, 0, a, 0, size);
items = a;
}
/** Inserts X into the back of the list. */
public void addLast(Item x) {
if (size == items.length) {
resize(size + 1);
}
items[size] = x;
size = size + 1;
}
/** Returns the item from the back of the list. */
public Item getLast() {
return items[size - 1];
}
/** Gets the ith item in the list (0 is the front). */
public Item get(int i) {
return items[i];
}
/** Returns the number of items in the list. */
public int size() {
return size;
}
/** Deletes item from back of the list and
* returns deleted item. */
public Item removeLast() {
Item x = getLast();
items[size - 1] = null;
size = size - 1;
return x;
}
}
AList课程原版 test:
import org.junit.Test;
import static org.junit.Assert.*;
/** Tests the AList class.
* @author Josh Hug
*/
public class AListTest {
@Test
public void testEmptySize() {
AList L = new AList();
assertEquals(0, L.size());
}
@Test
public void testAddAndSize() {
AList L = new AList();
L.addLast(99);
L.addLast(99);
assertEquals(2, L.size());
}
@Test
public void testAddAndGetLast() {
AList L = new AList();
L.addLast(99);
assertEquals(99, L.getLast());
L.addLast(36);
assertEquals(36, L.getLast());
}
@Test
public void testGet() {
AList L = new AList();
L.addLast(99);
assertEquals(99, L.get(0));
L.addLast(36);
assertEquals(99, L.get(0));
assertEquals(36, L.get(1));
}
@Test
public void testRemove() {
AList L = new AList();
L.addLast(99);
assertEquals(99, L.get(0));
L.addLast(36);
assertEquals(99, L.get(0));
L.removeLast();
assertEquals(99, L.getLast());
L.addLast(100);
assertEquals(100, L.getLast());
assertEquals(2, L.size());
}
/** Tests insertion of a large number of items.*/
@Test
public void testMegaInsert() {
AList L = new AList();
int N = 1000000;
for (int i = 0; i < N; i += 1) {
L.addLast(i);
}
for (int i = 0; i < N; i += 1) {
L.addLast(L.get(i));
}
}
public static void main(String[] args) {
jh61b.junit.TestRunner.runTests("all", AListTest.class);
}
}
AList speedTest
可以用 time
命令来测试程序运行时间。
(是 javac *.class ,然后在 java SpeedTest
,或者使用idea,直接在out/production 类似的文件夹里java SpeedTest
)
public static void main(String[] args) {
AList L = new AList();
int N = 1000000000;
for (int i = 0; i < N; i += 1) {
L.addLast(i);
}
for (int i = 0; i < N; i += 1) {
L.addLast(L.get(i));
}
}
}
下面是 自己写的,可以比对上面看看区别。
AList非课程原版实现,无法保甜
/** Array based list.
* @author Josh Hug
*/
public class AList {
private int[] items;
private int size ;
//index 0 1 2 3 4 5 6
// items [0 0 0 0 0 0 0]
// size 1 2 3 4 5 6 7
/** Creates an empty list. */
public AList() {
size=0;
items = new int[8];
}
private int[] createNewArray(int currentLength){
int[] newArray = new int[currentLength*2];
System.arraycopy(items,0,newArray,0,size);
return newArray;
}
/** Inserts X into the back of the list. */
public void addLast(int x) {
int length = items.length;
if(size==length){
int[] newArray= createNewArray(size);
newArray[size]=x;
items=newArray;
size+=1;
return;
}
items[size]=x;
size+=1;
}
/** Returns the item from the back of the list. */
public int getLast() {
return items[size-1];
}
/** Gets the ith item in the list (0 is the front). */
public int get(int i) {
return items[i];
}
/** Returns the number of items in the list. */
public int size() {
return size;
}
/** Deletes item from back of the list and
* returns deleted item. */
public int removeLast() {
int length = items.length;
if(size/length<=0.25){
int newArrLength = length/2;
if(newArrLength<16){
newArrLength= 16;
}
int[] newArray = new int[newArrLength];
System.arraycopy(items,0,newArray,0,length);
int oldLastItem =newArray[size-1];
newArray[size-1]=0;
size-=1;
items=newArray;
return oldLastItem;
}
int x = getLast();
items[size-1]=0;
size-=1;
return x;
}
}
AList测试,不保甜版本
AListTest
import org.junit.Test;
import static org.junit.Assert.*;
/** Tests the AList class.
* @author Josh Hug
*/
public class AListTest {
@Test
public void testEmptySize() {
AList L = new AList();
assertEquals(0, L.size());
}
@Test
public void testAddAndSize() {
AList L = new AList();
L.addLast(99);
L.addLast(99);
assertEquals(2, L.size());
}
@Test
public void testAddAndGetLast() {
AList L = new AList();
L.addLast(99);
assertEquals(99, L.getLast());
L.addLast(36);
assertEquals(36, L.getLast());
}
@Test
public void testGet() {
AList L = new AList();
L.addLast(99);
assertEquals(99, L.get(0));
L.addLast(36);
assertEquals(99, L.get(0));
assertEquals(36, L.get(1));
}
@Test
public void testRemove() {
AList L = new AList();
L.addLast(99);
assertEquals(99, L.get(0));
L.addLast(36);
assertEquals(99, L.get(0));
L.removeLast();
assertEquals(99, L.getLast());
L.addLast(100);
assertEquals(100, L.getLast());
assertEquals(2, L.size());
}
/** Tests insertion of a large number of items.*/
@Test
public void testMegaInsert() {
AList L = new AList();
int N = 1000000;
for (int i = 0; i < N; i += 1) {
L.addLast(i);
}
for (int i = 0; i < N; i += 1) {
L.addLast(L.get(i));
}
}
public static void main(String[] args) {
jh61b.junit.TestRunner.runTests("all", AListTest.class);
}
}
ArrayDeque 不保甜 版本
public class ArrayDeque<ItemType> {
private int size;
private ItemType[] items;
// array [0 0 0 0 0 0 0 0]
// index [0 1 2 3 4 5 6 7]
// size [1 2 3 4 5 6 7 8]
// length [1 2 3 4 5 6 7 8]
public ArrayDeque(){
items=(ItemType[] ) new Object[8];
size-=0;
}
private void resize(int oldLength){
ItemType[] newArray =(ItemType[] ) new Object[oldLength*2];
System.arraycopy(items,0,newArray,0,oldLength);
items=newArray;
}
// 在有限条件下(可以确定总元素个数不大于数组总长度。(
// 也就是向后移动元素后,元素顺序不变,元素没有移动位置,元素个数没有少,
// 这个操作的关键思路是,从最后一个(如果设置为空)索引,从后往前替换。
private void MoveArrayItemBackward() {
for (int i = items.length - 1; i >0; i--) {
items[i] = items[i - 1]; // 向后移动元素
// 注意 原始的第 items[0] 没变化
}
}
// 类似操作,把元素向前移动。
// 这里也要保证 第一个元素为空,数组总长足够。
private void moveArrayItemsForward() {
for (int i = 0; i <items.length-1; i++) {
items[i] = items[i + 1]; // 向前移动元素
}
items[items.length-1]=null;
}
// addFirst 就是把所有元素后移,在空出来的第一个位置加一个
public void addFirst(ItemType item){
if(size== items.length){
resize(items.length);
}
if(size==0){
items[0]=item;
size+=1;
return;
}
else{
// 这里可以确定 增加一个元素后的元素总个数也没有超过数组总长,因为最开始做了 size和items.length的检查
MoveArrayItemBackward();
items[0]=item;
size+=1;
return;
}
}
public int size(){
return size;
}
public void addLast(ItemType item){
if(size== items.length){
resize(items.length);
}
items[size]=item;
size+=1;
}
public boolean isEmpty(){
return size==0;
}
public void printDeque(){
for(int i =0;i<size;i++){
System.out.print(items[i]+" ");
}
}
public ItemType removeFirst(){
int currentLength = items.length;
double compareResult = (double)size/currentLength;
if(compareResult<0.25){
resize((int)Math.floor(items.length/4));
}
ItemType FirstItem = items[0];
items[0]=null;
moveArrayItemsForward();
size-=1;
return FirstItem;
}
public ItemType removeLast(){
int currentLength = items.length;
double compareResult = (double)size/currentLength;
if(compareResult<0.25){
resize((int)Math.floor(items.length/4));
}
ItemType lastItem = items[size-1];
items[size-1]=null;
size-=1;
return lastItem;
}
public ItemType get(int index){
if(index<0||index>size-1){
return null;
}
return items[index];
}
public static void main(String[] args) {
}
}
ArrayDequeTest 不保甜 版本
import org.junit.Test;
import static org.junit.Assert.*;
public class ArrayDequeTest {
@Test
public void testEmptySize() {
ArrayDeque L = new ArrayDeque<Integer>();
assertEquals(0, L.size());
}
@Test
public void testAddFirst() {
ArrayDeque L = new ArrayDeque<Integer>();
for (int i = 10; i > 0; i--) {
L.addFirst(i);
}
L.addFirst(0);
assertEquals(11, L.size());
}
@Test
public void testIsEmpty() {
ArrayDeque L = new ArrayDeque<Integer>();
assertTrue(L.isEmpty());
L.addFirst(1);
assertFalse(L.isEmpty());
}
@Test
public void testPrintDeque() {
ArrayDeque L = new ArrayDeque<Integer>();
System.out.println("testing PrintDeque,\nexpected should be:\n1 2 3 4 5 6 7 8 9 10");
for (int i = 10; i > 0; i--) {
L.addFirst(i);
}
System.out.println("actual is :");
L.printDeque();
}
@Test
public void testRemoveFirst() {
ArrayDeque L = new ArrayDeque<Integer>();
for (int i = 10; i > 0; i--) {
L.addFirst(i);
}
System.out.println("testing RemoveFirst,\nexpected should be:\n1 2 3 4 " +
"5 6 7 8 9 10,the first item will disappear in turn");
for (int i = 0; i < 10; i++) {
L.removeFirst();
L.printDeque();
System.out.println();
}
}
@Test
public void testRemoveLast() {
ArrayDeque L = new ArrayDeque<Integer>();
for (int i = 10; i > 0; i--) {
L.addFirst(i);
}
System.out.println("testing RemoveFirst,\noriginal list is:\n1 2 3 4 " +
"5 6 7 8 9 10,the last item will disappear in turn");
for (int i = 0; i < 10; i++) {
L.removeLast();
L.printDeque();
System.out.println();
}
}
@Test
public void testGet() {
ArrayDeque L = new ArrayDeque<Integer>();
L.addFirst(4);
L.addFirst(5);
L.addFirst(6);
L.addLast(5);
L.addLast(6);
L.addLast(8);
L.removeLast();
L.removeFirst();
L.removeFirst();
L.addFirst(3);
L.addFirst(2);
L.addFirst(1);
L.addLast(9);
L.removeFirst();
System.out.println("test Get ,should be:\n 2 3 4 5 6 9\nactual is:\n");
L.printDeque();
assertEquals(L.get(5), 9);
System.out.println("get the last item ,should be 9\nactual is:" + L.get(5));
}
public static void main(String[] args) {
jh61b.junit.TestRunner.runTests("all", ArrayDequeTest.class);
}
}
SpeedTestLinkedList LinkedList的速度测试,貌似超过10w就很慢了。
public class SpeedTestLinkedList
{
public static void main(String[] args) {
LinkedListDeque<Integer> L = new LinkedListDeque<Integer>();
int N = Integer.parseInt(args[0]);
for (int i = 0; i < N; i += 1) {
L.addLast(i);
}
for (int i = 0; i < N; i += 1) {
L.addLast(L.get(i));
}
}
}
不保证准确。。。。
标签:srping,sp18,proj1A,int,next,item,sentinel,public,size From: https://www.cnblogs.com/nulixuexipython/p/18646503