matlab 實現堆優化的迪傑斯特拉算法

迪傑斯特拉算法詳細算法我就不多比比啦,本人比較懶。我看了下網上好像沒有matlab 版堆優化的迪傑斯特拉,索性自己寫了一個。

堆也是自己寫的,詳情參見我的另一篇文章 https://blog.csdn.net/shengsikandan/article/details/105396751

代碼涉及到技術包括:使用元胞數組作爲結構的最小堆,使用元胞數組實現類似c++裏的vector容器

D = [ [0,12,inf,inf,inf,16,14],       %距離矩陣
        [12,0,10,inf,inf,7,inf],
        [inf,10,0,3,5,6,inf],
        [inf,inf,3,0,4,inf,inf],
        [inf,inf,5,4,0,2,8],
        [16,7,6,inf,2,0,9],
        [14,inf,inf,inf,8,9,0]
      ];
n = 7;

% --------------------------------------------------------------
% 構造node節點容器,是一個元胞數組矩陣,元素有兩個值。
% 第一個值是節點編號,第二個值是該點與點i(矩陣第i行)的距離
node = {};
for i = 1:n
    k = 1;
    for j = 1:n
        if D(i,j) < inf && D(i,j) ~=0
            node{i,k} = {j;D(i,j)};
            k = k + 1;
        end
    end
end
% --------------------------------------------------------------

dis = ones(n)*inf;   % 最終的最短路徑矩陣;

% --------------------------------------------------------------
% 迪傑斯特拉算法核心部分  該部分求的是任意兩點的最短距離
%s = 6;
for s = 1:n
    dis(s,s) = 0;
    hp = make_heap({});           %建立一個空堆
    hp = push(hp,s,0);       
    while ~isempty(hp)
        tmpid = cell2mat(hp{1}(1));
        tmpd = cell2mat(hp{1}(2));
        hp = pop(hp);
        i = 1;
        n = length({node{tmpid,:}});
        while i <= n && ~isempty(cell2mat(node{tmpid,i}))
            pos = cell2mat(node{tmpid,i}(1));
            ds = tmpd + cell2mat(node{tmpid,i}(2));
            if dis(s,pos) > ds
                dis(s,pos) = ds;
                hp = push(hp,pos,ds);
            end
            i = i + 1;
        end
    end  
end
% --------------------------------------------------------------
dis

function a = swap(a,i,j)  %交換數組的兩個元素 
    t = a{i};
    a{i} = a{j};
    a{j} = t;
end

% 向下調整函數
function a = shiftdown(a,i)
    n = length(a);
    if 2*i <= n && 2*i+1 <= n && i <= n
        if cell2mat(a{i}(2)) > cell2mat(a{2*i}(2))
            a = swap(a,i,2*i);
            a = shiftdown(a,2*i);
        end
        if cell2mat(a{i}(2)) > cell2mat(a{2*i+1}(2))
            a = swap(a,i,2*i+1);
            a = shiftdown(a,2*i+1);
        end
    elseif 2*i <= n
        if cell2mat(a{i}(2)) > cell2mat(a{2*i}(2))
            a = swap(a,i,2*i);
            a = shiftdown(a,2*i);
        end
    end
end
% 構造一個最小堆
function a = make_heap(a)   
    n = length(a);
    for i = n/2:-1:1
        a = shiftdown(a,i);
    end
end

% 彈出堆頂元素
function a = pop(a)
    a(1) = [];
    n = length(a);
    a = shiftdown(a,1);
end

%添加一個元素
function a = push(a,id,value)
    n = length(a)+1;
    a{n} = {id;value};
    n = length(a);
    while n>=2
        parent = floor(n/2);
        if cell2mat(a{n}(2)) < cell2mat(a{parent}(2))
            a = swap(a,parent,n);
        end
        n = parent;
    end
end

白嫖請點個贊,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章