分治与减治算法实验:题目1 数字旋转方阵程序设计

实验时间

2024年 4 月10日19时至22时

学时数

3

1.实验名称

分治与减治算法实验:题目1 数字旋转方阵程序设计

2.实验目的

(1)掌握分治法的设计思想;

(2)掌握数字旋转方阵的具体实现过程;

(3)熟练掌握二维数组的使用方法;

(4)在掌握的基础上编程实现数字旋转方阵的实现过程。

3.实验内容

给出一个初始数据,在此数据的基础上由外层向里层填写数据,完成一个数字旋转方阵,输出结果,输出时要求有文字说明。请任选一种语言编写程序实现上述算法,并分析其算法复杂度。

  1. 实验原理

用二维数组data[N][N]表示N×N的方阵,观察方阵中数字的规律,可以从外层向里层填数,如图所示。在填数过程中,每一层的起始位置很重要。设变量size表示方阵的大小,则初始时size=N,填完一层则size=size-2;设变量begin表示每一层的起始位置,变量i和j分别表示行号和列号,则每一层初始时i=begin,j=begin。将每一层的填数过程分为A、B、C和D四个区域,则每个区域需要填写size-1个数字,填写区域A时列号不变行号加1,填写区域B时行号不变列号加1,填写区域C时列号不变行号减1,填写区域D时行号不变列号减1。显然,递归的结束条件是size等于0或size等于1。

                     

9.实验源代码和伪代码

伪代码:

设递归函数Full实现填数过程,算法用伪代码描述如下。(这里只展示Full函数伪代码)

算法 数字旋转方阵 Full

输入:  当前层左上角要填的数字 number, 左上角的坐标 begin,方阵的阶数 size

输出:  data[i][j]

1:  if size == 0 then

2:          return 3:  end if

4:  if size == 1 then

5:          data[begin][begin] ← number

6:  end if

7:  else

8:    i ← begin 9:  j ← begin

10:    for k ← 0 to size − 2 do

11:           data[i][j] ← number //在当前位置填写 number

12:            number + +

13:            i + +

14:    end for

15:    for k ← 0 to size − 2 do

16:           data[i][j] ← number //在当前位置填写 number

17:            number + +

18:            j + +

19:    end for

20:    for k ← 0 to size − 2 do

21:           data[i][j] ← number //在当前位置填写 number

22:            number + +

23:            i − −

24:    end for

25:    for k ← 0 to size − 2 do

26:           data[i][j] ← number //在当前位置填写 number

27:            number + +

28:            j − −

29:    end for

30:  end if

31:  Full(number, begin + 1, size − 2)

设递归函数Full实现填数过程,算法用伪代码描述如下。(这里只展示Full函数伪代码)

由于递归函数Full在调用过程中需要对同一个数组data[N][N]墙数,为避免传递参数,将数组data[N][N]设为全局变量,算法用C++语言描述如下:

#include <stdio.h>
#include <iostream>

using namespace std;

int data [100][100];
void Full(int number, int begin, int size) {
    //从number开始填写size阶方阵,左上角的下标为(begin,begin)
    int i, j, k;
    if (size == 0)     //递归的边界条件,如果size等于0,则无须填写
        return;
    if (size == 1) {    //递归的边界条件,如果size等于1
        data[begin][begin] = number; //则只须填写number
        return;
    }

    i = begin;
    j = begin;    //初始化左上角下标
    for (k = 0; k < size - 1; k++) {    //填写区域A,共填写size-1个数
        data[i][j] = number;    //在当前位置填写number
        number++;
        i++;//行下标加1
    }
    for ( k = 0; k  < size - 1; k++) { //填写区域 B,共填写 size-1个数
        data[i][j] = number;//在当前位置填写number
        number++;
        j++;//列下标加1
    }
    for ( k = 0; k < size - 1; k++) { //填写区域 C,共填写size- 1个数

        data[i][j] = number;//在当前位置填写 number
        number++;
        i--;//行下标减1
    }
    for ( k = 0; k < size - 1; k++) { //填写区域D,共填写size- 1个数
        data[i][ j] = number;//在当前位置填写 number
        number ++;
        j --;//列下标减1
    }
    Full( number, begin + 1, size - 2); //递归求解,左上角下标为 begin+1
}

int main() {
    int number, begin, size;
    cout << "请输入数字矩阵的起始数字,左上角坐标和阶数: " << endl;
    cin >> number >> begin >> size;
    Full(number, begin, size);
    cout << "数字矩阵效果展示:" << endl;
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            cout << data[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

时间复杂度分析:

假设要填写n阶数字旋转方阵,算法Full需要先填写A、B、C和D四个区域,由4个并列的循环组成,每个循环均执行n—1次,然后执行递归调用,填写n-2阶方阵,因此,该算法满足如下递推关系式:

不失一般性,假设n为偶数,用扩展递归技术解此递推式,得

T(n)=T(n-2)+4(n-1)=T(n-4)+4(n-3)+4(n-1)

=T(0)+…+4(n-5)+4(n-3)+4(n-1)

=O(n2)

  1. 实验结论及心得

代码运行截图:

心得:

分治是一种将大问题划分为小问题的求解思路,递归是程序的写法,也就是方法(分治)的方法。

  • 24
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值