Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays FlashAS3,如何用整数键索引hashmap_Arrays_Actionscript 3_Search_Indexing_Timestamp - Fatal编程技术网

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]


现在我正在遍历每一个键,以找到最近的一个。是否有某种方法可以索引这些时间戳,以便比线性时间搜索更快?(我会有很多键!)也许我不想要字典?

您可以使用二进制搜索(分治)方法,将状态保存在排序数组中,然后递归:

  • 将数组分成两半
  • 如果数组包含一项,则返回该项
  • 确定哪一半将包含正确的结果
  • 转到步骤1
  • 这应该在对数时间内找到结果。(注意log2(1000)~10和log2(10000)~13)


    下面是一个草案(未经测试)实现:

    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);
            }
        }
    }