• astar寻路算法优化


    /**  
    
    A星算法:    
    
    @param  startX,startY 起点  
    
    @param  endX,endY 终点  
    
    @param  distance  小于等于这个距离则寻路成功  
    
    @author aerror  
    
    */  
    
     
    
    private static const STATE_NULL:uint = 0;     
    
    private static const STATE_CLOSE:uint = 1;                  
    
     
    
    public function findPath(startX:int, startY:int, endX:int, endY:int, distance:int ):ByteArray  
    
    {  
    
        var ret:ByteArray =  new ByteArray();  
    
        ret.endian = Endian.LITTLE_ENDIAN;  
    
      
    
          
    
        var uint = iwidth;  
    
        var height:uint = iheight;  
    
        var nodelist:PathNodeFactoryVector = new PathNodeFactoryVector(width * height);  
    
          
    
        var key:uint;  
    
          
    
          
    
        var opneListSortedArr:Array = new Array();  
    
        var opneNum:int=0;  
    
        var minIndex:uint = 0;  
    
          
    
        var stateMap:Vector.<uint>= new Vector.<uint>(width * height);  
    
          
    
        var startPoint:uint = nodelist.createNode(startX,startY,0,0,PathNodeFactoryVector.NULL);  
    
        key = x + width * y;  
    
        opneListSortedArr.push(startPoint);  
    
        stateMap[key]=startPoint;  
    
        opneNum = 1;  
    
        minIndex = 0;  
    
          
    
        var found_end_point:uint = PathNodeFactoryVector.NULL;  
    
          
    
        var x:int;  
    
        var y:int;  
    
        var g:int;  
    
        var h:Number;  
    
        var f:int;  
    
        var i:int;  
    
        var min:uint = PathNodeFactoryVector.NULL;  
    
      
    
          
    
        while(true)  
    
        {  
    
              
    
            var min_key:uint;   
    
            var min_x:uint;  
    
            var min_y:uint;  
    
            var min_f:uint;  
    
            var min_g:uint;  
    
              
    
            //find the min g+h  point  
    
            //  
    
            if(opneNum >0)  
    
            {  
    
                //remove from openlist;  
    
                min = opneListSortedArr.shift();  
    
      
    
                min_x    = nodelist.getNodeX(min);  
    
                min_y    = nodelist.getNodeY(min);  
    
                min_g    = nodelist.getNodeG(min);  
    
                min_key  = min_x + width * min_y;  
    
                opneNum--;  
    
      
    
                  
    
            }  
    
            else  
    
            {  
    
                trace("FIND PATH FAILED");  
    
                break;  
    
            }  
    
              
    
            //add to close list;  
    
            stateMap[min_key] = STATE_CLOSE;// = min;  
    
              
    
              
    
              
    
            //add nearby point to openlist  
    
            for( i  = 0;i<8;i++)  
    
            {  
    
                x = min_x + nearby[i*3];  
    
                y = min_y + nearby[i*3+1];  
    
                  
    
                key = x + width * y;  
    
                  
    
                //calc h  
    
                //  
    
                h = ((endX<x)?(x-endX):(endX-x)) +  
    
                    ((endY<y)?(y-endY):(endY-y));  
    
                //we find the path when openlist contains the endpoint  
    
                //  
    
                if(h<=distance)  
    
                {  
    
                    found_end_point = nodelist.createNode(x,y,0,0,min);  
    
                    break;  
    
                }  
    
                h = h*10;  
    
                  
    
              
    
                if(x >= width || x < 0 //out of bounds ?  
    
                    || y >= height || y < 0//out of bounds ?  
    
                    || obstacles[key]!=0 //is obstacle ?  
    
                )  
    
                {  
    
                    continue;  
    
                }  
    
                  
    
                // if in close list?  
    
                var state:uint = stateMap[key];  
    
                if(state==STATE_CLOSE)  
    
                {  
    
                    continue;  
    
                }  
    
                  
    
                //calc g  
    
                //  
    
                g = (nearby[i*3+2]+min_g);  
    
                f = g+h;  
    
                  
    
                  
    
                //check if new point or old  
    
                //  
    
                var newPt:uint;  
    
                //the old point  
    
                //key key its g value,update if new g is less  
    
                //  
    
                if(state==STATE_NULL)  
    
                {  
    
                    //the new point  
    
                    //  
    
                    newPt =  nodelist.createNode(x,y,g,f,min);                        
    
                    stateMap[key] = newPt;  
    
                    nodelist.sortInsert(opneListSortedArr,newPt,0,opneNum);  
    
                      
    
                      
    
                    opneNum++;  
    
                }  
    
                else if(g<nodelist.getNodeG(state))   
    
                {  
    
                    newPt = nodelist.createNode(x,y,g,f,min);  
    
                    nodelist.sortRemove(opneListSortedArr,state,0,opneNum);  
    
                  
    
                    stateMap[key] = newPt;  
    
                    nodelist.sortInsert(opneListSortedArr,newPt,0,opneNum-1);  
    
                }  
    
                  
    
            }  
    
              
    
              
    
            //just break the upper loop  
    
            //  
    
            if(found_end_point !=PathNodeFactoryVector.NULL)  
    
            {  
    
                break;  
    
            }  
    
              
    
        }  
    
          
    
          
    
        //encode it to bytearray.   
    
        //  
    
        if(found_end_point !=PathNodeFactoryVector.NULL)  
    
        {  
    
            var pt:uint = found_end_point;   
    
            var num:int=0;  
    
            while(pt!=PathNodeFactoryVector.NULL)  
    
            {  
    
                num++;  
    
                pt =nodelist.getNodeParent(pt);  
    
            }  
    
            ret.length = num*4;  
    
            pt  = found_end_point;  
    
            i =0;  
    
            while(pt!=PathNodeFactoryVector.NULL)  
    
            {  
    
                ret.position = (num-i-1)*4;  
    
                ret.writeShort(nodelist.getNodeX(pt));  
    
                ret.writeShort(nodelist.getNodeY(pt));  
    
                i++;  
    
                pt = nodelist.getNodeParent(pt);  
    
            }  
    
              
    
            ret.position = 0;  
    
        }  
    
          
    
        //clear used memory  
    
        //  
    
        trace("used length :" + nodelist.getUsedLength() + " open num " + opneListSortedArr.length);  
    
        nodelist.clear();  
    
        stateMap.length = 0;  
    
        opneListSortedArr.length =0;  
    
        return ret;  
    
    }  
    
     
    
    路点内存管理器:  
    
        public class PathNodeFactoryVector  
    
        {  
    
            public static const NULL:uint = 0;  
    
            private var mem:Vector.<uint>;  
    
            private var writePosition:uint =0;  
    
            public function PathNodeFactoryVector(max:uint)  
    
            {  
    
                mem  = new Vector.<uint>(max*4+4);      
    
                writePosition = 4;  
    
                  
    
            }  
    
              
    
              
    
            public function getNodeX(id:uint):uint  
    
            {  
    
                return mem[id]&0xffff;  
    
            }  
    
              
    
            public function getNodeY(id:uint):uint  
    
            {  
    
                return mem[id]>>16 &0xffff;  
    
            }  
    
              
    
            public function getNodeG(id:uint):uint  
    
            {  
    
                return mem[id+1];  
    
            }  
    
              
    
              
    
            public function getNodeF(id:uint):uint  
    
            {  
    
                return mem[id+2];  
    
            }  
    
              
    
              
    
            public function getNodeParent(id:uint):uint  
    
            {  
    
                return mem[id+3];     
    
            }  
    
              
    
              
    
              
    
              
    
            public function createNode(_x:uint,_y:uint,_g:uint, _f:uint,_linkParent:uint):uint  
    
            {  
    
                mem[writePosition + 0] = (_x | _y<<16 );    
    
                mem[writePosition + 1]= _g;  
    
                mem[writePosition + 2]= _f;  
    
                mem[writePosition + 3]= _linkParent;  
    
                writePosition += 4;  
    
                return writePosition-4;  
    
            }  
    
              
    
              
    
            public function checkOK(arr:Array):Boolean  
    
            {  
    
                for(var i:int=0;i < arr.length-1;i++)  
    
                {  
    
                    if(getNodeF(arr[i]) >getNodeF(arr[i+1]))  
    
                    {  
    
                        return false;  
    
                    }  
    
                }  
    
                  
    
                return true;  
    
            }  
    
              
    
            public function sortInsert(arr:Array, newPt:uint, begin:int, end:int):void  
    
            {  
    
                //optimize for empty array  
    
                if(arr.length==0)  
    
                {  
    
                    arr.push(newPt);  
    
                    return;  
    
                }  
    
                  
    
                var new_F:uint = getNodeF(newPt);  
    
                var cur_F:uint = getNodeF(arr[begin]);  
    
                //optimize for sorted inserting with less  
    
                if(new_F <= cur_F )  
    
                {  
    
                    arr.splice(0,0,newPt);  
    
                    return;  
    
                }  
    
                //optimize for sorted inserting with larger  
    
                cur_F = getNodeF(arr[end-1]);  
    
                if(new_F  >cur_F)  
    
                {  
    
                    arr.splice(end,0,newPt);      
    
                    return;  
    
                }  
    
                else if(new_F == cur_F)  
    
                {  
    
                    arr.splice(end-1,0,newPt);    
    
                    return;  
    
                }  
    
                  
    
                while(true)  
    
                {  
    
                    if(begin==end)  
    
                    {  
    
                        cur_F = getNodeF(arr[begin]);  
    
                        if(new_F > cur_F)  
    
                            arr.splice(begin+1,0,newPt);  
    
                        else  
    
                            arr.splice(begin,0,newPt);  
    
                        return ;  
    
                    }  
    
                      
    
                      
    
                      
    
                    //find a place  
    
                    var mid:int = begin+(end-begin)/2;  
    
                    cur_F =getNodeF(arr[mid]);  
    
                    if(new_F < cur_F)  
    
                    {   
    
                        end = mid;  
    
                    }  
    
                    else if(new_F > cur_F)   
    
                    {  
    
                        begin = mid +1;       
    
                    }  
    
                    else   
    
                    {  
    
                        arr.splice(mid,0,newPt);  
    
                        return;   
    
                    }  
    
                }  
    
                  
    
            }  
    
              
    
              
    
              
    
                          
    
            public function sortRemove(arr:Array, oldPt:uint, begin:int, end:int):void  
    
            {  
    
                var old_f:uint = getNodeF(oldPt);  
    
                var i:int;  
    
                  
    
                while(true)  
    
                {  
    
                      
    
                    //find a place  
    
                    var mid:int = begin+(end-begin)/2;  
    
                    var cur_f:uint = getNodeF(arr[mid]);  
    
                    if(old_f < cur_f)  
    
                    {   
    
                        end = mid;  
    
                    }  
    
                    else if(old_f > cur_f)  
    
                    {  
    
                        begin = mid +1;       
    
                    }  
    
                    else  
    
                    {  
    
                        for(i =mid; i<end ; i++)  
    
                        {  
    
                            if(oldPt==arr[i])  
    
                            {  
    
                                arr.splice(i,1);  
    
                                return ;          
    
                            }  
    
                        }  
    
                          
    
                        for(i = mid-1; i>=0 ; i--)  
    
                        {  
    
                            if(oldPt==arr[i])  
    
                            {  
    
                                arr.splice(i,1);  
    
                                return ;          
    
                            }  
    
                        }  
    
                          
    
                        return ;  
    
                    }  
    
                }  
    
                  
    
            }  
    
              
    
            public function clear():void  
    
            {  
    
                this.mem.length = 0;  
    
            }  
    
            public function getUsedLength():uint  
    
            {  
    
                return this.writePosition;  
    
            }  
    
              
    
            public function dumpArray(opneListSortedArr:Array):void  
    
            {  
    
                for(var j:int =0;j<opneListSortedArr.length;j++)  
    
                {  
    
                    trace(getNodeF(opneListSortedArr[j]));  
    
                }  
    
            }  
    
        }  

    优化思路:

    a.开包(open list)算法优化

                    线性查找-->

                    二叉堆(binary heap 容器:Array->Vector)->

                    二分排序插入/删除(容器:Array) b. 障碍点容器优化

    dictionary(1) ->dictionary(2)--  array(1)->array(2)->bitmapdata->bytearray(8位对齐)->byteArrayarray(32位对齐)->vector. <int> c. 闭包(close list)容器优化:

    dictionary(1) -> array(1)->bitmapdata->vector. <int>  d. 过程生成的路点对象内存管理优化:

    AS动态对象(Object)->非动态对象(自定义PathNode对象)->使用bytearray自己管理内存分配对象-->使用Vector自已管理内存分配对象. e. 评估函数:

    标准(F = G+H, G=Parent.G+DIR_G, H = (ABS(X1-X)+ABS(Y1-Y) )*10 )

                 

    上述优化基本上是  左->右 == ->

     

    测试结果部分 单位:毫秒

    地图大小:500x500地图:

     

     

     

    41条测试线路的平均值结果,  足足快3比较未优化但是快了25倍以上

    未优化                                            10886 ms 所谓终极优化                                      1361.414634  ms 二分插入排序 ByteArray做内存管理 (32bit对齐 )      479.195122 ms 二分插入排序Vector做内存管理                      447.2439024 ms

     

     

    startX

    startY

    endX

    endY

    距离

    未优化

    所谓

    终极

    优化

    二分插入排序ByteArray做内存管理(32bit对齐)

    二分插入排序

    Vector做内存管理

    36

    32

    113

    125

    120.7394

    17

    8

    10

    11

    113

    125

    34

    29

    124.3262

    16

    7

    11

    11

    34

    29

    469

    463

    614.4762

    9133

    1338

    544

    493

    469

    463

    152

    155

    441.9876

    超时

    8536

    2810

    2560

    152

    155

    169

    165

    19.72308

    17763

    2743

    957

    894

    169

    165

    465

    463

    420.0238

    1159

    219

    101

    97

    465

    463

    165

    143

    438.6342

    超时

    8385

    2594

    2470

    165

    143

    220

    146

    55.08176

    19685

    2958

    1031

    965

    220

    146

    229

    139

    11.40175

    725

    234

    124

    116

    229

    139

    111

    477

    358.0056

    827

    168

    72

    70

    111

    477

    327

    350

    250.5694

    1705

    364

    164

    158

    327

    350

    319

    340

    12.80625

    210

    71

    38

    38

    319

    340

    464

    477

    199.4843

    51

    20

    18

    17

    464

    477

    71

    26

    598.2057

    20912

    2370

    801

    774

    71

    26

    465

    468

    592.1149

    6158

    922

    362

    348

    465

    468

    119

    188

    445.1022

    超时

    7749

    2499

    2372

    119

    188

    219

    314

    160.8602

    3625

    804

    309

    286

    219

    314

    79

    401

    164.8302

    28

    11

    10

    12

    79

    401

    229

    309

    175.9659

    141

    35

    24

    23

    229

    309

    91

    432

    184.8594

    41

    13

    13

    12

    91

    432

    65

    446

    29.52965

    2

    1

    7

    6

    65

    446

    227

    310

    211.5183

    100

    21

    16

    14

    227

    310

    62

    444

    212.5582

    78

    15

    13

    14

    62

    444

    354

    26

    509.8902

    644

    89

    38

    36

    354

    26

    479

    27

    125.004

    32

    14

    14

    13

    479

    27

    27

    469

    632.193

    352

    48

    29

    29

    27

    469

    10

    18

    451.3203

    3733

    936

    384

    354

    10

    18

    473

    463

    642.1791

    9152

    1331

    534

    493

    473

    463

    100

    260

    424.6622

    5947

    782

    268

    255

    100

    260

    234

    152

    172.1046

    2182

    531

    241

    226

    234

    152

    248

    135

    22.02272

    超时

    0

    113

    0

    234

    152

    249

    137

    21.2132

    598

    193

    113

    104

    249

    137

    120

    234

    161.4001

    5200

    951

    401

    377

    120

    234

    154

    203

    46.01087

    1557

    418

    214

    201

    154

    203

    404

    237

    252.3014

    4173

    882

    357

    335

    404

    237

    11

    15

    451.3679

    8876

    1331

    572

    543

    11

    15

    230

    409

    450.7738

    55030

    7070

    2308

    2179

    230

    409

    240

    97

    312.1602

    1541

    325

    161

    152

    240

    97

    25

    19

    228.7116

    1819

    375

    181

    167

    25

    19

    148

    156

    184.1141

    29

    10

    12

    9

    148

    156

    169

    188

    38.27532

    23085

    3540

    1179

    1103

    平均ms

     

     

     

     

    10886

    1361.415

    479.2

    447

     

    代码:

     

       

  • 相关阅读:
    简单所以不要忽视,关于 和 程序员应了解的实际应用
    即使用ADO.NET,也要轻量级动态生成更新SQL,比Ormlite性能更高
    即使用ADO.NET,也要轻量级实体映射,比Dapper和Ormlite均快
    如何在前端实现语义缩放(第一步)
    react教程 — 性能优化
    react教程 — 组件
    react教程 — redux
    create-react-app 创建项目 及 配置
    CSS 预处理器
    react 和 vue 对比
  • 原文地址:https://www.cnblogs.com/forlove/p/2847456.html
Copyright © 2020-2023  润新知