实验报告
实验名称:(一)魔方阵(二)本科生导师制问题 实验类型:设计性实验 班级:20100631 学号:2010063114 姓名:万星含 (一)魔方阵 1.问题描述
魔方阵是一个古老的智力问题,它要求在一个m×m的矩阵中填入1~m2的数字(m为奇数),使得每一行、每一列、每条对角线的累加和都相等,如图1所示。
②基本要求
?输入魔方阵的行数m,要求m为奇数,程序对所输入的m作简单的判断,
如m有错,能给出适当的提示信息。 ?实现魔方阵。 ?输出魔方阵。 ③实现提示
本实验使用的数据结构是数组。
解魔方阵问题的方法很多,这里采用如下规则生成魔方阵。 ?由1开始填数,将1放在第0行的中间位置。
?将魔方阵想象成上下、左右相接,每次往左上角走一步,会有下列情况:
?左上角超出上方边界,则在最下边相对应的位置填入下一个数字; ?左上角超出左边边界,则在最右边相应的位置填入下一个数字; ?如果按上述方法找到的位置已填入数据,则在同一列下一行填入下一
个数字。
以3×3魔方阵为例,说明其填数过程,如图2所示。
由三阶魔方阵的生成过程可知,某一位置(x,y)的左上角的位置是(x-1,y-1),如果x-1≥0,不用调整,否则将其调整为x-1+m;同理,如果y-1≥0,不用调整,否则将其调整为y-1+m。所以,位置(x,y)的左上角的位置可以用求模的方法获得,即:
x=(x-1+m)%m y=(y-1+m)%m
如果所求的位置已经有数据了,将该数据填入同一列下一行的位置。这里需要注意的是。此时的x和y已经变成之前的上一行上一列了,如果想变回之前位置的下一行同一列,x需要跨越两行,y需要跨越一列,即:
x=(x+2)%m y=(y+1)%m ④思考
?可以考虑使用其他方法生成魔方阵。任何算法都有不同的实现方法,通过
采用不同实现方法来重新实现算法,这要比单纯学习算法的效果好得多。
2.实验要求
(1) 认真阅读和掌握和本实验相关的教材内容、算法和设计程序。 (3) 上机运行程序。
(4) 保存和打印出程序的运行结果,并结合程序进行分析。
3.实验目的
(1)设计数据结构;
(2)设计算法完成任意n阶魔方阵的填数; (3)分析算法的时间复杂度。
4.程序源代码
#include #include #define
MAX_NUM
500
/*
这
里
可
以
修
改
最
大
*/
int { int int int int // for for // while { printf(\ scanf(\ if { rows break; } else printf(\ } } // center
iArray[0][center] // okNum RowSet LineSet // while { if { RowSet } else
+=
(
RowSet
==
0
&&
LineSet
==
rows
(
set okNum
<
each
(rows
+
item 1)
*
in (rows
+
=
initialize
the
okNum,
= =
RowSet
and
= set
rows
=
number
/
行
数
必
须
在
0
和
%d
之
间
,
请
重
新
\
-=
(
rows
<=
MAX_NUM
输
入
行
数
get
(
the
rows 1
set ( (
the i j
items = =
0; 0;
of
i j
= array
< <
\
to
be i++ j++
rows RowSet
= i = 0,
0, LineSet
= okNum
center =
0,
= 0,
0,
main()
iArray[MAX_NUM][MAX_NUM]; = j =
0,
newLineSet
=
=
0; 0; 0; 0 ) ) 0; number
) :\\n\ &rows);
) 1;
newRowSet
MAX_NUM; MAX_NUM;
iArray[i][j]
{
MAX_NUM);
'1' 2; 1; LineSet
1; 0; center; \ 1)
) ) 1; {
newRowSet newLineSet if // { RowSet //RowSet } else{ RowSet LineSet } }
= (
= =
(RowSet (LineSet
== ==
0) rows)
? ?
rows 0
: : !=
RowSet LineSet
0
number
- +
1; 1; ) here!
iArray[newRowSet][newLineSet]
is
(RowSet
==
already rows)
+=
?
a 0
there
: RowSet + 1; 1;
= =
newRowSet; newLineSet;
iArray[RowSet][LineSet] } // for { for
(
j
=
0;
j
(
i
print =
0;
i
= ++okNum;
the <= <=
rows; rows;
i++ j++
\
) )
printf(\ printf(\ }
system(\ return }
iArray[i][j]);
0;
6.调试结果
(二)本科生导师制问题 1.问题描述
在高校的教学改革中,有很多学校实行了本科生导师制。一个班级的学生被分给几个老师,每个老师带n个学生,如果该老师还带研究生,那么研究生也可直接带本科生。本科生导师制问题中的数据元素具有如下形式:
?导师带研究生
(老师,((研究生1,(本科生1,?,本科生m1)),(研究生2,(本科生1,?,本科生m2))?)) ?导师不带研究生
(老师,(本科生1,?,本科生m))
导师的自然情况只包括姓名、职称;研究生的自然情况只包括姓名、班级;本科生的自然情况只包括姓名、班级。
②基本要求
要求完成以下功能:
?建立:建立导师广义表。
?插入:将某位本科生或研究生插入到广义表的相应位置。 ?删除:将某本科生或研究生从广义表中删除。 ?查询:查询导师、本科生(研究生)的情况。 ?统计:某导师带了多少个研究生和本科生。 ?输出:将某导师所带学生情况输出。 ?退出:程序结束。
2.设计思路
本实验使用的数据结构是广义表,广义表采用头尾链表存储结构来实现。 定义教师、学生结点结构体如下:
typedef struct GLNode {
char name[100]; /*教师或学生的姓名*/
char prof[100]; /*教师结点表示职称,学生结点表示班级*/ int type; /*结点类型:0-教师,1-研究生,2-本科生*/
struct {struct GLNode *hp, *tp;} ptr;
/*hp指向同级的下一结点,tp指向下级的首结点*/ }GList;
人员信息的表示形式为:高老师-教授-0、李刚-二班-1、李明-二班-2. 人员信息中的姓名、职称、班级、人员类型用“-”隔开,如高老师-教授-0,“高老师”表示姓名,“教师”表示职称,“0”表示人员的类型是教师;李刚-二班-1,“李刚”表示姓名,“二班”表示班级,“1”表示人员的类型是研究生;李明-二班-2,“李明”表示姓名,“二班”表示班级,“2”表示人员的类型是本科生。
广义表((高老师-教授-0,(李明-一班-2,王平-二班-2)),(李老师-副教授-0,(白梅-二班-1,(李刚-一班-2)))可以用图3表示。