现在的位置: 首页 > 综合 > 正文

常见算法和数据结构集合

2014年01月20日 ⁄ 综合 ⁄ 共 7740字 ⁄ 字号 评论关闭

巧填奇数阶幻方(魔方阵)[转]

一、什么叫幻方?
(通俗点说)把一些有规律的数填在纵横格数都相等的正方形图内,使每一行、每一列和每一条对角线上各个数之和都相等。这样的方阵图叫做幻方。
幻方又分为奇数阶幻方和偶数阶幻方。奇数阶幻方是指横行、竖列都是单数(即3、5、7、9……)的方阵图。偶数阶幻方是指横行、竖列都是双数(即4、6、8、10……)的方阵图。
二、奇数阶幻方的填法。
奇数阶幻方中最简便的一种就是三阶幻方,又称“九宫图”。
平常我们遇到这类题都是用分析、分组、尝试的方法推出,这种方法较麻烦,如果是五阶幻方、七阶幻方就更困难了。
有一种方法不仅能很快地填出三阶幻方,还能很快地填出五阶幻方、七阶幻方、九阶幻方……那就是“口诀法”
口 诀
“1”坐边中间,斜着把数填;
出边填对面,遇数往下旋;
出角仅一次,转回下格间。
注意:
(1)这里的“1”,是指要填的这一列数中的第一个数。
(2)“1”坐边中间,指第一个数要填在任何一边的正中间的空格里。
(3)从1到2时,必须先向边外斜(比如:第一个数填在上边的正中间,填第二个数时,要向左上方或右上方斜),填后面的数时也要按照同样的方向斜。

一) 大数阶乘

/*时间限制:3000 ms  |  内存限制:65535 KB
难度:3
描述 
我们都知道如何计算一个数的阶乘,可是,如果这个数很大呢,我们该如何去计算它并输出它? 
输入 
输入一个整数m(0<m<=5000) 
输出 
输出m的阶乘,并在输出结束之后输入一个换行符 
样例输入 
50
样例输出 

30414093201713378043612608166064768844377641568960512000000000000
*/
#include<stdio.h>  
#define MAXLEN 100000  
int Factorial(int n,int a[]){  
    int sum,i,j,temp;  
    sum=0;//最高位下标;  
    a[0]=1;  
    for(i=1;i<MAXLEN;i++){  
        a[i]=0;  
    }  
    for(i=2;i<=n;i++){  
        for(j=0;j<=sum;j++){  
            a[j]*=i;  
        }  
        for(j=0;j<sum;j++){  
            temp=a[j];  
            a[j]=temp%10;//本位数值;  
            a[j+1]+=temp/10;//进位;  
        }  
        while(a[sum]>9){  
            temp=a[sum];  
            a[sum]=temp%10;  
            sum++;  
            a[sum]=temp/10;  
        }  
    }  
    //printf("%d/n",a[sum]);  
    return sum;  
}  
  
int main(){  
    int n,a[MAXLEN],sum,i;  
    while(scanf("%d",&n)!=EOF){  
        if(n<=0||n>5000){  
            break;  
        }   
        sum=Factorial(n,a);  
        for(i=sum;i>=0;i--){  
            printf("%d",a[i]);  
        }  
        printf("/n");  
    }  
}  

unsigned int factory(int *a, const int n)
{
	int i,j,temp;
	 
	//最高位
	int sum = 0;

	//初始化的值
	a[0] = 1;
	for(i = 0; i < MAXLEN; ++ i)
	{
		a[i] = 0;
	}

	//开始计算
	for(i = 2; i <= n; ++ i)
	{
		//每一位相乘
		for(j = 0; j <= sum; ++ j)
		{
			a[j] *= i;
		}

		//对除最高位的每一位进行进位检测
		for(j = 0; j < sum; ++ j)
		{
			temp = a[j];
			a[j] = temp % 10;
			a[j + 1] += temp / 10;
		}

		//最高位进位
		while(a[sum] > 9)
		{
			temp = a[sum];
			a[sum] = temp % 10;
			a[++sum] = temp / 10;
		}
	}

	return sum;
}

二)环形旋转输出

/*在现实生活中,我们时常碰见这样形式的数据遍历或者输出数据。

             1    2    3  

             8    9    4

             7    6    5

像这样的形式,我们可以锁定一定的算法,准确地打印数据。下面是一种实现方法:
*/
#include "stdio.h"   
  
int main(int argc, char* argv[])  
{  
    int i,j,m,n,k=0;  
      
    printf("Input the number of n:");  
  
    scanf("%d",&n);  
  
    int **a=new int*[n];  
      
    for(i = 0;i < n;++ i)  
    {  
        a[ i ] = new int[ n ];  
    }  
    //It uses to control the count of for   
    if(n % 2 == 0)  
    {  
        m = n/2;  
    }  
    else  
    {  
        m = n/2 + 1;  
    }  
    //Traversal    
    for(i = 0;i < m;i ++)  
    {  
        for(j = i;j < n - i;j ++)  
        {  
            k ++;  
            a[i][j] = k;  
        }  
  
        for(j = i + 1;j < n - i;j ++)  
        {  
            k ++;  
            a[j][n - i - 1] = k;  
        }  
  
        for(j = n - i - 2;j >= i;j --)  
        {  
            k ++;  
            a[n - i - 1][j] = k;  
        }  
  
        for(j = n - i - 2;j >= i + 1;j --)  
        {  
            k ++;  
            a[j][i] = k;  
        }  
     }  
     //Print data   
     for(i = 0;i < n;i ++)  
     {  
         for(j = 0;j < n;j ++)  
         {  
             printf("%4d",a[i][j]);  
         }  
         printf("\n");  
     }  
     
     for(i = 0;i < n;i ++) 
     { 
        delete [] a[i]; 
     } 
     
     delete a;  
       
     return 0;  
}  

顺时针的打印

/*在现实生活中,我们时常碰见这样形式的数据遍历或者输出数据。

             7    8    9  

             6    1    2

             5    4    3

像这样的形式,我们可以锁定一定的算法,准确地打印数据。下面是一种实现方法:
*/
#include "stdio.h"   
  
int main(int argc, char* argv[])  
{  
    int i,j,m,n,k;  
      
    printf("Input the number of n:");  
  
    scanf("%d",&n);
	k = n * n;
  
    int **a=new int*[n];  
      
    for(i = 0;i < n;++ i)  
    {  
        a[ i ] = new int[ n ];  
    }  
    //It uses to control the count of for   
    if(n % 2 == 0)  
    {  
        m = n/2;  
    }  
    else  
    {  
        m = n/2 + 1;  
    }  
    //Traversal    
    for(i = 0;i < m;i ++)  
    {  		 
		for(j = n - i -1; j >= i; j --)  
        {  
            
            a[i][j] = k;
			-- k;
        } 
		
		for(j = i + 1; j < n - i - 1; j ++ )  
        {  
           
            a[j][i] = k;  
			k --;
        } 
          
		for(j = i; j < n - i - 1; j ++)  
        {  
            a[n - i - 1][j] = k;  
			k --;
        }	
		 
		for(j = n - i - 1; j >= i + 1; j --)  
        {  
             
            a[j][n - i - 1] = k; 
			k --;
        } 		

     }  
     //Print data   
     for(i = 0;i < n;i ++)  
     {  
         for(j = 0;j < n;j ++)  
         {  
             printf("%4d",a[i][j]);  
         }  
         printf("\n");  
     }  
     
     for(i = 0;i < n;i ++) 
     { 
        delete [] a[i]; 
     } 
     
     delete a;  
       
     return 0;  
}  

三)求数组的每行和每列的和

#include  "stdio.h"
#include "iostream.h"

int main(int argc, char* argv[])
{
 int i,j,a[5][4] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}};
 printf("cout the array:/n");
 for(i=0;i<5;i++)
 {
  for(j=0;j<4;j++)
  {
   printf("%4d",a[i][j]);
  }
  cout<<endl;
 }
 cout<<endl;
 for(i=0;i<4;i++)
 {
  for(j=0;j<3;j++)
  {
   a[i][3]+=a[i][j];
   a[4][j]+=a[i][j];
   a[4][3]+=a[i][j];
  }
 }
 cout<<"the end of the array:"<<endl;
 cout<<endl;
 for(i=0;i<5;i++)
 {
  for(j=0;j<4;j++)
  {
   printf("%4d",a[i][j]);
  }
  cout<<endl;
 }
 cout<<endl;

 return 0;
}

四)二分法查找算法

#include "stdio.h"   
#define M 10   
  
  
/* 
**二分法查找技术要点: 
**@1 要对已经有的数据进行有规律的排序 
**@2 然后,再进行算法分析  
*/  
int main(int argc, char* argv[])  
{  
 static int a[M]={-12,0,6,16,23,56,80,100,110,130};  
  
 int n,low,mid,high,found;  
  
 low=0;  
  
 high=M-1;  
   
 found=0;  
  
 printf("Input a number to be searched:");  
  
 scanf("%d",&n);  
   
 while(low<=high)  
 {  
  mid=(low+high)/2;  
  
  if(n==a[mid])  
  {  
   found=1;  
  
   break;  
  }  
  else if(n>a[mid])  
  {  
   low=mid+1;  
  }  
  else  
  {  
   high=mid-1;  
  }  
 }  
  
 if(found==1)  
 {  
  printf("the index of %d is %d/n",n,mid+1);  
 }  
 else  
 {  
  printf("there is not %d/n",n);  
 }  
 printf("/n");  
  
 return 0;  
}  

用递归方法实现:

int RecBinarySearch(int a[],int first,int last,int item) 
{
	if(first> last)//当要查找的值不在数组a中,递归调用将会使first> last 
		return   0xFFFFFFFF; 
	int   pos=0; 
	pos=(first+last)/2; 
	if(item <a[pos]) 
		RecBinarySearch(a,first,pos-1,item); 
	else   if(item> a[pos]) 
		RecBinarySearch(a,pos+1,last,item); 
	else 
		return   a[pos]; 
} 

五)给一个奇数阶N幻方,填入数字1,2,3...N*N,使得横竖斜方向上的和都相同

//给一个奇数阶N幻方,填入数字1,2,3...N*N,使得横竖斜方向上的和都相同
#include <iostream.h>
#include <iomanip.h>
#include <cmath>
//using namespace std;
int main()
{
   
   while(1)
   {
    int n;
   cout<<"please input the number of n:";
   cin>>n;
    if(n%2!=0)
    {
     int i;
     int **Matr=new int*[n];//动态分配二维数组
     for(i=0;i<n;++i)
     {
       Matr[ i ]=new int[n];//动态分配二维数组
     }
     //j=n/2代表首行中间数作为起点,即1所在位置
     int j=n/2,num=1;//初始值
     i=0;
     while(num!=n*n+1)
     {
     //往右上角延升,若超出则用%转移到左下角
     Matr[(i%n+n)%n][(j%n+n)%n]=num;
     //斜行的长度和n是相等的,超出则转至下一斜行
     if(num%n==0)
     {
       i++;
     }
     else
     {
        i--;
        j++;
     }
     num++;
     }
     for(i=0;i<n;i++)
     {
       for(j=0;j<n;++j)
       cout<<setw((int)log10(n*n)+4)<<Matr[ i][ j ];//格式控制
       cout<<endl<<endl;//格式控制
     }
    for(i=0;i<n;++i)
    {
       delete [ ]Matr[ i ];
    }
    }
    else
    {
     cout<<"请输入一个奇正整数!/n";
     
    }
   }
  return 1;
}

六)杨辉三角递归算法

#include <stdio.h>   
  
int f(int n,int m)  
{  
    if (m == n)    /* 三角形外面的一条边 */  
    {  
        return 1;    /* 这边上的元素都是1 */  
    }  
    else if (m == 1)  
    {  
        return 1;    /* 里面的边 */  
    }  
    else  
    {  
        return f(n - 1,m - 1) + f(n - 1,m);  
    }  
}  
  
   
  
int main(int argc, char* argv[])  
{  
 int n = 5;    /* 行数 */  
    int i,j;  
      
    for (i = 1;i <= n;i++)  
    {  
        for (j = 1;j <= i;j++)  
        {  
            printf("%4d",f(i,j));  
        }  
        printf("/n");  
    }  
 return 0;  
  
}  

七)约瑟夫环

/*如题:

用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。
循环链表,用取余操作做

代码如下:
*/
#include "stdio.h"    
int main()  
{  
     int k,j,i;  
  
     int nNum,nStart,nDistance;   
     /** 
      ** nNum 总共有的数目 
      **  
      ** nStart从哪个数据开始输出 
      ** 
      ** nDistance 每隔几个数据输出 
     */  
     printf("please input nNum,nStart and nDistance:");  
     scanf("%d%d%d",&nNum,&nStart,&nDistance);  
     int *nKey = new int [nNum];  
     for(i = 0;i < nNum ;i ++)  
     {  
        nKey[i] = nDistance;  
     }  
     k = 0;  
     for(i = 0;i < nNum;i ++)  
     {  
         j = 1;  
         while(j < nStart)  
         {  
            while(nKey[k] == 0)  
            {  
                k = (k + 1) % nNum;  
            }  
            j ++;  
            k = (k + 1) % nNum;  
        }  
        while(nKey[k] == 0)  
        {  
            k = (k + 1) % nNum;  
        }  
  
      printf("%4d",k + 1);  
      nStart = nKey[k];  
      nKey[k] = 0;  
     }  
  
     printf("\n");        
    return 0;  
}  

八)桶排序

// 有1,2,....一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数。

#include<iostream.h> 

int main(){ 
	int a[] = {10,6,9,5,2,8,4,7,1,3}; 
	int len = sizeof(a) / sizeof(int); 
	int temp; 
	for(int i = 0; i < len; ) 
	{ 
		temp = a[a[i] - 1]; 
		a[a[i] - 1] = a[i]; 
		a[i] = temp; 
		if ( a[i] == i + 1) 
			i++; 
	} 
	for (int j = 0; j < len; j++) 
		cout<<a[j]<<","; 
	return 0; 
}

九)母牛生小牛问题

/*一个牧场,买了一头一岁大的母牛,母牛3岁后,每年都能生一只母牛,现在编一段程序,计算该牧场20年后有多少头母牛

解析:

每年的牛数 = 前一年的牛数 + 这年新出生的牛数
这年新出生的牛数 = 三年前的牛数 //因为牛要三岁后才能生育
所以:每年的牛数 = 前一年的牛数 + 三年前的牛数  
即 f(n) = f(n-1) + f(n-3)
*/
#include <stdio.h>  
  
int f(int nY)  
{  
    if (nY == 1)  
    {  
        return 1;  
    }  
    else if (nY == 2)  
    {  
        return 1;  
    }  
    else if (nY == 3)  
    {  
        return 2;  
    }  
  
    return f(nY -3) + f(nY-1);  
}  
  
void main()  
{  
    printf("%d\n", f(20));  
      
}  

十)寻找马鞍点

#include  "stdio.h"   
   
#define M 3   
#define N 4   
  
void minmax(int b[M][N])  
{  
 int i,j,k=0;  
 int min[M],max[N];  
 for(i=0;i<M;i++)  
 {  
  for(j=0;j<N;j++)  
  {  
   printf("%3d",b[i][j]);  
  }  
  printf("/n");  
 }  
  
 for(i=0;i<M;i++)//计算找出每行的最小元素,放入min[M]中   
 {  
  min[i]=b[i][0];  
  for(j=0;j<N;j++)  
  {  
   if(min[i]>b[i][j])  
   {  
    min[i]=b[i][j];  
   }  
  }  
 }  
 for(i=0;i<N;i++)//计算找出每列的最大元素,放入max[N]中   
 {  
  max[i]=b[0][i];  
  for(j=0;j<M;j++)  
  {  
   if(max[i]<b[j][i])  
   {  
    max[i]=b[j][i];  
   }  
  }  
 }  
 for(i=0;i<M;i++)//按照题目意思,进行匹配   
 {  
  for(j=0;j<N;j++)  
  {  
   if(min[i]==max[j])  
   {  
    printf("马鞍点是:(%d,%d):%d/n",i+1,j+1,b[i][j]);  
    k=1;  
   }  
  }  
 }  
 if(k==0)  
 {  
  printf("没有马鞍点!/n");  
 }  
  
}  
  
int main(int argc, char* argv[])  
{  
 int a[M][N];  
 int i,j;  
 printf("请输入%d个数值:",M*N);  
 for(i=0;i<M;i++)  
 {  
  for(j=0;j<N;j++)  
  {  
   scanf("%d",&a[i][j]);  
  }  
 }  
 minmax(a);//调用minmax()函数找马鞍点   
 return 0;  
}  

C语言实现 出现次数最多的数字

int _tmain(int argc, _TCHAR* argv[])
{
	
	int list[]={1,2,3,4,4,3,2,1,1,2};
	int length =sizeof(list)/sizeof(int);
	printf("测试数组为:");
	for(int i =0;i<length;i++)
	{
		printf("%d,",list[i]);
	}
	int  *result;
	result = new int[length];
	int count = 0;    
    // 这个是剩余可用的总数    
    int has = length;    
    int element;
	int MaxNum =0;
    int tempCount;    
        // 循环,直到列表里不再有数据    
    while (has > 0) 
	{    
      // 拿到最后一个数据    
      element = list[has - 1];    
      // 计数    
      tempCount = 0;    
      // 向前查找相同的    
      for (int j = has - 1; j >= 0; j--) 
	  {    
        // 如果找到,则计数加1,然后将数据和末尾交换    
        // 这也是为何要从末尾开始循环的理由    
        if (element == list[j])
		{    
          tempCount++;    
          // 将当前位置交换为末尾的数据    
          // 注意末尾数据是动态变化的    
          list[j] = list[has - 1];    
          has--;    
        }    
      }  
	printf("\n修改数组为:");
	for(int i =0;i<length;i++)
	{
		printf("%d,",list[i]);
	}
          // 如果这个计数最大,则更新输出的数据   

	
      if (tempCount > count) 
	  {    
        count = tempCount; 
		MaxNum =0;
		result[MaxNum]=element;
		//printf("%d,",count);
       // outValue.clear();    
      //  outValue.add(element);    
      } 
	  else if (tempCount == count)
	  {    
        // 否则加入到最大数的列表里    
       // outValue.add(element); 
		  MaxNum ++;
		  result[MaxNum]=element;
		  //printf("%d,",count);
      }  

    } 
	printf("\n出现频率最高的次数是:%d 次", count );
	printf("\n出现频率最高次数的数字是:\n");
	for(int m =0;m<=MaxNum;m++)
	{
		printf("%d,",result[m]);
	}
   
	getchar();
	return 0;
}

待续。。。

 

 

 

抱歉!评论已关闭.