算法上机报告

(一)渗透问题(Percolation)

  1. 问题描述:
    我们使用N×N网格点来模型一个渗透系统。每个格点或是open格点或是blocked格点。 一个full site是一个open格点,它可以通过一连串的邻近(左,右,上,下)open格点连通到顶行的一个open格点。如果在底行中有一个full site格点,则称系统是渗透的。

  2. 数据类型
    Percolation数据类型:模型化一个Percolation系统,创建含有以下API的数据类型Percolation。

public class Percolation {
   public Percolation(int N)           // create N-by-N grid, with all sites blocked
   public void open(int i, int j)         // open site (row i, column j) if it is not already
   public boolean isOpen(int i, int j)    // is site (row i, column j) open?
   public boolean isFull(int i, int j)     // is site (row i, column j) full?
   public boolean percolates()          // does the system percolate?
   public static void main(String[] args)  // test client, optional
}

PercolationStats数据类型:我们创建数据类型PercolationStats来执行一系列计算实验,包含以下API。

public class PercolationStats {
   public PercolationStats(int N, int T)    // perform T independent computational experiments on an N-by-N grid
   public double mean()                // sample mean of percolation threshold
   public double stddev()               // sample standard deviation of percolation threshold
   public double confidenceLo()         // returns lower bound of the 95% confidence interval
   public double confidenceHi()         // returns upper bound of the 95% confidence interval
   public static void main(String[] args)    // test client, described below
}
  1. 问题分析:
    首先,可以确定该问题使用合并-查找(union-find)数据结构,把一个节点和他四周相邻的任意open节点合并(union),只要第一行的任意节点和第N行的任意节点处于同一并查集里,及渗透系统可渗透,问题解决。
    初始思路是用一个复杂度N*N的两层for循环,检查每一个第一行节点和每一个第N行的节点是否相连,但是如果N非常大,该思路的效率就很低,于是思考,在第一行之上加一个虚拟节点p,和第一行的每个open节点联通,在第N行之下加一个虚拟节点q,和第N行的每个open节点联通,这样只用判断p和q是否连通即可。
  2. 测试渗透算法PercolationStats
  • 初始化所有格点为blocked。
  • 重复以下操作直到系统渗出:
    ①在所有blocked的格点之间随机均匀选择一个格点 (row i, column j)。
    ②设置这个格点(row i, column j)为open格点。
  • open格点的比例提供了系统渗透时渗透阈值的一个估计。

重复测试渗透阈值,计算均值、标准差、95%置信区间上限及下限。

  1. 比较不同的合并-查找算法
    规模:N=50,T=100
    在这里插入图片描述
    规模:N=100,T=100
    在这里插入图片描述
    规模:N=200,T=100
    在这里插入图片描述
  2. 示例输出
    在这里插入图片描述

(二)几种排序算法的实验性能比较

  1. 问题描述:
    实现插入排序(Insertion Sort,IS),自顶向下归并排序(Top-down Mergesort,TDM),自底向上归并排序(Bottom-up Mergesort,BUM),随机快速排序(Random Quicksort,RQ),Dijkstra 3-路划分快速排序(Quicksort with Dijkstra 3-way Partition,QD3P)。在你的计算机上针对不同输入规模数据进行实验,对比上述排序算法的时间及空间占用性能。要求对于每次输入运行10次,记录每次时间/空间占用,取平均值。
  2. 问题分析:
    写出5种排序算法,并随机生成100000个随机数分别用5种排序算法进行排序,记录运行时间和内存空间占用
  3. 几种排序算法性能比较
    数据规模:随机生成10000个1到100000的随机整数用不同排序算法排序,每次计算100次排序的时间总和
    Comparison of running time of sorting algorithms (in Micro Seconds)
    在这里插入图片描述
    Comparison of space usage of sorting algorithms (in Kilo Bytes)
    在这里插入图片描述
  4. 结果分析
    通过上面两个表格可知,对于随机整数(顺序打乱):
    插入排序最慢,且与其他几种排序形成鲜明对比,但内存占用最小,若内存空间紧张且对时间性能要求不高,可以选择插入排序。
    两种归并排序由于需要辅助数组,内存空间占用很大,但时间性能比插入排序快很多。
    快速排序和三路快排时间和空间性能都较为优秀。

(三)地图路由(Map Routing)

  1. 问题描述
    实现经典的Dijkstra最短路径算法,并对其进行优化。
    想法1. Dijkstra算法的朴素实现检查图中的所有V个顶点。 减少检查的顶点数量的一种策略是一旦发现目的地的最短路径就停止搜索。 通过这种方法,可以使每个最短路径查询的运行时间与E’ log V’成比例,其中E’和V’是Dijkstra算法检查的边和顶点数。 然而,这需要一些小心,因为只是重新初始化所有距离为∞就需要与V成正比的时间。由于你在不断执行查询,因而只需重新初始化在先前查询中改变的那些值来大大加速查询。
    想法2. 你可以利用问题的欧式几何来进一步减少搜索时间,这在算法书的第21.5节描述过。对于一般图,Dijkstra通过将d[w]更新为d[v] + 从v到w的距离来松弛边v-w。 对于地图,则将d[w]更新为d[v] + 从v到w的距离 + 从w到d的欧式距离 从v到d的欧式距离。 这种方法称之为A*算法。这种启发式方法会有性能上的影响,但不会影响正确性。
  2. 问题分析
    这个问题要求我们先读取地图数据,根据数据画出地图,输入两个点,输出这两个点之间的最短路径,以及最短路径的长度。这是经典Dijkstra就可以实现的。但经典Dijkstra对于该问题来说,有一个最大的问题就是冗余计算,所以我们要根据问题描述里的想法一和想法二进行优化。
    我对于想法一的优化是:检测索引优先队列每次delmin()弹出的节点,若弹出的节点正是输入的终点,就停止程序的继续检索。
    我对于想法二的优化是:建立无向边Edge的类,以表示边的数据结构,Edge里包含了v(边的顶点之一),w(边的另一个顶点),weight(边的权重)这三个属性,在读取地图信息时,每读一个边,就计算他的权重,存入WEIGHT。
  3. 结果分析
    画出地图并标出第1到第999个节点的最短路径(黑色为地图,红色为最短路径)
    在这里插入图片描述
    路径的具体内容:
    from: 1 to: 999
    1-4 1.00000
    4-18 13.60147
    18-34 25.49510
    34-37 1.41421
    37-46 10.29563
    46-50 2.23607
    50-57 4.00000
    57-78 8.00000
    78-84 3.60555
    84-87 3.16228
    87-94 6.32456
    94-120 18.78829
    120-125 3.16228
    125-143 12.80625
    143-169 25.94224
    169-183 6.70820
    183-206 23.32381
    206-215 9.84886
    215-232 23.60085
    232-271 23.43075
    271-278 2.82843
    278-279 1.41421
    279-285 0.00000
    285-303 5.00000
    303-312 1.41421
    312-340 10.04988
    340-360 10.00000
    360-410 18.02776
    410-422 3.16228
    422-441 8.54400
    441-459 8.94427
    459-479 9.00000
    479-505 16.03122
    505-545 14.31782
    545-585 5.09902
    585-600 5.00000
    600-632 7.00000
    632-638 2.23607
    638-660 11.04536
    660-670 6.32456
    670-678 5.09902
    678-681 1.41421
    681-685 2.23607
    685-697 6.08276
    697-729 16.49242
    729-734 2.23607
    734-760 9.43398
    760-785 8.60233
    785-804 7.28011
    804-811 6.32456
    811-856 33.61547
    856-859 2.23607
    859-892 17.00000
    892-896 2.23607
    896-900 8.60233
    900-921 11.40175
    921-923 2.23607
    923-945 14.21267
    945-944 2.00000
    944-981 37.57659
    981-991 3.16228
    991-999 2.00000
    路径总权重:573.6662959705246
    (源代码太长了,所以只叙述思想)
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值