1 module prova.util.linkedlist; 2 3 import std.typecons; 4 5 /** 6 * Linked list node 7 */ 8 class Node(T) 9 { 10 private LinkedList!T list; 11 private Node!T next; 12 private Node!T last; 13 private Nullable!T value; 14 15 /** 16 * Retrieves the stored value 17 */ 18 T getValue() 19 { 20 return value; 21 } 22 23 /** 24 * Modifies the stored value 25 */ 26 void setValue(T value) 27 { 28 this.value = value; 29 } 30 31 /** 32 * Gets the node previous in order 33 */ 34 Node!T getLast() 35 { 36 return last; 37 } 38 39 /** 40 * Gets the node next in order 41 */ 42 Node!T getNext() 43 { 44 return next; 45 } 46 47 /** 48 * Detaches the node from the list 49 */ 50 void remove() 51 { 52 if(last) 53 last.next = next; 54 55 if(next) 56 next.last = last; 57 58 if(list.last == this) 59 list.last = null; 60 61 if(list.first == this) 62 list.first = null; 63 64 list.count--; 65 } 66 } 67 68 /** 69 * LinkedList template 70 */ 71 class LinkedList(T) 72 { 73 private Node!T first; 74 private Node!T last; 75 private int count = 0; 76 77 /** 78 * Returns the node count 79 */ 80 @property int length() 81 { 82 return count; 83 } 84 85 Node!T getFirstNode() 86 { 87 return first; 88 } 89 90 Node!T getLastNode() 91 { 92 return last; 93 } 94 95 /** 96 * Creates a node and places it at the start of the list 97 */ 98 Node!T insertFront(T value) 99 { 100 return insertBefore(value, first); 101 } 102 103 /** 104 * Creates a node and places it at the end of the list 105 */ 106 Node!T insertBack(T value) 107 { 108 return insertAfter(value, last); 109 } 110 111 /** 112 * Creates a node in the list placed before the specified node 113 */ 114 Node!T insertBefore(T value, Node!T node) 115 { 116 if(!node && first) 117 return insertBefore(value, first); 118 119 Node!T storedNode = new Node!T; 120 storedNode.value = value; 121 storedNode.list = this; 122 123 if(node) { 124 storedNode.last = node.last; 125 node.last = storedNode; 126 storedNode.next = node; 127 } else { 128 first = last = storedNode; 129 } 130 131 if(storedNode.last) 132 storedNode.last.next = storedNode; 133 134 count++; 135 return storedNode; 136 } 137 138 /** 139 * Creates a node in the list placed after the specified node 140 */ 141 Node!T insertAfter(T value, Node!T node) 142 { 143 if(!node && last) 144 return insertAfter(value, last); 145 146 Node!T storedNode = new Node!T; 147 storedNode.value = value; 148 storedNode.list = this; 149 150 if(node) { 151 storedNode.next = node.next; 152 node.next = storedNode; 153 storedNode.last = node; 154 } else { 155 first = last = storedNode; 156 } 157 158 if(storedNode.next) 159 storedNode.next.last = storedNode; 160 161 count++; 162 return storedNode; 163 } 164 165 /** 166 * Tests if the list contains a node with the specified value 167 */ 168 bool contains(T value) 169 { 170 foreach(Node!T node; this) 171 if(node.value == value) 172 return true; 173 174 return false; 175 } 176 177 /** 178 * Removes the first node with the specified value 179 */ 180 void remove(T value) 181 { 182 foreach(Node!T node; this) { 183 if(node.value == value) { 184 node.remove(); 185 break; 186 } 187 } 188 } 189 190 /** 191 * Empties the LinkedList 192 */ 193 void clear() 194 { 195 first = null; 196 last = null; 197 count = 0; 198 } 199 200 int opApply(int delegate(ref Node!T result) dg) 201 { 202 int result = 0; 203 204 for(Node!T node = first; node; node = node.next) { 205 result = dg(node); 206 207 if(result) 208 break; 209 } 210 211 return result; 212 } 213 214 int opApply(int delegate(ref T result) dg) 215 { 216 int result = 0; 217 218 for(Node!T node = first; node; node = node.next) { 219 T value = node.getValue(); 220 result = dg(value); 221 222 if(result) 223 break; 224 } 225 226 return result; 227 } 228 }