Java 为自定义链表实现插入方法?
我想要一些关于我写的在链表中插入元素的方法的反馈。给出的链表类定义为:Java 为自定义链表实现插入方法?,java,data-structures,linked-list,insert,nodes,Java,Data Structures,Linked List,Insert,Nodes,我想要一些关于我写的在链表中插入元素的方法的反馈。给出的链表类定义为: public class List { private Node head; private static class Node { public String data; public Node next; public Node(String data, Node next) { //Assign data and next here } //Optiona
public class List {
private Node head;
private static class Node {
public String data;
public Node next;
public Node(String data, Node next) {
//Assign data and next here
}
//Optional Node helper methods are written here
}
//List methods and data go here
基于这个定义,我试图创建一个insert方法。我不确定给我的定义是否包含size()
方法,但我假设没有,并尝试在我的insert方法中查找大小(基本上是列表中的节点数)。该方法具有签名public void insert(String s,int psn)
当给出非法索引(psn)值(超出范围)时,该方法还应引发IllegalArgumentException。我猜,psn
的值范围是从0到第一个空元素出现时的值(如果我不正确,请纠正我。这是我编写的方法:
public void insert(String s, int psn) {
Node temp = head; //Save original head
int c = 0;
while (temp != null) { //Traverse linked list
c++;
temp = temp.next;
}
if (psn < 0 || psn >= c) { //Should throw exception when illegal value is used
throw new IllegalArgumentException();
}
if (psn == 0) { //Special case when inserting an element at the front of the list
head = new Node(s, head);
} else if (head != null) {
Node current = head; //Save original head while traversing list
while (current != null) {
current = current.next;
psn--;
}
if (current != null) { //We are at the position where we want to insert the element
current.next = new Node(s, current.next);
}
}
}
public void插入(字符串s,int psn){
节点温度=头部;//保存原始头部
int c=0;
while(temp!=null){//遍历链表
C++;
温度=下一个温度;
}
如果(psn<0 | | psn>=c){//在使用非法值时应引发异常
抛出新的IllegalArgumentException();
}
如果(psn==0){//在列表前面插入元素时的特殊情况
头部=新节点(多个,头部);
}else if(head!=null){
节点当前=头;//遍历列表时保存原始头
while(当前!=null){
当前=当前。下一步;
psn--;
}
如果(current!=null){//,则我们位于要插入元素的位置
current.next=新节点(s,current.next);
}
}
}
有没有人能告诉我,在查找链表长度时,我是否正确使用了第一个while循环,以及我是否正确地使用了它(除了例外)?这是我最关心的部分。提前非常感谢!您可以通过在一些测试用例上运行它来测试代码。但下面是我对您的评论此代码:
- 最后一个if语句
将始终返回false,因为之前的while循环将使if(current!=null)
在结尾处为nullcurrent
- 在第一个while循环之前,我会检查psn是否
,以减少浪费的计算0
- 我建议您在类中保留一个名为
的字段,它将处理列表的大小。首先它将设置为0,在每次size
和每次insert
之后,您将更新此字段remove
public void insert(String s, int psn) {
if(psn < 0 || psn > size)
throw new IllegalArgumentException();
Node temp = head; //Save original head
for(int i=0;i<psn-1;i++)
temp = temp.next;
temp.next = new Node(s, temp.next);
this.size++;
}
public void insert(字符串s,int psn){
如果(psn<0 | | psn>大小)
抛出新的IllegalArgumentException();
节点温度=头部;//保存原始头部
对于(int i=0;i
- 是的,这是在不存储大小的情况下检索LinkedList中元素数量的正确方法
- 这是链表的一个缺点,就是O(n)遍历,但如果存储“tail”元素,则插入1次
- 参见Matan Kintzlinger的逻辑建议
目前,您的insert
将遍历整个列表两次,一次用于查找大小,另一次用于查找节点。最基本的实现是,没有数据可以帮助您在每次写入时更新大小字段,只需遍历它一次,因为如果点击earli,您将知道所需的位置无效呃,比预期的要高。我将这样实施它:
public void insert(String item, int position) {
if(position == 0) {
head = new Node(item, head);
return;
}
List.Node previousNode = head;
for(int i = 1; i < position && previousNode != null; ++i) {
previousNode = previousNode.next;
}
if(position < 0 || previousNode == null) {
throw new IllegalArgumentException("index " + position + " is out of bounds");
}
previousNode.next = new Node(item, previousNode.next);
}
public void插入(字符串项,int位置){
如果(位置==0){
head=新节点(项目,head);
返回;
}
List.Node-previousNode=head;
对于(int i=1;i
其他考虑因素包括:
- 尽量使用描述性变量名,而不是缩写词,如
psn
,因为没有完整的上下文,它们可能很难阅读。在大多数真实场景中,优化人类可读性更为重要,因为调试和维护代码的人越容易理解代码,出现错误的可能性就越小很多时候,变量名实际上是你了解发生了什么事情的第一条线索,是一个真正的理智保护程序!我上一次试图理解外部库中的代码为什么会崩溃时,被一个给定的变量名保存是在几天前
- 尝试使用和提前返回以避免。如果您在方法中避免,那么发现它们并不是问题。例如,在这种情况下,在零位置插入的特殊情况是一个提前返回机会,因为不需要检查,并且在完成后无需执行任何操作
- 使您的异常尽可能有用。这意味着,当您因为捕获了另一个异常而抛出异常时,请按顺序将捕获的异常作为原因;在这种情况下,如果不存在早期异常,则提供一条帮助开发人员了解发生了什么的有用消息就足够了。在这种情况下,
IllegalArgument异常
并没有告诉我们很多导致抛出此异常的原因,因此是消息。几乎每个异常构造函数都允许一条消息和一个可丢弃的
原因