最短路径:Dijstra(迪杰斯特拉)算法

本文详细介绍了Dijkstra算法,包括其数据结构(加权有向边、加权有向图和最短路径)、算法核心和具体实现。算法通过最小索引优先队列选取最小节点,遍历边并进行放松操作,以计算单源最短路径。文章还提供了具体的构造过程和测试案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景

全文根据《算法-第四版》,Dijkstra(迪杰斯特拉)算法,一种单源最短路径算法。我们把问题抽象为2步:1.数据结构抽象   2.实现。 分别对应第二章、第三章。

二、算法分析

2.1 数据结构

  顶点+边->图。注意:Dijkstra算法的限定:
  • 1.边有权重,且非负
  • 2.边有向
2.1.1 加权有向边

DirectedEdge,API抽象如下:

方法 描述
DirectedEdge(int v, int w, double weight)  构造边
double weight()  边的权重
int from()  边的起点
int to()  边的终点

 

 

 

 

 

 

 

2.1.2 加权有向图

EdgeWeightedDigraph,API抽象如下:

方法 描述
EdgeWeightedDigraph(In in)  从输入流中构造图
int V()  顶点总数
int E()  边总数
void addEdge(DirectedEdge e)  将边e添加到图中
Iterable<DirectedEdge> adj(int v)  从顶点v指出的边(邻接表,一个哈希链表,key=顶点,value=顶点指出的边链表)
Iterable<DirectedEdge> edges()  图中全部边

 

 

 

 

 

 

 

 

 

 2.1.3 最短路径

DijkstraSP, API抽象如下:

方法 描述
DijkstraSP(EdgeWeightedDigraph G, int s)  构造最短路径树
double distTo(int v)  顶点s->v的距离,初始化无穷大
boolean hasPathTo(int v)  是否存在顶点s->v的路径
Iterable<DirectedEdge> pathTo(int v)  s->v的路径,不存在为null

 

 

 

 

 

 

 

元素:

最短路径树中的边(DirectedEdge[] edgeTo):

  edgeTo[v]代表树中连接v和父节点的边(最短路径最后一条边数组),每个顶点都有一条这样的边,就组成了最短路径树。

原点到达顶点的距离:由顶点索引的数组 double[] distTo:

  distTo[v] 代表原点到达顶点v的最短距离。

索引最小优先级队列: IndexMinPQ<Double> pq:

     int[] pq:索引二叉堆(元素=顶点v,对应keys[v]):数组从pq[0]代表原点其它顶点从pq[1]开始插入

     Key[] keys:元素有序数组(按照pq值作为下标赋值)存储到顶点的最短距离

 

2.2 算法核心

计算最短路径,三步骤:

  • 1.每次选取最小节顶点:如果选择?使用最小堆排序,每次取堆顶元素即可。
  • 2.遍历从顶点的发出的全部边
  • 3.放松操作

三、具体实现

3.1 构造

3.1.1 元素迭代器
因为有遍历需要,这里定义Bag<Item>类实现了Iterable<Item>迭代器接口,Item是元素。就是个简单的某个元素的迭代器基本实现。
  1 package study.algorithm.base;
  2 
  3 import java.util.Iterator;
  4 import java.util.NoSuchElementException;
  5 
  6 /**
  7  *  The {
   @code Bag} class represents a bag (or multiset) of 
  8  *  generic items. It supports insertion and iterating over the 
  9  *  items in arbitrary order.
 10  *  <p>
 11  *  This implementation uses a singly linked list with a static nested class Node.
 12  *  See {
   @link LinkedBag} for the version from the
 13  *  textbook that uses a non-static nested class.
 14  *  See {
   @link ResizingArrayBag} for a version that uses a resizing array.
 15  *  The <em>add</em>, <em>isEmpty</em>, and <em>size</em> operations
 16  *  take constant time. Iteration takes time proportional to the number of items.
 17  *  <p>
 18  *  For additional documentation, see <a href="https://algs4.cs.princeton.edu/13stacks">Section 1.3</a> of
 19  *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
 20  *
 21  *  @author Robert Sedgewick
 22  *  @author Kevin Wayne
 23  *
 24  *  @param <Item> the generic type of an item in this bag
 25  */
 26 public class Bag<Item> implements Iterable<Item> {
 27     /**
 28      * 首节点
 29      */
 30     private Node<Item> first;
 31     /**
 32      * 元素个数
 33      */
 34     private int n;
 35 
 36     /**
 37      * 链接表
 38      * @param <Item>
 39      */
 40     private static class Node<Item> {
 41         private Item item;
 42         private Node<Item> next;
 43     }
 44 
 45     /**
 46      * 初始化一个空包
 47      */
 48     public Bag() {
 49         first = null;
 50         n = 0;
 51     }
 52 
 53     /**
 54      * Returns true if this bag is empty.
 55      *
 56      * @return {
   @code true} if this bag is empty;
 57      *         {
   @code false} otherwise
 58      */
 59     public boolean isEmpty() {
 60         return first == null;
 61     }
 62 
 63     /**
 64      * Returns the number of items in this bag.
 65      *
 66      * @return the number of items in this bag
 67      */
 68     public int size() {
 69         return n;
 70     }
 71 
 72     /**
 73      * Adds the item to this bag.
 74      *
 75      * @param  item the item to add to this bag
 76      */
 77     public void add(Item item) {
 78         // 保留老的首节点
 79         Node<Item> oldfirst = first;
 80         // 构造一个新首节点
 81         first = new Node<Item>();
 82         // item为新首节点item
 83         first.item = item;
 84         // 新节点的next节点指向老的首节点
 85         first.next = oldfirst;
 86         n++;
 87     }
 88 
 89 
 90     /**
 91      * Returns an iterator that iterates over the items in this bag in arbitrary order.
 92      *
 93      * @return an iterator that iterates over the items in this bag in arbitrary order
 94      */
 95     @Override
 96     public Iterator<Item> iterator()  {
 97         return new LinkedIterator(first);  
 98     }
 99 
100     /**
101      * 链接迭代器,不支持移除
102      */
103     private class LinkedIterator implements Iterator<Item> {
104         private Node<Item> current;
105 
106         public LinkedIterator(Node<Item> first) {
107             current = first;
108         }
109 
110         @Override
111         public boolean hasNext()  { return current != null;                     }
112         @Override
113         public void remove()      { throw new UnsupportedOperationException();  }
114 
115         @Override
116         public Item next() {
117             if (!hasNext()) {
118                 throw new NoSuchElementException();
119             }
120             Item item = current.item;
121             // 下一节点
122             current = current.next; 
123             return item;
124         }
125     }
126 
127     /**
128      * Unit tests the {
   @code Bag} data type.
129      *
130      * @param args the command-line arguments
131      */
132     public static void main(String[] args) {
133         Bag<String> bag = new Bag<String>();
134         while (!StdIn.isEmpty()) {
135             String item = StdIn.readString();
136             bag.add(item);
137         }
138 
139         StdOut.println("size of bag = " + bag.size());
140         for (String s : bag) {
141             StdOut.println(s);
142         }
143     }
144 
145 }

 

3.1.2 具体构造

1. 从输入流中初始化图,输入流格式(括号内为注释,实际文件中不存在):

8(顶点数)
15(边数)
4 5 0.35(边4->5 权重=0.35)
5 4 0.35 
4 7 0.37
5 7 0.28
7 5 0.28
5 1 0.32
0 4 0.38
0 2 0.26
7 3 0.39
1 3 0.29
2 7 0.34
6 2 0.40
3 6 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值