持久对象
package test; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Stack; import org.junit.Before; public class Test { public static LinkedList<String> dl; public static ArrayList<String> l; @Before public void init() { dl = new LinkedList<String>(); dl.add("N1"); dl.add("N2"); dl.add("N3"); dl.add("N4"); dl.add("N5"); l = new ArrayList<String>(); l.add("N1"); l.add("N2"); l.add("N3"); l.add("N4"); l.add("N5"); } @org.junit.Test public void test() { for (String str : dl) { System.out.println("双向链表:" + str); } for (String str : l) { System.out.println("普通arrylist:" + str); } } @org.junit.Test public void add() { // 双向链表独有的向链表头部添加元素 dl.addFirst("N6"); dl.addLast("N7"); } @org.junit.Test public void del() { dl.remove("N1"); for (String str : dl) { System.out.println("双向链表:" + str); } l.remove("N1"); for (String str : l) { System.out.println("普通arrylist:" + str); } } /** * 模仿栈的后进后出的pop * * @return */ public static String pop() { return dl.removeLast(); } /** * */ @org.junit.Test public void stack() { System.out.println(Test.pop()); for (String str : dl) { System.out.println("双向链表:" + str); } } @org.junit.Test public void t() { Stack<String> statck = new Stack<String>(); statck.push("N1"); statck.push("N2"); statck.push("N3"); statck.push("N4"); statck.push("N5"); System.out.println("pop:" + statck.pop()); for (String str : statck) { System.out.println(str); } } /** * 实现队列 * 队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除, * 所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。[1] * 队列队首删除 队尾插入 */ @org.junit.Test public void quene(){ LinkedList<String> quene = new LinkedList<String>(); quene = (LinkedList<String>)Collections.synchronizedCollection(quene); Test.addQuene(quene, "n1"); Test.addQuene(quene, "n2"); Test.addQuene(quene, "n3"); Test.frecah(quene); System.out.println("---------------------------------"); Test.delQuene(quene); Test.frecah(quene); } public static void frecah(List<String> list) { for(String str:list){ System.out.println(str); } } /** * 每次插入都会插入队尾 * @param quene * @param o */ public static void addQuene(LinkedList<String> quene,String o){ quene.add(o); } /** * 删除 从队首删除 */ public static void delQuene(LinkedList<String> quene){ quene.removeFirst(); } }
下面展示一下使用java实现双向链表的代码
1 package test.link; 2 3 4 5 public class DoubleLink<T> { 6 7 private class Node<T> { 8 /** 9 * 节点值 10 */ 11 12 private T vlaue; 13 /** 14 * 前一个节点 15 */ 16 17 private Node<T> prev; 18 /** 19 * 后一个节点 20 */ 21 22 private Node<T> prex; 23 24 public Node(T value,Node<T> prev,Node<T> prex){ 25 this.vlaue = value; 26 this.prev = prev; 27 this.prex = prex; 28 } 29 } 30 /** 31 * 链表长度 32 */ 33 private int size ; 34 /** 35 * 头节点 36 */ 37 private Node<T> head; 38 public DoubleLink(){ 39 /** 40 * 头结点不存储值 并且头结点初始化时 就一个头结点。 41 * 所以头结点的前后节点都是自己 42 * 并且这个链表的长度为0; 43 */ 44 head = new Node<>(null, null, null); 45 head.prev = head.prex ; 46 head = head.prex; 47 size = 0; 48 } 49 public int getSize(){ 50 return this.size; 51 } 52 /** 53 * 判断链表的长度是否为空 54 */ 55 public boolean isEmplty(){ 56 return size == 0; 57 } 58 /** 59 * 判断索引是否超出范围 60 */ 61 public void checkIndex(int index){ 62 if(index<0||index>=size){ 63 throw new IndexOutOfBoundsException(); 64 } 65 return; 66 } 67 /** 68 * 通过索引获取链表当中的节点 69 * 70 */ 71 public Node<T> getNode(int index){ 72 /** 73 * 检查该索引是否超出范围 74 */ 75 checkIndex(index); 76 /** 77 * 当索引的值小于该链表长度的一半时,那么从链表的头结点开始向后找是最快的 78 */ 79 if(index<size/2){ 80 Node<T> cur = head.prex; 81 for(int i=0;i<index;i++){ 82 cur = cur.prex; 83 } 84 return cur; 85 } 86 /** 87 * 当索引值位于链表的后半段时,则从链表的另端开始找是最快的 88 */ 89 /** 90 * 此 91 */ 92 Node<T> cur = head.prev; 93 int newIndex = size - (index+1); 94 for(int i=0;i<newIndex;i++){ 95 cur = cur.prev; 96 } 97 return cur; 98 } 99 /** 100 * 获取节点当中的值 101 */ 102 public T getValue(Node<T> cur){ 103 return cur.vlaue; 104 } 105 /** 106 * 获取第一个节点的值 107 */ 108 public T getFirst(){ 109 return getValue(getNode(0)); 110 } 111 /** 112 * 获取最后一个节点的值 113 */ 114 public T getLast(){ 115 return getValue(getNode(size-1)); 116 } 117 /** 118 * 插入节点 119 */ 120 public void inesert(int index,T value){ 121 //如果这次插入时 链表是空的 122 if(index==0){ 123 //这个节点的 124 Node<T> cur = new Node<T>(value, head, head.prex); 125 head.prex.prev = cur; 126 head.prex = cur; 127 size++; 128 return; 129 } 130 /** 131 * 先根据给出的插入位置 找到该链表原来在此位置的节点 132 */ 133 Node<T> node = getNode(index); 134 /** 135 *放置的位置的前一个节点就是原节点的前置节点 而后节点就是原节点 136 */ 137 Node<T> cur = new Node<T>(value,node.prev,node); 138 /** 139 * 现将该位置也就是 原节点的前节点的后节点 赋值成为新节点 140 * 然后将新节点的后置节点的值赋值成为原节点 141 */ 142 node.prev.prex = cur; 143 node.prev = cur; 144 size++; 145 } 146 /** 147 * 向表头插入数据 148 */ 149 public void insertTo(T Value) 150 { 151 inesert(0,Value); 152 } 153 /** 154 * 将元素插入到链表的尾部 155 */ 156 public void insertTotatil(T vlaue){ 157 Node<T> cur = new Node<>(vlaue,head.prev, head); 158 //head.prev 代表原来的尾部节点 159 //遵循两个原则 一 新插入节点的前一个节点的后一个节点为新节点。新节点的后一个节点的前一个节点是新节点 160 head.prev.prex = cur; 161 head.prev = cur; 162 size++; 163 } 164 /** 165 * 删除节点的方法 166 */ 167 public void del(int index){ 168 checkIndex(index); 169 Node<T> cur = getNode(index); 170 //记住此时的指针还没断开 赋值以后才相当于断开 171 cur.prev.prex = cur.prex; 172 cur.prex.prev = cur.prev; 173 size--; 174 cur = null; 175 return; 176 } 177 /** 178 * 删除第一个节点 179 */ 180 public void delFirst(){ 181 del(0); 182 } 183 /** 184 * 删除最后一个节点 185 */ 186 public void delLast(){ 187 del(size-1); 188 } 189 }