在 java 中反转短双向链表时遇到内存不足错误
Encountering out of memory error while reversing a short doubly linked list in java
我正在尝试反转双向链表并通过覆盖 toString 方法打印它。我在java中使用了一个实现双向链表的模板,只添加了一个方法:reverse().
我花了很多时间调试,并且能够正确打印出整个反转列表。但是,当 testReverse() 函数运行并在新的反向列表上调用覆盖的 toString() 方法时,我收到 java.lang.outofmemoryerror java heap space
错误。我已经包括了我在下面使用的双向链表的整个实现,但我几乎可以肯定这个问题与我的算法有关。
任何和所有见解或建议将不胜感激。谢谢!
public class LinkedList<T> implements Iterable<T> {
private int size;
private Node<T> beginMarker;
private Node<T> endMarker;
private class Node<NodeT> {
public Node(NodeT d, Node<NodeT> p, Node<NodeT> n) {
data = d;
prev = p;
next = n;
}
public NodeT data;
public Node<NodeT> prev;
public Node<NodeT> next;
}
public LinkedList() {
doClear();
}
public void doClear() {
beginMarker = new Node<>(null, null, null);
endMarker = new Node<>(null, beginMarker, null);
beginMarker.next = endMarker;
size = 0;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size() == 0;
}
private Node<T> getNode(int idx, int lower, int upper) {
Node<T> p;
if (idx < lower || idx > upper)
throw new IndexOutOfBoundsException("getNode index: " + idx + "; size: "+ size());
if (idx < size() / 2) { // Search through list from the beginning
p = beginMarker.next;
for (int i = 0; i < idx; i++)
p = p.next;
} else { // serch through the list from the end
p = endMarker;
for (int i = size(); i > idx; i--)
p = p.prev;
}
return p;
}
private Node<T> getNode(int idx) {
return getNode(idx, 0, size() - 1);
}
public T get(int idx) {
return getNode(idx).data;
}
public T set(int idx, T newVal) {
Node<T> p = getNode(idx);
T oldVal = p.data;
p.data = newVal;
return oldVal;
}
private void addBefore(Node<T> p, T x) {
Node<T> newNode = new Node<>(x, p.prev, p);
newNode.prev.next = newNode;
p.prev = newNode;
size++;
}
public void add(int idx, T x) {
addBefore(getNode(idx, 0, size()), x);
}
public void add(T x) {
add(size(), x);
}
private T remove(Node<T> p) {
p.next.prev = p.prev;
p.prev.next = p.next;
size--;
return p.data;
}
public T remove(int idx) {
return remove(getNode(idx));
}
public void reverse() {
Node current = beginMarker.next;
Node temp = null;
while (current != endMarker) {
temp = current.next; // store reference to next node
current.next = current.prev; // next points to previous node
current.prev = temp; // prev points to next node
current = temp; // current references temp (next node).
}
// changing references of beginning and end nodes
temp = beginMarker.next;
beginMarker.next = endMarker.prev;
endMarker.prev = temp;
/* TESTING THE PROGRAM, THIS PRINTS THE REVERSED LIST 'PROPERLY' BUT THE TESTER METHOD DOESN'T WORK */
current = beginMarker;
for (int i = 0; i <= size() + 1; i++) {
System.out.println(current.data);
current = current.next;
/* END TEST */
}
}
public String toString() {
StringBuilder sb = new StringBuilder("[ ");
for (T x : this) {
sb.append(x + " ");
}
sb.append("]");
return new String(sb);
}
public java.util.Iterator<T> iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements java.util.Iterator<T> {
private Node<T> current = beginMarker.next;
private boolean okToRemove = false;
public boolean hasNext() {
return current != endMarker;
}
public T next() {
if (!hasNext())
throw new java.util.NoSuchElementException();
T nextItem = current.data;
current = current.next;
okToRemove = true;
return nextItem;
}
public void remove() {
if (!okToRemove)
throw new IllegalStateException();
LinkedList.this.remove(current.prev);
okToRemove = false;
}
}
public static void testReverse(){
LinkedList<Integer> lst = new LinkedList<>();
for (int i = 0; i < 10; i++)
lst.add(i);
for (int i = 20; i < 30; i++)
lst.add(0, i);
System.out.println("Testing reverse:");
System.out.println("Original list:");
// Should print [ 29 28 27 26 25 24 23 22 21 20 0 1 2 3 4 5 6 7 8 9 ]
System.out.println(lst);
lst.reverse();
System.out.println("After reversal:");
// Should print [ 9 8 7 6 5 4 3 2 1 0 20 21 22 23 24 25 26 27 28 29 ]
System.out.println(lst);
}
public static void main(String[] args) {
testReverse();
}
}
public void reverse() {
Node current = beginMarker.next;
Node temp = null;
while (current != endMarker) {
temp = current.next; // store reference to next node
if (current == beginMarker.next) {
current.next = endMarker;
} else {
current.next = current.prev; // next points to previous node
}
current.prev = temp; // prev points to next node
current = temp; // current references temp (next node).
}
// changing references of beginning and end nodes
temp = beginMarker.next;
beginMarker.next = endMarker.prev;
endMarker.prev = temp;
/* TESTING THE PROGRAM, THIS PRINTS THE REVERSED LIST 'PROPERLY' BUT THE TESTER METHOD DOESN'T WORK */
current = beginMarker;
for (int i = 0; i <= size() + 1; i++) {
System.out.println(current.data);
current = current.next;
/* END TEST */
}
}
我正在尝试反转双向链表并通过覆盖 toString 方法打印它。我在java中使用了一个实现双向链表的模板,只添加了一个方法:reverse().
我花了很多时间调试,并且能够正确打印出整个反转列表。但是,当 testReverse() 函数运行并在新的反向列表上调用覆盖的 toString() 方法时,我收到 java.lang.outofmemoryerror java heap space
错误。我已经包括了我在下面使用的双向链表的整个实现,但我几乎可以肯定这个问题与我的算法有关。
任何和所有见解或建议将不胜感激。谢谢!
public class LinkedList<T> implements Iterable<T> {
private int size;
private Node<T> beginMarker;
private Node<T> endMarker;
private class Node<NodeT> {
public Node(NodeT d, Node<NodeT> p, Node<NodeT> n) {
data = d;
prev = p;
next = n;
}
public NodeT data;
public Node<NodeT> prev;
public Node<NodeT> next;
}
public LinkedList() {
doClear();
}
public void doClear() {
beginMarker = new Node<>(null, null, null);
endMarker = new Node<>(null, beginMarker, null);
beginMarker.next = endMarker;
size = 0;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size() == 0;
}
private Node<T> getNode(int idx, int lower, int upper) {
Node<T> p;
if (idx < lower || idx > upper)
throw new IndexOutOfBoundsException("getNode index: " + idx + "; size: "+ size());
if (idx < size() / 2) { // Search through list from the beginning
p = beginMarker.next;
for (int i = 0; i < idx; i++)
p = p.next;
} else { // serch through the list from the end
p = endMarker;
for (int i = size(); i > idx; i--)
p = p.prev;
}
return p;
}
private Node<T> getNode(int idx) {
return getNode(idx, 0, size() - 1);
}
public T get(int idx) {
return getNode(idx).data;
}
public T set(int idx, T newVal) {
Node<T> p = getNode(idx);
T oldVal = p.data;
p.data = newVal;
return oldVal;
}
private void addBefore(Node<T> p, T x) {
Node<T> newNode = new Node<>(x, p.prev, p);
newNode.prev.next = newNode;
p.prev = newNode;
size++;
}
public void add(int idx, T x) {
addBefore(getNode(idx, 0, size()), x);
}
public void add(T x) {
add(size(), x);
}
private T remove(Node<T> p) {
p.next.prev = p.prev;
p.prev.next = p.next;
size--;
return p.data;
}
public T remove(int idx) {
return remove(getNode(idx));
}
public void reverse() {
Node current = beginMarker.next;
Node temp = null;
while (current != endMarker) {
temp = current.next; // store reference to next node
current.next = current.prev; // next points to previous node
current.prev = temp; // prev points to next node
current = temp; // current references temp (next node).
}
// changing references of beginning and end nodes
temp = beginMarker.next;
beginMarker.next = endMarker.prev;
endMarker.prev = temp;
/* TESTING THE PROGRAM, THIS PRINTS THE REVERSED LIST 'PROPERLY' BUT THE TESTER METHOD DOESN'T WORK */
current = beginMarker;
for (int i = 0; i <= size() + 1; i++) {
System.out.println(current.data);
current = current.next;
/* END TEST */
}
}
public String toString() {
StringBuilder sb = new StringBuilder("[ ");
for (T x : this) {
sb.append(x + " ");
}
sb.append("]");
return new String(sb);
}
public java.util.Iterator<T> iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements java.util.Iterator<T> {
private Node<T> current = beginMarker.next;
private boolean okToRemove = false;
public boolean hasNext() {
return current != endMarker;
}
public T next() {
if (!hasNext())
throw new java.util.NoSuchElementException();
T nextItem = current.data;
current = current.next;
okToRemove = true;
return nextItem;
}
public void remove() {
if (!okToRemove)
throw new IllegalStateException();
LinkedList.this.remove(current.prev);
okToRemove = false;
}
}
public static void testReverse(){
LinkedList<Integer> lst = new LinkedList<>();
for (int i = 0; i < 10; i++)
lst.add(i);
for (int i = 20; i < 30; i++)
lst.add(0, i);
System.out.println("Testing reverse:");
System.out.println("Original list:");
// Should print [ 29 28 27 26 25 24 23 22 21 20 0 1 2 3 4 5 6 7 8 9 ]
System.out.println(lst);
lst.reverse();
System.out.println("After reversal:");
// Should print [ 9 8 7 6 5 4 3 2 1 0 20 21 22 23 24 25 26 27 28 29 ]
System.out.println(lst);
}
public static void main(String[] args) {
testReverse();
}
}
public void reverse() {
Node current = beginMarker.next;
Node temp = null;
while (current != endMarker) {
temp = current.next; // store reference to next node
if (current == beginMarker.next) {
current.next = endMarker;
} else {
current.next = current.prev; // next points to previous node
}
current.prev = temp; // prev points to next node
current = temp; // current references temp (next node).
}
// changing references of beginning and end nodes
temp = beginMarker.next;
beginMarker.next = endMarker.prev;
endMarker.prev = temp;
/* TESTING THE PROGRAM, THIS PRINTS THE REVERSED LIST 'PROPERLY' BUT THE TESTER METHOD DOESN'T WORK */
current = beginMarker;
for (int i = 0; i <= size() + 1; i++) {
System.out.println(current.data);
current = current.next;
/* END TEST */
}
}