C的几个小程序和概念(常见操作)(下)

C的几个小程序和概念(常见操作)(下)

1、排列问题

输出n中取m无重复的元素排列情况。

用递归实现

#include "iostream"

using namespace std;

char f[27];//最多用个字母来表示排列情况

char p[27];//来标识当前字母的获取情况。都从开始,不用。自动初始化为

int m,n;//从n个数中取m个数

FILE *fp=fopen("c:\\pailie.txt","w+");

void pa(int k){

if(k>m) //已取够了m个了,则输出

  {

   for(int i=1;i<=m;i++)

    //putchar(p[i]+'A'-1);

   fprintf(fp,"%c",p[i]+'A'-1);

   //cout<<endl;//输出,换行,返回

   fprintf(fp,"%c",'\n');

   return;

  }//if

//还没有取够m个

for(int i=1;i<=n;i++)

   if(!f[i])

     {

      f[i]=1;//将当前的这个字母作标记

   p[k]=i;//将当前的这个字母取上

   pa(k+1);//继续取下一个字母

   f[i]=0;//将取出的第i个元素重新放入集合S,关键

     }//if

}//pa

int main(){

cout<<"Input n m of P(n,m)=";

cin>>n>>m;

//...进行n,m合乎规定逻辑的判断

if(!fp)  {

 cout<<"error";

     return 1;

         }

pa(1);//先找第一个字符

}

2、组合问题

取n个数字中可重复的m个数的情况

#include "iostream"

using namespace std;

char f[27];//最多用个字母来表示排列情况

char p[27];//来标识当前字母的获取情况。都从开始,不用。自动初始化为

int m,n;//从n个数中取m个数

//FILE *fp=fopen("c:\\pailie.txt","w+");

void pa(int k,int share){

if(k>m) //已取够了m个了,则输出

  {

   for(int i=1;i<=m;i++)

    putchar(p[i]+'A'-1);

   //fprintf(fp,"%c",p[i]+'A'-1);

   cout<<endl;//输出,换行,返回

   //fprintf(fp,"%c",'\n');

   return;

  }//if

//还没有取够m个

for(int i=share+1;i<=n;i++)

   if(!f[i])

     {

      f[i]=1;//将当前的这个字母作标记

   p[k]=i;//将当前的这个字母取上

   pa(k+1,i);//继续取下一个字母

   f[i]=0;//将取出的第i个元素重新放入集合S,关键

     }//if

}//pa

int main(){

cout<<"Input n m of P(n,m)=";

cin>>n>>m;

//...进行n,m合乎规定逻辑的判断

//if(!fp)  {

// cout<<"error";

 //    return 1;

//         }

pa(1,0);//先找第一个字符

}

我们分析问题,可以知道,组合问题是:为了避免重复,取下一个元素时,必须在当前元素的下一位置开始探索。所以再传递一个share变量,以便下一次搜索时从下一个位置开始就好了。

3、八皇后问题

每列必然有一个皇后,每行必然有一个皇后。

放下一列放置皇后时,我们要找的是应当放置在该列的那一行,这样我们与前面的所有列放置的皇后进行操作探索,看是否满足条件。

不满足条件的定义是:(因为是在不同列试探,所以列肯定不同)同处于同一行,或在45角方向上。用(k,j)来描述,k表示列号,j表示行号。

试探过程中,如果第k个皇后无位置可放,则退回上一列,试探第k-1皇后的下一个可放位置,依次类推。这样一直回溯到第一个皇后,如果第一个皇后试完最后一个行号8,则算法停止。

#include "cmath"

#include "iostream"

using namespace std;

int row[8];//由于我们是每一列逐一进行试探,所以只需要保存每一列的行号就可以了。

int count;

void arrange(int k){//试探第k列

int i,j;

if(k>8){//第k列也放置好了,说明存在一个可放置的行系列,输入之

  for(i=1;i<=8;i++)

   cout<<row[i]<<" "; //输出每一列的行号

  cout<<endl;

  count++;

  return;

  }//if

for(j=1;j<=8;j++){//试探当前列的每一行是否满足条件

 for(i=1;i<k;i++)//将当前列的第一行都与前面k-1列放置的皇后位置进行判断,看当前列的试探行是否满足条件

 if(row[i]==j||(k-i)==abs(j-row[i]))//与前面的任何一个皇后同行,或位于角上,则退出此处试探,进行下一轮

  break;

 if(i>=k)//当前第k列的第j行满足条件,记录

 {

 row[k]=j;

 arrange(k+1);//继续放置下一列的皇后

 }//if

  }//for

}//arrange

int main()

{

arrange(1);

cout<<count<<endl;

}

可以得出,是92种。

4、关于new和delete的几个操作

int(*p)[3][4]=new int[2][3][4];//int(*p)[3][4]=(int(*)[3][4])malloc(2*sizeof(int[3][4]));

char **s=new char*[10];//char **s=(char**)malloc(10*sizeof(char*))

int(**p)()=new(int(*)[7]());//int(**p)()=(int(**)())malloc(sizeof(int(*[7])()));

5、字符I/O

输入

int fgetc( FILE *stream );

int getc( FILE *stream );

int getchar( void );//get the char from the stdin

返回int主要是为了允许函数报告文件的末尾EOF

输出

int fputc( int c, FILE *stream );

int putc( int c, FILE *stream );

int putchar( int c );

fgetc,fputc是函数,其它几个都是宏。

撤销字符

int ungetc( int c, FILE *stream );

如果多个字符返回一个流中,则再次读时以反序进行。退回到流和写入到流中不相同。如果用fseek,rewind改变了流的位置,则退回的字符会丢弃。

#include <stdio.h>

#include <ctype.h>

void main( void )

{

   int ch;

   int result = 0;

   printf( "Enter an integer: " );

   /* Read in and convert number: */

   while( ((ch = getchar()) != EOF) && isdigit( ch ) )

      result = result * 10 + ch - '0';    /* Use digit. */

   if( ch != EOF )

      ungetc( ch, stdin );                /* Put nondigit back. */

   printf( "Number = %d\nNextcharacter in stream = %c%c", 

            result, getchar(), getchar());

}

发布了81 篇原创文章 · 获赞 17 · 访问量 6001

猜你喜欢

转载自blog.csdn.net/hopegrace/article/details/103894672