数学与计算机学院 程序设计 实验报告
年级 11级数电二班 学号2011435058 姓名魏珊珊 成绩______
专业 电气信息类计算机类 实验地点 主楼402 指导教师 石强实验题目学习数组
日期 2012年5月8日
一、实验目的
学会向数组中插入某个数;对于幻方有一定的了解,会用二维数组解决幻方问题;培养培养细心和耐心。
二、实验问题描述
(1)输入一串数字,排好序后,再输入一个数,要求按原来排序规律将它插入数列中(用数组做)
(2)编一个函数,函数的参数是整数n,函数输出1~n^2的自然数组成的魔方
三、实验问题分析
算法:
(1)法一:先将数字存入一个一维数组中,然后用冒泡法将其从小到大排序;再输入想要插入的数n,将n以此与数组元素比较,如果找到比n大的数,比如a[i],将i以后的数组元素整体向后挪移(当然,定义的数组的长度要比数字串要长些),然后再将n赋给a[i]。最后输出插入后的数组就行了。
法二:直接将n插入原数组,然后用冒泡法对数组重新排序一遍,不过这种算法有点简单,跟书上的例题一样。
(2)具体的解法和算法都包含在代码中的注释中了,参见代码和最后的总结。
四、实验结果(程序)及分析
以下是代码跟注释:
(1) 法一:
#include<iostream.h>
#define size 30
int main()
{
cout<<"请输入原数组的元素个数:";
int m; //m为原数组的元素个数,m应该小于size
while(cin>>m&&m<size)
{
int s[size]={0},n,k=0,p;
cout<<"Please input the digitals:";
for(int i=0;i<m;i++)
cin>>s[i];
//将数组进行从小到大排序
for(int i=0;i<m;i++)
for(int j=i+1;j<m;j++)
if(s[i]>s[j])
{
int hold;
hold=s[i];
s[i]=s[j];
s[j]=hold;
}
//输出排序后的结果
cout<<"\nAfter sorting:";
for(int i=0;i<m;i++)
cout<<" "<<s[i];
cout<<"\nInput the digital you want to insect:";
cin>>n;
//逐个验证,直到找到比n大的数
for(int i=0;i<m;i++)
{
if(s[i]>=n)
{
p=i; //为了方便将n赋给a[i],将i的值暂存入p中
break;
}
k++; //k用来计数,便于下面将n插入数组
}
if(k==m)
s[m]=n;
else
{
for(int j=m-1;j>=p;j--)
s[j+1]=s[j]; //将"i"值以后的数组元素整体向后挪一位
s[p]=n;
}
cout<<"\nAfter insecting :"; //输出插入后结果
for(int i=0;i<=m;i++)
cout<<" "<<s[i];
cout<<endl;
cout<<"请输入原数组的元素个数:"; //进入下一组测试
}
return 0;
}
法二:
#include<iostream.h>
#define size 30
int main()
{
cout<<"请输入原数组的元素个数:";
int m; //m为原数组的元素个数,m应该小于size
while(cin>>m&&m<size)
{
int s[size]={0},n; //n为要插入的数
cout<<"Please input the digitals:";
for(int i=0;i<m;i++)
cin>>s[i];
cout<<"Please input the digital you want to insect:";
cin>>n;
s[m]=n;
//将插入n后的数组重新排列
for(int i=0;i<=m;i++)
for(int j=i+1;j<=m;j++)
if(s[i]>s[j])
{
int hold;
hold=s[i];
s[i]=s[j];
s[j]=hold;
}
//输出排序后的结果
cout<<"\nAfter sorting:";
for(int i=0;i<=m;i++)
cout<<" "<<s[i];
cout<<endl;
cout<<"请输入原数组的元素个数:";
cin>>n;
}
return 0;
}
(2)幻方代码:
#include<iostream.h>
#include<conio.h>
#define max 50
#define size 15
int test____print(int matrix[max][max],int order);
void test__print(int matrix[max][max],int matrixA[max][max],int matrixB[max][max],int matrixC[max][max],int matrixD[max][max],int ord);
void jishujie(int matrix[max][max],int x,int y,int ord);
int main()
{
int order;
cout<<"请输入阶数:";
while(cin>>order)
{
//奇数阶算法
/******************************************************************************
奇数阶幻方最经典的填法是罗伯法。填写的口诀:
1居首行正中央,
依次右上莫相忘。
上出格时往下放,
右出格时往左放。
排重便往自下放,
右上出格一个样。
******************************************************************************/
if(order%2==1)
{
int matrix[max][max]={0},count,row=0,coclum=order/2;
for(count=1;count<=order*order;count++)
{
matrix[row][coclum]=count;
if(count%order==0)
row++;
else
{
row=(row==0)? order-1:row-1;
coclum=(coclum==order-1)? 0:coclum+1;
}
}
int m=0;
for(int i=0;i<order;i++)
for(int j=0;j<order;j++)
{
m++;
cout<<matrix[i][j]<<"\t";
if(m%order==0)
cout<<endl<<endl;
}
cout<<"请输入阶数:";
}
//双偶数的算法
/****************************************************************************** 所谓双偶阶幻方就是当n可以被4整除时的偶阶幻方,即4K阶幻方。在说解法之前我们先说明一个"互补数"定义:就是在n阶幻方中,如果两个数的和等于幻方中最大的数与1的和(即n×n+1),我们称它们为一对互补数。如 在三阶幻方中,每一对和为10的数,是一对互补数 ;在四阶幻方中,每一对和为17的数,是一对互补数。 双偶数阶幻方最经典的填法是海尔法。填写的方法是: 以八阶幻方为例 :
先写出顺序数组 :
1 2 3 4 |5 6 7 8
9 10 11 12 |13 14 15 16
17 18 19 20 |21 22 23 24
25 26 27 28 |29 30 31 32
------------------------------------------------------------>
33 34 35 36 |37 38 39 40
41 42 43 44 |45 46 47 48
49 50 51 52 |53 54 55 56
57 58 59 60 |61 62 63 64
然后平均划分成4份,类似直角坐标系,然后使每个小方阵的对角线元素换成它的互补数
(互补数为:数组最大数加一 如:8*8+1=65)
64 2 3 61 |60 6 7 57
A 9 55 54 12 |13 51 50 16 B
17 47 46 20 |21 43 42 24
40 26 27 37 |36 30 31 33
--------------------------------------------------->
32 34 35 29 |28 38 39 25
C 41 23 22 44 |45 19 18 48
49 15 14 52 |53 11 10 56 D
8 58 59 5 |4 62 63 1
以八阶幻方为例 :
先写出顺序数组 :
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
然后平均划分成4份,类似直角坐标系,然后使每个小方阵的对角线元素换成它的互补数
(互补数为:数组最大数加一 如:8*8+1=65)
64 2 3 61 |60 6 7 57
A 9 55 54 12 |13 51 50 16 B
17 47 46 20 |21 43 42 24
40 26 27 37 |36 30 31 33
-------------------------|--------------------à
32 34 35 29 |28 38 39 25
C 41 23 22 44 |45 19 18 48
49 15 14 52 |53 11 10 56 D
8 58 59 5 |4 62 63 1
|
***************************************************************************/
if(order%4==0) //双偶
{
int matrix[max][max];
int m=1+order*order,count=1;
for(int row=0;row<order;row++)
for(int coclum=0;coclum<order;coclum++)
matrix[row][coclum]=count++;
if(order==4)
{
for(int i=0,j=0,p=0,k=3,n=0;n<4;n++)
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
test____print(matrix,order);
cout<<"请输入阶数:";
}
else
{
for(int i=0,j=0,p=0,k=order/2-1,n=0;n<order/2;n++) //A部分
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
for(int i=0,j=order/2,p=0,k=order-1,n=0;n<order/2;n++)//B部分
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
for(int i=order/2,j=0,p=order/2,k=order/2-1,n=0;n<order/2;n++) //C部分
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
for(int i=order/2,j=order/2,p=order/2,k=order-1,n=0;n<order/2;n++) //D部分
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
test____print(matrix,order);
cout<<"请输入阶数:";
}
}
/* ***************************************************************************** 单偶数阶幻方(斯特拉兹法)
所谓单偶阶幻方就是当n不可以被4整除时的偶阶幻方,即4K+2阶幻方。如(n=6,10,14……)的幻方。
单偶数阶幻方最经典的填法是斯特拉兹法。填写的方法是:
以10阶幻方为例。这时,k=2。
(1)把魔方阵分为A,B,C,D四个象限,这样每一个象限肯定是奇数阶。
用罗伯法,依次在A象限,D象限,B象限,C象限按奇数阶幻方的填法填数。
17 24 1 8 15 |67 74 51 58 65
23 5 7 14 16 |73 55 57 64 66
4 6 13 20 22 |54 56 63 70 72
10 12 19 21 3 |60 62 69 71 53
11 18 25 2 9 |61 68 75 52 59
-------------------------------------------->
92 99 76 83 90 |42 49 26 33 40
98 80 82 89 91 |48 30 32 39 41
79 81 88 95 97 |29 31 38 45 47
85 87 94 96 78 |35 37 44 46 28
86 93 100 77 84 |36 43 50 27 34
|
(2)在A象限的中间行、中间格开始,按自左向右的方向,标出k格。
A象限的其它行则标出最左边的k格。将这些格,和C象限相对位置上的数互换位置。
92 99 1 8 15 |67 74 51 58 65
98 80 7 14 16 |73 55 57 64 66
4 6 88 95 22 |54 56 63 70 72
85 87 19 21 3 |60 62 69 71 53
86 93 25 2 9 |61 68 75 52 59
------------------------------------------------->
17 24 76 83 90 |42 49 26 33 40
23 5 82 89 91 |48 30 32 39 41
79 81 13 20 97 |29 31 38 45 47
10 12 94 96 78 |35 37 44 46 28
11 18 100 77 84 |36 43 50 27 34
(3)在B象限所有行的中间格,自右向左,标出k-1格。
(注:6阶幻方由于k-1=0,所以不用再作B、D象限的数据交换),将这些格,和D象限相对位置上的数互换位置。
92 99 1 8 15 |67 74 26 58 65
98 80 7 14 16 |73 55 32 64 66
4 6 88 95 22 |54 56 38 70 72
85 87 19 21 3 |60 62 44 71 53
86 93 25 2 9 |61 68 50 52 59
--------------------------------------------------------->
17 24 76 83 90 |42 49 51 33 40
23 5 82 89 91 |48 30 57 39 41
79 81 13 20 97 |29 31 63 45 47
10 12 94 96 78 |35 37 69 46 28
11 18 100 77 84 |36 43 75 27 34
****************************************************************************/
if(order%2==0&&order%4!=0) //单偶数
{
int matrixA[max][max],matrixB[max][max],matrixC[max][max],matrixD[max][max],
matrix[max][max];
int a[size][size],b[size][size],c[size][size],d[size][size];
//将每个象限的数组变成奇数阶
jishujie(matrixA,1,order*order/4,order/2);
jishujie(matrixB,1+order*order/2,order*order*3/4,order/2);
jishujie(matrixC,1+order*order*3/4,order*order,order/2);
jishujie(matrixD,1+order*order/4,order*order/2,order/2);
int k=(order-2)/4;
if(k==1)
{
//从A象限中间行中间格开始,按自左向右的方向,标出K格。A象限的其他行则标出最左行的K格,与C相同位置的数进行互换
for(int i=0;i<order/2;i++) //把A,C象限需要交换的数保留起来
for(int j=0;j<k;j++)
{
if(i==order/4)
{
for(int p=order/4,r=0;r<k;r++,j++,p++) //r用来控制循环次数
{
a[i][j]=matrixA[i][p];
c[i][j]=matrixC[i][p];
}
break;
//终止内循环,开始下一次外循环. 且i自增1,即从order/4+1开始
}
else
{
a[i][j]=matrixA[i][j];
c[i][j]=matrixC[i][j];
}
}
for(int i=0;i<order/2;i++) //交换AC象限的数
for(int j=0;j<k;j++)
{
if(i==order/4)
{
for(int p=order/4,r=0;r<k;r++,j++,p++)
{
matrixA[i][p]=a[i][j];
matrixC[i][p]=c[i][j];
}
break; //终止内循环,开始下一次外循环. 且i自增1,即从order/4+1开始
}
else
{
matrixA[i][j]=c[i][j];
matrixC[i][j]=a[i][j];
}
}
test__print(matrix,matrixA,matrixB,matrixC,matrixD,order);
cout<<"请输入阶数:";
}
else
{
//从A象限中心的数 向右标出K格,与C相同位置的数进行交换
for(int i=0;i<order/2;i++) //把A,C象限需要交换的数保留起来
for(int j=0;j<k;j++)
{
if(i==order/4)
{
for(int p=order/4,r=0;r<k;r++,j++,p++) //r用来控制循环次数
{
a[i][j]=matrixA[i][p];
c[i][j]=matrixC[i][p];
}
break; //终止内循环,开始下一次外循环. 且i自增1,即从order/4+1开始
}
else
{
a[i][j]=matrixA[i][j];
c[i][j]=matrixC[i][j];
}
}
for(int i=0;i<order/2;i++) //交换AC象限的数
for(int j=0;j<k;j++)
{
if(i==order/4)
{
for(int p=order/4,r=0;r<k;r++,j++,p++)
{
matrixA[i][p]=a[i][j];
matrixC[i][p]=c[i][j];
}
break; //终止内循环,开始下一次外循环. 且i自增1,即从order/4+1开始
}
else
{
matrixA[i][j]=c[i][j];
matrixC[i][j]=a[i][j];
}
}
//交换BD象限的数
for(int i=0;i<order/2;i++) //把BD象限需要交换的数保留起来
for(int j=order/4;j>1;j--)
{
b[i][j]=matrixB[i][j];
d[i][j]=matrixD[i][j];
}
for(int i=0;i<order/2;i++) //交换BD象限的数
for(int j=order/4;j>1;j--)
{
matrixB[i][j]=d[i][j];
matrixD[i][j]=b[i][j];
}
test__print(matrix, matrixA, matrixB,matrixC,matrixD,order);
cout<<"请输入阶数:";
}
}
}
getch();
return 0;
}
int test____print(int matrix[max][max],int order) //双偶数的输出函数
{
int m=0;
for(int i=0;i<order;i++)
for(int j=0;j<order;j++)
{
m++;
cout<<matrix[i][j]<<"\t";
if(m%order==0)
cout<<endl<<endl;
}
cout<<endl;
}
void jishujie(int matrix[max][max],int x,int y,int ord) //将单偶数每个象限的数奇数阶化
{
int row=0,coclum=ord/2;
for(int count=x;count<=y;count++)
{
matrix[row][coclum]=count;
if(count%ord==0)
row++;
else
{
row=(row==0)? ord-1:row-1;
coclum=(coclum==ord-1)? 0:coclum+1;
}
}
}
//将ABCD四个象限的数付给数组matrix[][],使得单偶数以矩阵的形式输出
void test__print(int matrix[max][max],int matrixA[max][max],int matrixB[max][max],int matrixC[max][max],int matrixD[max][max],int ord)
{
for(int i=0;i<ord/2;i++) //将A象限的数付给matrix[][]的第一个1/4
for(int j=0;j<ord/2;j++)
matrix[i][j]=matrixA[i][j];
for(int i=0,m=0;i<ord/2;i++,m++) //将B象限的数付给matrix[][]第二个的1/4
for(int j=ord/2,n=0;j<ord;j++,n++)
matrix[i][j]=matrixB[m][n];
for(int i=ord/2,m=0;i<ord;i++,m++) //将C象限的数付给matrix[][]的第三个1/4
for(int j=0,n=0;j<ord/2;j++,n++)
matrix[i][j]=matrixC[m][n];
for(int i=ord/2,m=0;i<ord;i++,m++) //将D象限的数付给matrix[][]的第四个1/4
for(int j=ord/2,n=0;j<ord;j++,n++)
matrix[i][j]=matrixD[m][n];
int m=0;
for(int i=0;i<ord;i++)
for(int j=0;j<ord;j++)
{
m++;
cout<<matrix[i][j]<<"\t";
if(m%ord==0)
cout<<endl<<endl;
}
}
对于幻方的总结:
我觉的这个题考察的主要是细心和一定的分析能力,而且被人的代码几乎看不懂,只有自己写的代码自己记忆才深刻,对于奇数阶幻方用三目运算符特简单,其实找到奇数阶排列规律后,还有更简单的方法,网上有位大牛直接用
for(n2=n^2,n1=0;n1<n2;n1++) //n为阶数
matrix[(n1*(n-1)+(n1/n)*2)%n][(n1+(n>1)-n1)/n]=n1+1;没看懂,还是用的我的笨方法
对于双偶幻方,要分阶数等于4和阶数大于4两种情况,对于大于4的情况,交换小矩阵对角线元素就行;对于单偶数,对于每个象限进行奇数阶化,(注意6阶的BD象限不交换)剩下的就是数的交换问题了,细点心就能做对的。我认为我是个挺粗心的人,通过这个题我认识到了粗心对于程序的危害极深那,差不多思考了一个星期才把这道题完整的敲出来,以后一定要细心。一定要认真!