实验报告<幻方,数组的排序和向数组中插入某个数>

数学与计算机学院 程序设计 实验报告

年级 11级数电二班 学号2011435058  姓名魏珊珊 成绩______

专业 电气信息类计算机类 实验地点 主楼402  指导教师 石强实验题目­­学习数组

日期 201258

一、实验目的

学会向数组中插入某个数;对于幻方有一定的了解,会用二维数组解决幻方问题;培养培养细心和耐心。

二、实验问题描述

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象限不交换)剩下的就是数的交换问题了,细点心就能做对的。我认为我是个挺粗心的人,通过这个题我认识到了粗心对于程序的危害极深那,差不多思考了一个星期才把这道题完整的敲出来,以后一定要细心。一定要认真!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值