Java实现带Scanner输入的循环单链表插入元素覆盖问题排查
循环单链表插入异常问题排查
问题现象
本次作业要求实现循环单链表的节点插入方法,通过Scanner获取用户输入。当前输入3个元素时功能正常,但插入第4个元素时出现异常:
依次输入1、2、3后再插入新元素4,列表展示结果为1、2、4,期望结果应为1、2、3、4,第3个元素被覆盖。
问题代码
主方法代码
import java.util.Scanner; public class MySinglyLinkedCircularListMain { public static void main(String[] args) throws ListOverflowException { Scanner keyboard = new Scanner(System.in); MySinglyLinkedCircularList<Node> singlyLinkedCircularList = new MySinglyLinkedCircularList<>(); while (true) { System.out.println("+---------------------------------------------------+"); System.out.println("| Select the Number to be executed: |\n" + "| 1) Insert an element |\n" + "| 2) Delete an element from the list |\n" + "| 3) Get an element from the list |\n" + "| 4) Search an element in the list |\n" + "| 5) Number of elements in the list |\n" + "| 6) Show the elements in the list |"); System.out.print("+---------------------------------------------------+ \n"); System.out.print("Input your choice: "); int intInput = keyboard.nextInt(); if (intInput == 1) { singlyLinkedCircularList.insert(new Node(singlyLinkedCircularList)); } else if (intInput == 2) { singlyLinkedCircularList.delete(new Node(singlyLinkedCircularList)); } else if (intInput == 3) { singlyLinkedCircularList.getElement(new Node(singlyLinkedCircularList)); } else if (intInput == 4) { singlyLinkedCircularList.search(new Node(singlyLinkedCircularList)); } else if (intInput == 5){ System.out.println("The current capacity of the single circular linked list is " + singlyLinkedCircularList.getSize()); } else if (intInput == 6) { singlyLinkedCircularList.showAllElements(); System.out.println(); } } } }
Node类代码
public class Node<T> { T data; Node<T> next; public Node(T data) { this.data = data; next = null; } public T getData() { return data; } public void setData(T data) { this.data = data; } public void setNext(Node<T> node) { next = node; } public Node<T> getNext() { return next; } }
链表实现类(含插入方法)代码
import java.util.NoSuchElementException; import java.util.Scanner; public class MySinglyLinkedCircularList<E> implements MyList<E> { Scanner keyboard = new Scanner(System.in); int size; Node<E> startNode; Node<E> endNode; public MySinglyLinkedCircularList() { size = 0; startNode = endNode = null; } public int getSize() { return size; } public void insert(E data) throws ListOverflowException { System.out.print("Input the element you want: "); data = (E) keyboard.next(); Node<E> newNode = new Node(data); if (startNode == null) { startNode = endNode = newNode; startNode.next = startNode; size++; System.out.println("Element " + startNode.getData() + " has been stored in position " + getSize() + " and is now referenced itself"); } else { Node<E> addNode = endNode; for (int i = 0; i < getSize(); i++) { addNode = addNode.getNext(); } addNode.next = newNode; newNode.next = startNode; size++; } }
元素展示方法代码
public void showAllElements() { Node<E> showNode = startNode; int i = 0; System.out.print("Here are the current elements: "); while (i<getSize()) { System.out.print(showNode.getData() + " "); showNode = showNode.getNext(); i++; } System.out.print(showNode.getData()); }
自定义List接口代码
public interface MyList<E> { public int getSize(); public void insert(E data) throws ListOverflowException; public E getElement(E data) throws NoSuchElementException; public boolean delete(E data); // returns false if the data is not deleted in the list public boolean search(E data); public void showAllElements(); }
根因分析
- 插入逻辑错误:代码已经维护了
endNode尾节点指针,但插入尾部后没有更新endNode为新插入的节点,同时多余的循环逻辑导致后续插入时总是覆盖旧的尾节点后继,造成节点丢失。 - 展示逻辑错误:while循环已经遍历输出了所有
size个节点,最后额外多输出一次节点值,此时指针已经回到首节点,会导致输出结果冗余。 - 泛型使用错误:主类中声明的链表泛型为
Node类型,实际存储的是用户输入的字符串,类型不匹配,且insert方法内部直接覆盖了传入的参数,参数设计不合理。
修复方案
1. 修正插入逻辑
删除多余的循环,插入后更新尾节点指针:
public void insert(E data) throws ListOverflowException { System.out.print("Input the element you want: "); data = (E) keyboard.next(); Node<E> newNode = new Node(data); if (startNode == null) { startNode = endNode = newNode; startNode.next = startNode; size++; System.out.println("Element " + startNode.getData() + " has been stored in position " + getSize() + " and is now referenced itself"); } else { // 直接在尾节点后插入新节点 endNode.next = newNode; newNode.next = startNode; // 更新尾节点为新插入的节点 endNode = newNode; size++; } }
2. 修正展示逻辑
删除多余的输出语句:
public void showAllElements() { Node<E> showNode = startNode; int i = 0; System.out.print("Here are the current elements: "); while (i<getSize()) { System.out.print(showNode.getData() + " "); showNode = showNode.getNext(); i++; } }
3. 修正主类泛型与调用逻辑
调整泛型为实际存储的String类型:
// 泛型改为存储String MySinglyLinkedCircularList<String> singlyLinkedCircularList = new MySinglyLinkedCircularList<>(); // 调用insert时无需传入Node对象 if (intInput == 1) { singlyLinkedCircularList.insert(null); }
如果要代码更合理,可直接删除insert方法的入参,因为方法内部没有使用传入的参数,完全通过Scanner读取输入。
内容的提问来源于stack exchange,提问作者Julliard - Kun
相关产品推荐
相关产品推荐

