如何优化主类中的链表反转方法?能否仅用单循环实现?
主类中链表反转方法的优化:单循环实现与效率提升
问题背景
需要在不修改MyListReferenceBased内部代码的前提下,优化主类中的链表反转逻辑——当前实现用了两个循环,还创建了临时链表,想去掉第二个循环,或者用单循环完成,同时提升效率,且只能通过链表的公开方法(add/get/remove等)操作。
原反转方法代码
// 位于主类反转方法中的代码,接收从主方法传入的list对象 int size = list.size(); // 创建临时链表对象,用于存储原链表的逆序内容 MyListReferenceBased temp = new MyListReferenceBased(); for (int i = 0; i < size; i++) { // list的add方法需要指定索引和对象 // get方法用于获取指定索引处的对象 temp.add(i, list.get((size-i)-1)); // remove方法用于移除指定索引处的对象 list.remove((size-i)-1); } // 原链表已空,将临时链表内容复制回原链表 for (int i = 0; i<size; i++) { list.add(i, temp.get(i)); } temp.removeAll(); // 最终结果:原链表已反转 // 临时链表已清空 System.out.println("List has been Reversed."); // 能否去掉第二个循环?直接赋值是否可行?
优化方案:单循环完成,无需临时链表
直接通过将原链表的末尾元素依次移到头部的方式,用一个循环完成反转,完全不需要临时链表和第二个复制循环。代码如下:
public static void reverse(MyListReferenceBased list) { int size = list.size(); // 只需要循环size-1次,最后一个元素会自动落到反转后的末尾 for (int i = 0; i < size - 1; i++) { // 获取当前链表的最后一个元素 Object lastItem = list.get(size - 1 - i); // 删除最后一个元素 list.remove(size - 1 - i); // 把该元素插入到链表头部 list.add(0, lastItem); } System.out.println("List has been Reversed."); }
方案说明
- 为什么不用临时链表?:每次操作直接修改原链表,把末尾元素移到头部,循环
size-1次后,整个链表就完成反转,省去了临时链表的创建和后续的复制步骤。 - 为什么不能直接赋值?:因为
MyListReferenceBased类的head成员是私有且没有提供公开的setter方法,无法直接将临时链表的节点指针赋值给原链表,只能通过公开的add/remove方法操作元素。 - 效率对比:原代码的时间复杂度是O(n²)(两次循环,每次循环中的
get/remove/add都需要遍历链表),优化后的代码依然是O(n²),但减少了一次完整的链表遍历和复制操作,实际运行效率更高,代码也更简洁。
完整参考代码
MyListReferenceBased类
public class MyListReferenceBased implements ListInterface { private Node head; public MyListReferenceBased() { head = null; } public boolean isEmpty() { return head == null; } // 请勿使用find() public int size() { int size = 0; Node curr = head; while (curr != null) { curr = curr.getNext(); size++; } return size; } private Node find (int index) { Node curr = head; for (int skip = 0; skip < index; skip++) { curr = curr.getNext(); } // end for return curr; } // end find public void add(int index, Object item) throws ListIndexOutOfBoundsException { if (index >= 0 && index < size() + 1) { if (index == 0) { // 将包含item的新节点插入链表头部 Node newNode = new Node(item, head); head = newNode; } else { Node prev = find(index-1); Node newNode = new Node(item, prev.getNext()); prev.setNext(newNode); } // end if } else { throw new ListIndexOutOfBoundsException( "List index out of bounds exception on add"); } // end if } // end add public Object get(int index) throws ListIndexOutOfBoundsException { if (index >= 0 && index < size()) { Node curr = find(index); Object dataItem = curr.getItem(); return dataItem; } else { throw new ListIndexOutOfBoundsException( "List index out of bounds exception on get"); } // end if } // end get public void remove(int index) throws ListIndexOutOfBoundsException { if (index >= 0 && index < size()) { if (index == 0) { head = head.getNext(); } else { Node prev = find(index-1); Node curr = prev.getNext(); prev.setNext(curr.getNext()); } // end if } else { throw new ListIndexOutOfBoundsException( "List index out of bounds exception on remove"); } // end if } // end remove public void removeAll() { head = null; } public String toString() { String x = ""; Node curr = head; int size = size(); for (int i = 0; i < size ; i++) { // curr.getNext(); x += curr.getItem() + " "; curr = curr.getNext(); } return x; } }
Node类
public class Node { private Object item; private Node next; public Node(Object newItem) { item = newItem; next = null; } // end constructor public Node(Object newItem, Node nextNode) { item = newItem; next = nextNode; } // end constructor public void setItem(Object newItem) { item = newItem; } // end setItem public Object getItem() { return item; } // end getItem public void setNext(Node nextNode) { next = nextNode; } // end setNext public Node getNext() { return next; } // end getNext } // end class Node
内容的提问来源于stack exchange,提问作者RhinoECE
相关产品推荐
相关产品推荐

