n阶⾏列式计算----c语⾔实现(完结)
花了半天时间,写了这个n阶⾏列式计算的程序,应该算是⽐较优美吧,有很多地⽅多次做了优化,程序占⽤内存不是很⼤,要是说⼩吧,也不合适,因为⾥边有⼀个递归,⽽且递归的深度还⽐较深。时间复杂度具体没有细看,应该不会太⼤。ok,先看程序。
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>//包含的头⽂件不解释
typedef bool int //因为标准c⾥边没有bool类型才这么做
#define false 0
#define true 1
//定义⼏个全局变量,⽆奈之举
int *c, //将整个⾏列式的值存到c指向的空间⾥
n = 0,//记录当前的⾏列式计算进⾏了多少步
a, //⽅便传递⾏列式的阶数
sum = 0; //记录每⼀步⾏列式计算所累加的结果
int aq(int a) //计算阶乘的函数,就不多解释了
{
int s = 1;
for (int i = 1; i <= a; i ++)
s *= i;
return s;
}
void swap(int *a, int *b) //利⽤地址传递,交换两个数的值
{c语言用递归函数求n的阶乘
int m = * a;
* a = * b;
*b = m;
}
bool sa(int *l) //计算在⾏列式计算过程中每⼀项前边的符号是正还是负
{
int n = 0;//n为⾏列式展开式每⼀项的逆序数
for (int i = 0; i < a - 1; i ++)
for (int j = i + 1; j < a; j++)
if (l[i] > l[j])n++; //不断通过条件判断累加逆序数得出最终的逆序数
if (n % 2 == 0) return false; //若为正,则返回false
return true;//否则返回true
}
void perm(int *l, int k, int m) //整个程序⾥边的核⼼函数,出在不同⾏不同列的所有组合
{
int i, s = 1;
if (k > m)
{
n++;//每递归回来⼀次,将记录运⾏次数加⼀
for (int j = 0; j < a; j ++)
s *= c[ l[ j ] + a * j ];//算出此次⾏列式展开式的这项的值
if ( sa( l ) ) s * = -1; //确定这⼀项的符号
//输出当前sum内的值(即到当前为⽌所得到的结果是多少)
//输出运⾏的完成程度(即当前运⾏的次数除以总次数)
printf("%5d 完成度:%2.2f%%\n", sum + = s, n / ( aq( a ) * 0.1 ) * 10 );
}
else //不断的向内递归,就不多解释了,因为很多⼤公司招聘的时候,全排列问题在笔试环节是必出题,百度⾥有很多解释
{
for (i = k; i <= m; i++)
{
swap(l + k, l + i);
perm(l, k + 1, m);
swap(l + k, l + i);
}
}
}
void main()//主函数
{
int *b, //⼀个辅助变量,在递归函数中将b指向的空间内的值进⾏全排列,也即⾏列式展开式不同组合的下标
i, //循环中的辅助变量
f, //在格式化输出⾏列式的辅助变量
e;//判断是否退出程序的标志位
system("color 3e");//设置程序运⾏的前景⾊和背景⾊
u: system("cls");//清空屏幕
printf("请输⼊⾏列式的阶数:\n");
scanf("%d", &a);//获取⾏列式的阶数
b = ( int *) mallo
c ( sizeof ( int ) * a ); //为变量申请空间
c = ( int *) malloc ( sizeof ( int ) * a * a );
for ( i = 0; i < a; i++)
* ( b + i ) = i;//为辅助变量也即⾏列式下标逐个赋值
for ( i = 0; i < a * a; i++)
{
if ( i % a == 0 )
printf("请依次输⼊⾏列式中第%d⾏的值(以空格分隔):\n", i / a + 1 ); //提⽰输⼊⾏列式的值
scanf("%d", c + i );
}
printf("\n\n");
perm( b, 0, a - 1 );//计算⾏列式的值
printf("\n⾏列式展开式共有%d项\n", aq( a ) );//打印出来⾏列式的各种信息
if ( a % 2 != 0 ) f = a + 1;//判断当前的⾏列式是偶数⾏还是奇数⾏
else f = a;
for ( i = 0; i < a * a; i ++ )
{
if ( i / a + 1 == f / 2 && i % a == 0) //判断是否达到⾏列式中间的⼀⾏⾏⾸
printf("D = ");//输出“D = ”
else if ( i % a == 0) //判断是否是每⼀⾏的⾏⾸,若是则输出四个空格,保证输出的格式优美
printf(" ");
if ( i % a == 0) //判断是否是⾏⾸,若是输出制表符竖线,可与上⼀句写到⼀块⼉
printf("┃");
if ( ( i + 1 ) % a == 0) //判断是否是⾏列式某⼀⾏的最后⼀个数
printf("%2d", * ( c + i ) );
else printf("%2d ", * ( c + i ) );//若不是⾏列式某⼀⾏的最后⼀个数则在数字后边加⼀个空格
if ( ( i + 1 ) % a == 0 ) //判断是否到达⼀⾏的⾏末
printf("┃");
if ( ( i + 1 ) / a == f / 2 && ( i + 1 ) % a == 0) //判断是否达到⾏列式中间⼀⾏的⾏末,输出整个⾏列式的值
printf(" = %d\n", sum);
else if ( ( i + 1 ) % a == 0 ) //判断是否到达⾏末输出换⾏
printf("\n");
}
printf("\n\n");
printf("是否继续?( 1 / 0 )\n");//提⽰是否退出
scanf("%d", &e);
n = 0;//每次都将都将上⼀次的运⾏记录消除
if ( e == 1 ) goto u; //判断是否推出
else if ( e == 0 ) exit( 0 );
}
过了很久之后,加了⼀些注释,若是各位看官还有不清楚的请百度去,或者直接问我,愿意解答。⾥边还有好多地⽅可以调整,若有更好的调整⽅法,请联系我,不胜感激。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论