虽然这个问题的目的可能没有什么区别,但无论如何我都会陈述。我正在制作一个在图上执行Dijkstra算法的方法。该算法需要一组U未访问的城市。访问城市时,必须将其从列表中删除。
所以我想为我的集合U使用二叉搜索树,因为我能想到的最好的数据结构将允许我拥有一大堆可以高效搜索和删除的城市。
城市数组按字母顺序排列,对于索引为1,2,... n的数组,城市[0] =奥尔巴尼纽约,城市[n] =尤马AZ。
我创建了一个我想要使用的二叉搜索树,但它不是自我平衡的。如果我按原样添加所有元素,它实际上只会创建一个高度(n-1)的链接列表。
因此,我的问题是以下:如果按顺序添加数组,我该如何订购数组,或者我应该将数组添加到BST的顺序,以便生成的BST更接近记录(n)?
创建BST时我将使用以下构造函数:
//this constructor initialized a BST with a City array
//a node is created with the City object, and then appended to
//the tree
BST(City[] cities)
{
for (int i = 0; i < cities.length; i++)
{
BSTNode newNode = new BSTNode(cities[i]);
append(newNode);
}
}//end BST(int[]) ----------------------------------------------------------
使用的附加方法是:
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\
//::::::::::::::::: APPEND METHODS :::::::::::::::::::::::::::::::::::::|
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::/
//append (BSTNode) calls append(BSTNode,BSTNode), with the second parameter
//root and first parameter passed from this methods parameter.
//append finds the correct location for a node and inserts it
//
//append(BSTNode,BSTNode) adds newNode to the tree at the appropriate location
//current is used in the recursive step
//
//append(City) creates a new node with the City parameter and passes that
// node as a parameter in append(BSTNode)
public void append(City city)
{
BSTNode newNode = new BSTNode(city);
append(newNode);
}//end append(int) --------------------------------------------------------
public void append(BSTNode newNode)
{
append(newNode, root);
}//end append(BSTNode) ----------------------------------------------------
private void append(BSTNode newNode, BSTNode current)
{
if (root == null)
{
//setup root node for an empty tree
root = newNode;
root.setDepth(0);
size = 1;
} else
{
//add 1 to depth in each level of recursion
newNode.setDepth(current.getDepth() + 1);
//if newNode comes first in lexographical order compared to current
// then place left or go left
if (newNode.compareTo(current) < 0)
{
if (current.getLeft() == null)//if spot is empty
{
current.setLeft(newNode);//place node
size++;
} else
{
append(newNode, current.getLeft());//else recall this method
}
//if newNode is after current in lexographical order, then
//place right or go right
} else if (newNode.compareTo(current) > 0)
{
if (current.getRight() == null)//if spot is empty
{
current.setRight(newNode);//place node
size++;
} else
{
append(newNode, current.getRight());//else recall method
}
} else//if newNode has data that another node already has then
//print error and do not add
{
System.out.println("Attempting to append a duplicate node.\nThe"
+ "city " + newNode.getData().getName()
+ "already is in a node that"
+ "exists in this BST.\nNo element appended.");
}
}//end else*(root != null)
}//end append(BSTNode,BSTNode) ---------------------------------------------
答案 0 :(得分:1)
对于您未访问过的城市,请考虑HashMap<String, City>
或HashSet<City>
。在任何一种情况下,查找成本都是常数(即O(1)),对于足够大的n,它优于O(log(n))。
实现Dijkstra算法的常用方法是使用按成本排序的节点堆。在Java中,这可能由TreeMap<Double, City>
或按成本排序的一组成本 - 城市对表示,可能基于PriorityQueue
。在算法的每个步骤中,继续删除TreeMap.firstEntry()
,直到条目的值出现在未访问的城市列表中。
条目键为您提供到达新发现城市的最低费用。找到新城市后,添加链接到堆的所有城市,以达到每个城市的总成本为基础。除非您对替代路径感兴趣,否则添加已到达堆的城市是没有意义的。