Java 基于位置的序列ADT如何在O(1)时间内插入元素?
我在读关于基于位置的序列。(迈克尔·T·古德里奇)第四章(顺序)。Java 基于位置的序列ADT如何在O(1)时间内插入元素?,java,data-structures,Java,Data Structures,我在读关于基于位置的序列。(迈克尔·T·古德里奇)第四章(顺序)。 我所理解的是,位置序列继续以线性顺序添加节点。(基于双链接列表)此外,每个节点可能指向其他节点。 例如,以一个简单的树为例,它有四个节点a、b、c、d,由位置序列.P实现(有节点p1、p2、p3、p4) 现在,如果我想添加新的树节点“e”作为“b”的正确子节点。为此,我将在p5中添加此节点,然后我将引用e。 书中说它在O(1)时间内添加了一个节点。 我的观点是,要把e作为b的右子元素,我们不需要b的位置,我们将从“a”(链接跳
我所理解的是,位置序列继续以线性顺序添加节点。(基于双链接列表)此外,每个节点可能指向其他节点。
例如,以一个简单的树为例,它有四个节点a、b、c、d,由位置序列.P实现(有节点p1、p2、p3、p4) 现在,如果我想添加新的树节点“e”作为“b”的正确子节点。为此,我将在p5中添加此节点,然后我将引用e。 书中说它在O(1)时间内添加了一个节点。 我的观点是,要把e作为b的右子元素,我们不需要b的位置,我们将从“a”(链接跳跃)的位置得到它。为什么不是O(n) 我在Stackoverflow中找到的解决方案之一是以下代码
public interface Position{
Object element();
}
制作一个实现位置接口的类节点:
public class Node implements Position {
private Object data;
private Node next;
private Node prev;
public Node(Node prev, Object data, Node next){
this.prev = prev;
this.data = data;
this.next = next;
}
public Object element() // Method of interface Position
{
return data;
}
public void setData(Object data)
{
this.data = data;
}
public void setNext(Node next)
{
this.next = next;
}
public void setPrev(Node prev)
{
this.prev = prev;
}
public Node getNext()
{
return next;
}
public Node getPrev()
{
return prev;
}
}
制作一个实现列表ADT的类列表:
// this is a List ADT implemented using a Doubly Linked List
public class List{
private Node first;
private Node last;
private int size;
List()
{
first = null;
last = null;
size = 0;
}
public int getSize()
{
return size;
}
public boolean isEmpty()
{
return (size==0);
}
// Accessor methods
public Position first()
{
return first;
}
public Position last()
{
return last;
}
public Position before(Position p) throws Exception
{
Node n = (Node) p;
try{
return n.getPrev();
}catch(NullPointerException ex)
{
throw new Exception("Position Doesn't Exists");
}
}
public Position after(Position p) throws Exception
{
Node n = (Node) p;
try{
return n.getNext();
}catch(NullPointerException ex)
{
throw new Exception("Position Doesn't Exists");
}
}
// Update methods
public void insertFirst(Object data)
{
Node node;
if(isEmpty())
{
Node prev = null;
Node next = null;
node = new Node(prev,data,next);
first = node;
last = node;
}
else
{
Node prev = null;
Node next = first;
node = new Node(prev,data,next);
first.setPrev(node);
first = node;
}
size++;
}
public void insertLast(Object data)
{
Node node;
if(isEmpty())
{
Node prev = null;
Node next = null;
node = new Node(prev,data,next);
first = node;
last = node;
}
else
{
Node prev = last;
Node next = null;
node = new Node(prev,data,next);
last.setNext(node);
last = node;
}
size++;
}
public void insertBefore(Position p, Object data) throws Exception
{
Node cur = (Node) p;
Node prev;
try{
prev = cur.getPrev();
}catch(NullPointerException ex)
{
throw new Exception("Position Doesn't Exists");
}
Node next = cur;
Node node;
node = new Node(prev,data,next);
next.setPrev(node);
if(cur!=first)
prev.setNext(node);
else
first=node;
size++;
}
public void insertAfter(Position p, Object data) throws Exception
{
Node cur = (Node) p;
Node prev = cur;
Node next;
try{
next = cur.getNext();
}catch(NullPointerException ex)
{
throw new Exception("Position Doesn't Exists");
}
Node node;
node = new Node(prev,data,next);
prev.setNext(node);
if(cur!=last)
next.setPrev(node);
else
last=node;
size++;
}
public Object remove(Position p) throws Exception
{
Node n = (Node) p;
Object data = n.element();
if(isEmpty())
{
throw new Exception("List is Empty");
}
else
{
Node prev,next;
if(n==first && n==last)
{
first = null;
last = null;
}
else if(n==first)
{
prev = null;
next = n.getNext();
next.setPrev(prev);
first = next;
}
else if(n==last)
{
prev = n.getPrev();
next = null;
prev.setNext(next);
last = prev;
}
else
{
prev = n.getPrev();
next = n.getNext();
prev.setNext(next);
next.setPrev(prev);
}
size--;
}
return data;
}
}
和平我对这种情况的理解如下。要将新项目添加到列表中,我们必须执行以下任务: 第一个:查找目标项,然后我们要添加新项 第二个:添加项目和更改链接 正如您正确指出的,在链表的情况下,第一个操作取决于列表中项目的数量,并且将(最大)取O(n)。但是,例如在数组列表的情况下,它可能需要O(1) 我猜,书中提到了第二个任务,当目标物品已经找到时。如果您使用的是链表,那么这个操作实际上需要固定数量的操作-O(1)。对数组列表的相同操作可能需要O(n) 关于你的评论。比较一下: 基于职位
is O(n)get(i)
是O(1)优势添加(项目)
为O(n)添加位置(i,项)
是O(1)优势删除(项目)
是从O(1)到O(n)删除(i)
是O(1)优势get(i)
是从O(1)到O(n)add(item)
从O(1)到O(n)添加位置(i,项)
是从O(1)到O(2n)delete(item)
是从O(1)到O(n)删除(i)
所以,您应该了解这两种类型的优点,以便根据具体情况使用。例如,如果您需要大量的
add
和delete
操作,您应该使用LinkedList
,但是当您只需要按索引访问项目,并且add
和delete
操作很少时,请选择ArrayList
以明确说明。你在问为什么加法运算需要O(1)而不是O(n)?是的------肯贝科确实如此。但对我来说,引入新的ADT毫无意义,它的工作原理类似于基于排名的序列