求線性代數n階行列式代碼

算的實在是心煩,上網找了一篇大佬的代碼
真的是牛逼,附:大佬博客

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>//包含的頭文件不解釋
#define bool int      //因爲標準c裏邊沒有bool類型才這麼做
#define false 0
#define true 1
//定義幾個全局變量,無奈之舉
int *c;  //將整個行列式的值存到c指向的空間裏
int	n = 0;//記錄當前的行列式計算進行了多少步
int a; //方便傳遞行列式的階數
int 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 % 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);
        }
    }
}
int 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 == 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;//每次都將都將上一次的運行記錄消除
    sum=0;
    if ( e == 1 ) goto u; //判斷是否推出
    else if ( e == 0 ) exit( 0 );
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章