美文网首页
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