Files
hsa/Html/apps/static/第二周-算法设计范式:分而治之与归并排序.html
2025-09-24 11:29:31 +08:00

126 lines
6.1 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html>
<head>
<style>
img {
max-width: 100%;
height: auto;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.2.0/github-markdown.min.css">
</head>
<body class="markdown-body">
<h1>算法设计范式:分而治之与归并排序</h1>
<blockquote>
<p>Auto-generated at 2025-09-22 15:38</p>
</blockquote>
<h2>算法设计范式:分而治之与归并排序</h2>
<h3>第一关:理论探究:分而治之的力量</h3>
<p><strong>案例背景:智慧城市交通优化系统</strong></p>
<p>在上周的工作中你已经实现并分析了插入排序在交通数据处理中的性能。虽然它在数据量较小或基本有序的情况下表现不错但在应对大规模拥堵逆序数据其性能瓶颈非常明显。本周你的项目经理Agent将向你介绍一种更高效的算法设计思想——“分而治之”并要求你掌握其代表算法归并排序。</p>
<h4>任务:理解与分析</h4>
<h5>场景介绍</h5>
<p>你的经理告诉你归并排序Merge Sort是解决大规模排序问题的利器。在投入编码之前你必须先从理论上理解它为何如此高效。</p>
<h5>思考题</h5>
<p>请与右侧的Agent你的项目经理对话清晰地回答以下问题以证明你已理解核心思想</p>
<ol>
<li>
<p><strong>分治思想</strong>根据课程资料请解释什么是“分而治之”Divide-and-Conquer设计范式它包含哪三个基本步骤</p>
</li>
<li>
<p><strong>递推关系</strong>:归并排序的时间复杂度可以用递推式 T(n)=2T(n/2)+Θ(n) 来表示。请解释这个式子各部分的含义:</p>
<ul>
<li><code>2</code> 代表什么?</li>
<li><code>T(n/2)</code> 代表什么?</li>
<li><code>Θ(n)</code> 代表什么?</li>
</ul>
</li>
<li>
<p><strong>效率对比</strong>你的同事认为插入排序经过极致优化后处理n个数据的耗时为 $0.1n^2$;而归并排序由于递归和合并开销,耗时为 1000nlog_2n。在处理超大规模城市交通数据时即n趋于无穷大时哪个算法最终会胜出请从渐进增长的角度解释你的理由。</p>
</li>
<li>
<p><strong>增长排序</strong>:将下列函数的渐进增长率从低到高排序,并将它们划分到等价类(即 Θ 关系相同的函数)。这有助于你理解不同算法效率的所在层级。 </p>
<ul>
<li>$n^2$ (插入排序最坏情况)</li>
<li>nlogn (归并排序)</li>
<li>n (一种非常低效的蛮力算法)</li>
<li>$2^n$ (另一种指数级算法)</li>
<li>logn (类似二分查找的效率)</li>
</ul>
</li>
</ol>
<h3>第二关:编程实践:实现归并排序</h3>
<h4>任务:编码与对比</h4>
<h5>场景介绍</h5>
<p>现在你已经从理论上理解了归并排序的威力。是时候亲手实现它,并与上周的插入排序进行一次性能上的正面较量了!</p>
<h5>题目:实现归并排序并对比性能</h5>
<p>你需要实现归并排序的核心函数,并利用上周的测试框架来直观对比它与插入排序在处理不同交通数据时的表现。</p>
<h5>代码框架</h5>
<p>在下方代码编辑区,完成 <code>merge_sort(arr)</code><code>merge(left, right)</code> 两个函数的实现。
```python
import random
import time</p>
<h1>上周实现的插入排序(用于对比)</h1>
<p>def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j &gt;= 0 and arr[j] &gt; key:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
return arr</p>
<h1>--- 本周任务:请在下方实现归并排序 ---</h1>
<p>def merge_sort(arr):
"""
实现归并排序算法
参数arr: 待排序的交通数据数组
返回: 一个新的、排序好的数组
"""
# TODO: 实现归并排序的递归逻辑
# 提示当数组元素个数小于等于1时递归终止</p>
<p>def merge(left, right):
"""
合并两个已排序的子数组
参数left: 左侧已排序数组
参数right: 右侧已排序数组
返回: 合并后的一个有序数组
"""</p>
<h1>--- 测试与对比部分 ---</h1>
<p>def measure_performance(sort_func, data):
start_time = time.perf_counter_ns()
sort_func(data.copy())
end_time = time.perf_counter_ns()
return (end_time - start_time) / 10**6</p>
<p>network_sizes = [1000, 5000, 10000, 50000]
print("算法性能对比测试:")
for size in network_sizes:
# 生成逆序数据,这是插入排序的最坏情况
worst_case_data = list(range(size, 0, -1))</p>
<pre><code>time_insertion = measure_performance(insertion_sort, worst_case_data)
time_merge = measure_performance(merge_sort, worst_case_data)
print(f"--- 网络规模 n={size} (最坏情况) ---")
print(f" - 插入排序: {time_insertion:.2f} ms")
print(f" - 归并排序: {time_merge:.2f} ms")
</code></pre>
<p>```</p>
<h5>分析与讨论</h5>
<p>完成编程并得到输出后请与右侧Agent讨论以下问题</p>
<ol>
<li>
<p><strong>性能验证</strong>:观察“交通大堵塞”(最坏情况)的测试结果,归并排序的性能表现与插入排序有何天壤之别?这是否验证了你在第一关的理论分析?</p>
</li>
<li>
<p><strong>性能稳定性</strong>:如果我们将测试数据换成“畅通无阻”(最好情况)或“随机车流”(平均情况),你认为归并排序的运行时间会发生巨大变化吗?为什么?</p>
</li>
<li>
<p><strong>空间成本</strong>:在实现 <code>merge</code> 函数时,你可能创建了一个新的数组 <code>merged</code> 来存放结果。这在算法分析中被称为“空间复杂度”。与在原数组上进行交换的插入排序相比,归并排序的这个特点是优点还是缺点?</p>
</li>
<li>
<p><strong>最终决策</strong>:作为项目工程师,你会选择哪种排序算法用于我们的大规模交通调度系统?请综合考虑<strong>时间效率</strong><strong>空间成本</strong>来陈述你的理由。</p>
</li>
</ol>
</body>
</html>