n阶行列式计算----c语言实现(完结)

花了半天时间,写了这个n阶行列式计算的程序,应该算是比较优美吧,有很多地方多次做了优化,程序占用内存不是很大,要是说小吧,也不合适,因为里边有一个递归,而且递归的深度还比较深。时间复杂度具体没有细看,应该不会太大。
看我的程序运行的截图:




ok,先看程序。
 
 C  Code 
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
 
 
#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)//利用地址传递,交换两个数的值
{
    
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 %  ==  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/( a q( a ) *  0 . ) *  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  * ) malloc (  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 ==  )
            printf(
"请依次输入行列式中第%d行的值(以空格分隔):\n" ,i / a +  );//提示输入行列式的值
        scanf(
"%d" , c + i );
    }
    printf(
"\n\n" );
    perm( b, 
0 , a -  );//计算行列式的值
    printf(
"\n行列式展开式共有%d项\n" , aq( a ) );//打印出来行列式的各种信息
   
  if  ( a %  !=  ) f = a +  1 ;//判断当前的行列式是偶数行还是奇数行
        
else  f = a;
    
for ( i =  0 ; i < a * a; i ++ )
    {       

        
if  ( i / a +  == f /  && i % a ==  0 ) //判断是否达到行列式中间的一行行首
            printf(
"D = " );//输出“D = ”
        
else   if  ( i % a ==  0 ) //判断是否是每一行的行首,若是则输出四个空格,保证输出的格式优美
                    printf(
"    " );
        
if  ( i % a ==  0 ) //判断是否是行首,若是输出制表符竖线,可与上一句写到一块儿
            printf(
"┃" );
        
if  ( ( i +  ) % a ==  0 ) //判断是否是行列式某一行的最后一个数
            printf(
"%2d" , * ( c + i ) );
        
else  printf( "%2d " , * ( c + i ) );//若不是 行列式某一行的最后 一个数则在数字后边加一个空格
        
if  ( ( i +  ) % a ==  ) //判断是否到达一行的行末
            printf(
"┃" );
        
if  ( ( i +  ) / a == f /  && ( i +  ) % a ==  0 ) //判断是否达到行列式中间一行的行末,输出整个行列式的值
            printf(
" = %d\n" ,sum);
        
else   if  ( ( i +  ) % a ==  ) //判断是否到达行末输出换行
                    printf(
"\n" );
    }
    printf(
"\n\n" );
    printf(
"是否继续?( 1 / 0 )\n" );//提示是否退出
    scanf(
"%d" , &e);
    n = 0;//每次都将都将上一次的运行记录消除
    
if ( e == goto  u;//判断是否推出
    
else   if  ( e ==  ) exit(  );
}

 
过了很久之后,加了一些注释,若是各位看官还有不清楚的请百度去,或者直接问我,愿意解答。
里边还有好多地方可以调整,若有更好的调整方法,请联系我,不胜感激。 







 

转载于:https://www.cnblogs.com/tosone/p/3353625.html

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值