Arrays FlashAS3,如何用整数键索引hashmap
事情是这样的 现在我有一本游戏状态字典Arrays FlashAS3,如何用整数键索引hashmap,arrays,actionscript-3,search,indexing,timestamp,Arrays,Actionscript 3,Search,Indexing,Timestamp,事情是这样的 现在我有一本游戏状态字典 history = new Dictionary(); 每个状态的键为时间戳(int) 我的问题是,如何找到最近的游戏状态。比如说,我想知道在670时的状态,我想要不超过670的最新历史(我不想展示未来)。这将是历史[500] 现在我正在遍历每一个键,以找到最近的一个。是否有某种方法可以索引这些时间戳,以便比线性时间搜索更快?(我会有很多键!)也许我不想要字典?您可以使用二进制搜索(分治)方法,将状态保存在排序数组中,然后递归: 将数组分成两半 如果数组
history = new Dictionary();
每个状态的键
为时间戳(int)
我的问题是,如何找到最近的游戏状态。比如说,我想知道在670
时的状态,我想要不超过670
的最新历史(我不想展示未来)。这将是历史[500]
现在我正在遍历每一个键,以找到最近的一个。是否有某种方法可以索引这些时间戳,以便比线性时间搜索更快?(我会有很多键!)也许我不想要字典?您可以使用二进制搜索(分治)方法,将状态保存在排序数组中,然后递归:
下面是一个草案(未经测试)实现:
class HistoryEntry
{
public var timestamp:int;
public var state:GameState;
public function HistoryEntry(timestamp:int, state:GameState)
{
this.timestamp = timestamp;
this.state = state;
}
}
class History
{
private var states:Array;
public function History()
{
super();
states = [];
}
public function addState(state:State):void
{
var timestamp:int = getTimer();
var entry:HistoryEntry = new HistoryEntry(timestamp, state);
states.push(entry);
}
public function getStateBefore(timestamp:int):State
{
return doGetStateBefore(timestamp, 0, states.length - 1);
}
// Recursive function
private function doGetStateBefore(timestamp:int, beginIndex:int, endIndex:int):State
{
if (beginIndex == endIndex) {
return states[beginIndex];
}
var beginEntry:HistoryEntry = states[beginIndex];
var endEntry:HistoryEntry = states[endIndex];
if (beginEntry.timestamp == timestamp) {
return beginEntry.state;
}
if (endEntry.timestamp == timestamp) {
return endEntry.state;
}
var middleIndex:int = (beginIndex + endIndex) / 2;
var middleEntry:HistoryEntry = states[middleIndex];
if (midleEntry.timestamp >= timestamp) {
return doGetStateBefore(timestamp, beginIndex, middleIndex);
} else {
return doGetStateBefore(timestamp, middleIndex + 1, endIndex);
}
}
}
我引入了类
HistoryEntry
,以便从数组中获取类型化对象,因为使用动态对象会对性能产生负面影响。您应该提供更多信息,例如性能约束、修改状态列表的次数、读取状态列表的次数等。例如,如果您阅读列表的次数多于修改列表的次数,那么保持列表的有序性可能是一个好主意。但它总是被分类的(如果我要改变它,我会创造一个新的历史,历史不能改变),我只是不知道如何利用这个事实!嗯,键之间的间隔不会随着列表的长度而增加。如果您只是从感兴趣的点(例如67066968…)向后搜索,性能应该更合理。+1我键入了类似的答案。只是一种预感,他可能会发现迭代版本(见链接)更容易,因为他并不寻找精确的匹配。这真是太棒了。但我不确定它是否会一直有效?因为精确匹配并不总是存在的,在这种情况下,我需要最接近的时间戳,它不大于搜索的时间戳。我会试试看会发生什么。我确信我想要的是二进制搜索,而不是哈希映射。如果没有精确匹配,搜索将在只剩下一个项目时停止(请参阅doGetStateBefore
开头的If条件)。如果实现是正确的,则该项应该是具有最近时间戳的项。
class HistoryEntry
{
public var timestamp:int;
public var state:GameState;
public function HistoryEntry(timestamp:int, state:GameState)
{
this.timestamp = timestamp;
this.state = state;
}
}
class History
{
private var states:Array;
public function History()
{
super();
states = [];
}
public function addState(state:State):void
{
var timestamp:int = getTimer();
var entry:HistoryEntry = new HistoryEntry(timestamp, state);
states.push(entry);
}
public function getStateBefore(timestamp:int):State
{
return doGetStateBefore(timestamp, 0, states.length - 1);
}
// Recursive function
private function doGetStateBefore(timestamp:int, beginIndex:int, endIndex:int):State
{
if (beginIndex == endIndex) {
return states[beginIndex];
}
var beginEntry:HistoryEntry = states[beginIndex];
var endEntry:HistoryEntry = states[endIndex];
if (beginEntry.timestamp == timestamp) {
return beginEntry.state;
}
if (endEntry.timestamp == timestamp) {
return endEntry.state;
}
var middleIndex:int = (beginIndex + endIndex) / 2;
var middleEntry:HistoryEntry = states[middleIndex];
if (midleEntry.timestamp >= timestamp) {
return doGetStateBefore(timestamp, beginIndex, middleIndex);
} else {
return doGetStateBefore(timestamp, middleIndex + 1, endIndex);
}
}
}