c语言用堆栈0到n1的全排列.docx
《c语言用堆栈0到n1的全排列.docx》由会员分享,可在线阅读,更多相关《c语言用堆栈0到n1的全排列.docx(8页珍藏版)》请在冰豆网上搜索。
![c语言用堆栈0到n1的全排列.docx](https://file1.bdocx.com/fileroot1/2023-1/26/b9952078-1be7-4673-81d1-23127cdc312a/b9952078-1be7-4673-81d1-23127cdc312a1.gif)
c语言用堆栈0到n1的全排列
C语言用堆栈0到n-1的全排列
本程序用C语言实现,采用多文件编译,从主函数中调用其接口函数即可.需要注意的是由于采用了堆栈,其运行效率并不是十分高.对于n阶,共有n!
种情况.以下plzh代表排列组合.(本机运行环境是xpsp3+vc6.0++)
//头文件plzh.h
#ifndefPLZH_H
#definePLZH_H
#include
#include
voidinitial(intn);
intstackfull(intn);
voidstackprint(intn);
voidstackoutfile(intn);
voidstackback();
voidstackadd(intn);
voidstackmov(intn);
voidstackfun(intn);
#endif
//头文件实现函数plzh.c
#include
#include
#include"plzh.h"
#defineN50//定义栈的大小.
intstack[N];//定义栈.
intp=-1;//定义栈底.
inta[N],b[N],c[N];//分别表示当前数的值,改变后的值,及改变的次数.
FILE*pfile;
/**********************
*对栈进行初始化.
**********************/
voidinitial(intn)
{
inti=0;
for(i=0;i{
stack[++p]=i;//第一次初始化的值.
a[i]=b[i]=i;//初始值相同.
c[i]=0;//0表示尚未改变过.
}
}
/***********************************************
*判断栈是否已满,在本程序中,此函数实际上是多余的.
***********************************************/
intstackfull(intn)
{
if(p+1==n)
return1;
else
return0;
}
/********************
*打印栈中的数值.
*此处是输出到屏幕上.
********************/
voidstackprint(intn)
{
inti=0;
for(i=0;iprintf("%d",stack[i]);
printf("\n");
}
/*************************
*也可输出到文件中.
*************************/
voidstackoutfile(intn)
{
fwrite(stack,sizeof(int),n,pfile);
//FILE*pfile;
//inti;
//pfile=fopen("dat.txt","a+");
//for(i=0;i//fprintf(pfile,"%d",stack[i]);
//putw(stack[i],pfile);
//fprintf(pfile,"%c",'\n');
//fclose(pfile);
}
/***********************
*退栈.
*实际上这个可以省去,但为了更好理解,写成一个函数.
***********************/
voidstackback()
{
p--;
}
/**********************************
*当经过一次退栈后,当前栈顶是p,则p+1到n-1
*中并没有填充数字,此函数的作用就是为后面
*的栈中重新入栈.
*并且此处是有规律的入栈.
**********************************/
voidstackadd(intn)
{
intj,k,flag;//j,k是控制变量,flag是标志变量.
while(1+p{
/************************
*此段的作用是使当前填充的值与前面的都不相同.
*用for循环控制.
************************/
for(j=0;j{
flag=0;
for(k=0;k<=p;k++)
{
if(j==stack[k])//若与某一个栈相同,则重新对j赋值.
{
flag=1;
break;
}
}
if(flag==0)//当flag为0时,表示赋值成功.
{
stack[++p]=j;//当此值赋到栈中.
a[p]=b[p]=j;//同时重新定义当前值,并使其相等.相当于又初始化.
c[p]=0;//把值的改变次数定义为0.
break;
}
}
}
}
/*********************************
*本程序的核心所在.
*算法是若退栈到当前值,则改变当前值.
*使当前栈值b[p]=(b[p]+1)%n;
*********************************/
voidstackmov(intn)
{
intflag,i;
while
(1)
{
b[p]=(b[p]+1)%n;//此处比较好理解,即循环.
c[p]++;//记录值的变化.
flag=0;//0表示赋值成功,1表示要赋的值已被占用.
for(i=0;i
{
if(b[p]==stack[i])//要赋的值已存在.
{
flag=1;
break;
}
}
if(flag==1)//若赋值失败则进行下一轮的赋值.
continue;
if((a[p]==b[p])||flag==0)//结果是要么赋值成功,要么回到原来的值.
break;
}
if(flag==0&&(a[p]!
=b[p]))//当赋值成功.
{
stack[p]=b[p];//将值赋进栈中.
stackadd(n);//对该栈后面的值进行填充.
}
else//当回到原来的位置,要退栈.
stackback();
}
/**********************************
*此处是接口函数.
**********************************/
voidstackfun(intn)
{
pfile=fopen("dat.txt","w");
initial(n);//初始化.
if(stackfull(n))//初始化后本身就是一个成功的排列,打印出来.
{
stackprint(n);
stackoutfile(n);
XX文库-让每个人平等地提升自我}
while
(1)//一直循环下去,直到退无可退.
{
/*********************************
*这是本程序中最关键的一条指令.
*此处的退栈仅且只能在值尚未发生变化的情况下退栈.
*若没有c[p]!
=0,当退到任一个栈时,他们的初始状态都是a[p]==b[p]
*若是(a[p]==b[p])&&c[p]!
=0表明当前栈已是退无可退.
*此处有个关键时,第一轮开始的时候并没有执行该指令,当栈顶值循环一轮后
*使c[p]!
=0后才开始执行的,要特别注意这个地方.
*********************************/
if((a[p]==b[p])&&c[p]!
=0)
stackback();
stackmov(n);//退完栈后要补齐后面的.
if(stackfull(n))
{
stackprint(n);
stackoutfile(n);
}
if(p==-1)//结束的条件,退无可退.
break;
}
fclose(pfile);
}
//用户的调用函数,即入口主函数diaoyong.c
#include
#include
#include"plzh.h"
intmain()
{
inti;
printf("请输入一个数字:
");
while(scanf("%d",&i)==1)
{
if(i>0)
{
printf("\n%d的排列如下:
\n",i);
stackfun(i);
printf("\n");
printf("请输入一个数字:
");
}
else
printf("输入的不合法,请重新输入:
");
}
return0;
}