美文网首页
dijkstra(狄克斯特拉)算法

dijkstra(狄克斯特拉)算法

作者: MoneyRobber | 来源:发表于2019-05-18 22:32 被阅读0次

    dijkstra是用来求最短路径的一种算法,能得出最优解,属于广度优先搜索法

    思路分解

    图1表示一个有向,有权图


    图1

    图2表示初始配置,假设开始节点s为v1,第一个选择的顶点为v1,路径的长为0,改顶点标记为已知,既然v1已知,那么某些表项就需要调整,邻接到v1的顶点是是v2,v4,这两个顶点的项得到调整,如图3所示


    图2
    图3
    下一步,选取v4标记为已知。顶点v3,v5,v6,v7时邻接的顶点,对这几个顶点进行调整,如图4
    图4

    接着选择v2,v4是邻接的点,但已经是已知的,因此不做任何工作。v5是邻接的点,因为经过v2的值为2+10 = 12,而长为3的路径是已知的,图5指出在这些顶点被选取之后的表


    图5
    下一个选取的顶点是v5,其值为3,。v7是其唯一的邻接顶点,但是它不用调整,因为3+6 > 5.然后选取v3,对v6的距离下调到3+5 = 8,结果如图6
    图6
    然后选择v7.v6下调到5+1 = 6,如图7
    图7
    最后我们选择v6,如图8
    图8

    时间复杂度分析

    V表示顶点,E表示边
    通过扫描表来得出每一步最小的dv,那么每一步将花费O(V)时间找到最小值,那么整个算法将花费O(V2)来查找最小值dv,每次更新dw的时间为常数,每条边最多有一次更新总计为O(E),因此总的运行时间为O(V2) + O(E) = O(V2)

    如果图是稠密的E和V2成线性关系,这种算法不仅简单,而且几乎是最优的
    如果图是稀疏的E = V,那么这种算法就太慢了,需要优化
    优化的方式可以采用二叉堆优化

    Code

    //
    //  ViewController.m
    //  ppp
    //
    //  Created by Liashui on 2019/5/18.
    //  Copyright © 2019年 Liashui. All rights reserved.
    //
    
    #import "ViewController.h"
    
    /**
     邻接链表节点
     */
    @interface Node:NSObject
    @property(nonatomic,copy)NSString *name;//名称
    @property(nonatomic,assign)NSInteger weight;//权重
    @property(nonatomic,strong)Node *next;//下个节点
    @end
    
    @implementation Node
    @end
    
    /**
     辅助数组元素节点
     */
    @interface Node1:NSObject
    @property(nonatomic,copy)NSString *name;//名称
    @property(nonatomic,assign)BOOL known;//是否已经设置
    @property(nonatomic,assign)NSInteger d;//当前最短路径
    @property(nonatomic,strong)Node1 *p;//移动到当前顶点的上一个顶点
    @end
    
    @implementation Node1
    @end
    
    @interface ViewController ()
    @property(nonatomic,strong)NSMutableArray *array;//邻接链表
    @property(nonatomic,strong)NSMutableArray *arrayOne;//辅助数组结构
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        //初始化邻接表
        [self initArray];
        
        //起点索引
        int start = 0;
        [self dijkstraWithStart:start];
        
        //终点索引
        int end = 5;
        Node1 *nodeEnd = self.arrayOne[end];
        NSLog(@"v%d",start+1);
        [self printRoute:nodeEnd];
    }
    
    /**
     初始化邻接表
     */
    - (void)initArray {
        //v1
        Node *node2 = [Node new];
        node2.name = @"v2";
        node2.weight = 2;
        node2.next = nil;
        
        Node *node4 = [Node new];
        node4.name = @"v4";
        node4.weight = 1;
        node4.next = node2;
        
        Node *node1 = [Node new];
        node1.name = @"v1";
        node1.weight = 0;
        node1.next = node4;
        
        //v2
        Node *nod55 = [Node new];
        nod55.name = @"v5";
        nod55.weight = 10;
        nod55.next = nil;
        
        Node *node44 = [Node new];
        node44.name = @"v4";
        node44.weight = 3;
        node44.next = nod55;
        
        Node *node22 = [Node new];
        node22.name = @"v2";
        node22.weight = 0;
        node22.next = node44;
        
        //v3
        Node *nod666 = [Node new];
        nod666.name = @"v6";
        nod666.weight = 5;
        nod666.next = nil;
        
        Node *node111 = [Node new];
        node111.name = @"v1";
        node111.weight = 4;
        node111.next = nod666;
        
        Node *node333 = [Node new];
        node333.name = @"v3";
        node333.weight = 0;
        node333.next = node111;
        
        //v4
        Node *node6 = [Node new];
        node6.name = @"v3";
        node6.weight = 2;
        node6.next = nil;
        
        Node *node7 = [Node new];
        node7.name = @"v6";
        node7.weight = 8;
        node7.next = node6;
        
        Node *node8 = [Node new];
        node8.name = @"v7";
        node8.weight = 4;
        node8.next = node7;
        
        Node *node9 = [Node new];
        node9.name = @"v5";
        node9.weight = 2;
        node9.next = node8;
        
        Node *node10 = [Node new];
        node10.name = @"v4";
        node10.weight = 0;
        node10.next = node9;
        
        //v5
        Node *node11 = [Node new];
        node11.name = @"v7";
        node11.weight = 6;
        node11.next = nil;
        
        Node *node12 = [Node new];
        node12.name = @"v5";
        node12.weight = 0;
        node12.next = node11;
        
        //v6
        Node *node13 = [Node new];
        node13.name = @"v6";
        node13.weight = 0;
        node13.next = nil;
        
        //v7
        Node *node14 = [Node new];
        node14.name = @"v6";
        node14.weight = 1;
        node14.next = nil;
        
        Node *node15 = [Node new];
        node15.name = @"v7";
        node15.weight = 0;
        node15.next = node14;
        
        self.array = [[NSMutableArray alloc] initWithObjects:node1,node22,node333,node10,node12,node13,node15, nil];
    }
    
    /**
     打印路径
    
     @param node 顶点
     */
    - (void)printRoute:(Node1 *)node {
        if (!node.p) {
            return;
        }
        [self printRoute:node.p];
        NSLog(@"%@",node.name);
    }
    
    /**
     初始化辅助数组
     */
    - (void)initArrayOne:(NSInteger)start {
        self.arrayOne = [NSMutableArray new];
        for (int i = 0; i< self.array.count; i++) {
            Node1 *node1 = [Node1 new];
            if (i == start) {
                node1.d = 0;
                node1.known = YES;
            } else {
                node1.d = 10000;
                node1.known = NO;
            }
            node1.p = nil;
            node1.name = [NSString stringWithFormat:@"v%d",i+1];
            [self.arrayOne addObject:node1];
        }
    }
    
    /**
     dijkstra算法
     @param start 起点index
     */
    - (void)dijkstraWithStart:(NSInteger)start{
        //初始化
        [self initArrayOne:start];
        
        NSInteger knownCount = 1;
        NSInteger k = start;
        Node1 *tmp = self.arrayOne[k];
        tmp.known = YES;
        while (1) {
            Node *tmp1 = self.array[k];
            tmp1 = tmp1.next;
            Node1 *tmpN = self.arrayOne[k];
            
            //赋值
            while (tmp1) {
                NSInteger index = [[tmp1.name stringByReplacingOccurrencesOfString:@"v" withString:@""] integerValue] - 1;
                Node1 *tmp2 = self.arrayOne[index];
                if (!tmp2.known) {
                    if (tmpN.d + tmp1.weight < tmp2.d) {
                        tmp2.d = tmpN.d + tmp1.weight;
                        tmp2.p = tmpN;
                    }
                }
                tmp1 = tmp1.next;
            }
            
            //找出最小值
            NSInteger min = 1000;
            for (int j = 0; j<self.arrayOne.count; j++) {
                Node1 *node1 = self.arrayOne[j];
                if (!node1.known) {
                    if (node1.d < min) {
                        min = node1.d;
                        k = j;
                    }
                }
            }
            
            Node1 *w = self.arrayOne[k];
            w.known = YES;
            knownCount ++;
            if (knownCount == self.arrayOne.count) {
                break;
            }
        }
    }
    
    @end
    
    

    console

    2019-05-19 17:20:44.030575+0800 [13576:669580] v1
    2019-05-19 17:20:44.030848+0800 [13576:669580] v4
    2019-05-19 17:20:44.030994+0800 [13576:669580] v7
    2019-05-19 17:20:44.031551+0800 [13576:669580] v6
    

    相关文章

      网友评论

          本文标题:dijkstra(狄克斯特拉)算法

          本文链接:https://www.haomeiwen.com/subject/juhxzqtx.html