结构化设计与八皇后问题求解
立即解锁
发布时间: 2025-08-16 00:06:03 阅读量: 5 订阅数: 16 


软件开发的艺术:从设计到编码的全面指南
### 结构化设计与八皇后问题求解
#### 1. 结构化编程的起源
结构化设计起源于Edsger Dijkstra在1968年发表的著名信件《Go To Statement Considered Harmful》。在这篇文章中,Dijkstra指出“goto”语句过于原始,容易让程序变得混乱。之后的编程语言虽然没有完全摒弃“goto”语句(Java除外),但都降低了它的使用频率。编程课程也鼓励学生避免使用“goto”语句,转而采用自顶向下的结构化方式解决问题,即从问题描述出发,将问题分解为一系列可解决的子问题,直到每个子问题都足够简单。在20世纪80年代中期面向对象编程出现之前,结构化编程是解决问题和编程的标准方法,并且至今仍是解决许多问题的优秀方法之一。
#### 2. 逐步细化设计方法
Niklaus Wirth在1971年的论文《Program Development by Stepwise Refinement》中正式提出了结构化设计技术——逐步细化。该方法认为程序设计由一系列细化步骤组成,每个步骤将一个任务分解为多个子任务,同时要对数据描述和接口进行相应细化。程序的模块化程度决定了其适应需求或环境变化的难易程度。
在细化过程中,应使用适合问题空间的符号,尽量避免使用编程语言进行描述。每次细化都基于一组设计标准做出设计决策,这些标准包括时间和空间效率、清晰度以及结构规则性(简单性)。
细化可以采用两种方式:
- **自顶向下细化**:从问题的总体描述逐步细化到各个模块或例程的详细说明。其指导原则是人类一次只能专注处理少数事情,即Miller提出的7 ± 2数据块规则。具体操作步骤如下:
1. 分析问题,确定解决方案的轮廓以及各种可能性的优缺点。
2. 先设计顶层结构。
3. 避免涉及特定语言的细节。
4. 将细节逐步下推到较低层次。
5. 对每个层次进行形式化。
6. 验证每个层次。
7. 进入下一个较低层次进行下一轮细化。
持续细化解决方案,直到编码比分解更容易为止,但何时停止细化并没有明确的衡量标准,需要通过实践来掌握。
- **自底向上细化**:如果无法从顶层开始,可以从底层入手。具体步骤如下:
1. 思考系统需要完成的底层操作,如输入输出操作、数据结构的底层操作等。
2. 尽可能识别出更多的底层函数和组件。
3. 找出底层组件的共同特征并进行分组。
4. 继续向上推进到下一个层次,或者回到顶层再次尝试自顶向下的方法。
自底向上评估通常能早期识别出实用例程,有助于实现更紧凑的设计和促进代码复用,但很难单独使用,通常在某个阶段需要切换到自顶向下的方法。大多数实际的逐步细化过程都涉及自顶向下和自底向上设计元素的交替使用,这两种方法具有很强的互补性。
#### 3. 逐步细化的示例:八皇后问题
八皇后问题是一个经典问题,要求在一个标准的8×8棋盘上放置八个皇后,使得任意两个皇后都不能相互攻击。由于皇后可以在水平、垂直和对角方向上移动任意格数,目前尚未找到该问题的解析解。下面介绍几种解决该问题的方案:
##### 3.1 方案一:暴力求解
可以考虑使用暴力方法,尝试所有可能的皇后排列组合,然后选择符合条件的解。8个皇后在64个方格中有$C_{n}^{k}$种可能的棋盘配置(其中n为棋盘方格数,k为皇后数),即$C_{64}^{8}=4294967296$种配置。在现代计算机的处理能力下,这个数量不算太多,因此暴力求解是一种可行的方法。
具体实现步骤如下:
1. 生成所有可能的棋盘组合集合A。
2. 创建一个测试函数q(x),如果棋盘配置x是一个解,则返回true,否则返回false。
3. 编写程序:
```plaintext
Generate the set A of all board configurations;
while there are still untested configurations in A do
x = the next configuration from A
if (q(x) == true) then print the solution x and stop
go back to the top and do it again.
```
这种分解方法虽然可行,但效率不高,我们希望减少组合数量以提高效率。
##### 3.2 方案二:限制列的选择
通过分析问题,我们发现每列最多只能放置一个皇后,实际上每列必须放置一个皇后。这样可以将可能的组合数量减少到$2^{24}=16777216$种。
具体实现步骤如下:
1. 生成受限的棋盘配置集合B,其中每列有一个皇后。
2. 同样使用测试函数q(x)。
3. 编写程序:
```plaintext
Generate the set B of restricted board configurations;
while there are still untested configurations in B do
x = the next configuration from B
if (q(x) == true) then print the solution x and stop
go back to the top and do it again.
```
这种方法虽然减少了组合数量,但生成集合B比生成集合A更复杂,因为需要检查每个棋盘位置是否满足每列一个皇后的限制。因此,我们需要寻找更高效的方法。
##### 3.3 方案三:生成并测试部分解
我们可以更智能地生成棋盘配置,并在生成过程中对部分解进行测试。如果发现某个部分解无效,就立即停止并回溯到上一个有效的部分解,这样可以更快地排除无效配置。
具体细化步骤如下:
- **细化1**:
1. 在下一个可用列的下一行放置一个皇后。
2. 测试该皇后是否能攻击其他皇后(类似于前面的q(x)测试)。
3. 如果能攻击,将该皇后拿起,回溯到上一个试验解并再次尝试。
4. 如果不能攻击,保留该皇后并回到顶部尝试下一个皇后。
以下是使用伪代码实现的寻找单个解的算法:
```plaintext
do {
while ((row < 8) && (col < 8)) {
if (the current queen is safe) then
advance: keep the queen on the board and advance to the next column
else
the queen is not safe, so
```
0
0
复制全文
相关推荐










