基于C语言实现整数行列式

在本文章内,将会实现行列式的建立、销毁、打印、计算四个操作。

鉴于笔者技术有限,此行列式只针对整数int型,请读者自行扩充~_~。

1.行列式的建立与销毁

我们首先建立行列式的数据类型,由于行列式规模的不确定,采用动态分配方法。

typedef struct
{
	int n;
	int* p;
}determinant;

建立函数

void build_deter(determinant *d)//创建行列式
{
	printf("请输入行列数:>");//输入行列式
	scanf("%d", &d->n);

	d->p = (int*)malloc(sizeof (int)* d->n*d->n);//为行列式分配空间
	if (d->p == NULL)
	{
		printf("%s", strerror(errno));
	}

	printf("请按行输入值:>");
	for (int i = 0; i < d->n; i++)
	{
		for (int j = 0; j < d->n; j++)
		{
			scanf("%d",(d->p)+(i*d->n+j));
		}
	}
	printf("building over!\n");
}

销毁函数

void free_deter(determinant* d)//释放空间
{
	free(d->p);
	d->p = NULL;
}

2.行列式的打印

void dis_deter(determinant d)//打印行列式
{
	for (int i = 0; i < d.n; i++)
	{
		printf("|");
		for (int j = 0; j < d.n; j++)
		{
			printf("%-3d ", *((d.p) + (i * d.n + j)));
		}
		printf("|\n");
	}
	printf("printing over!\n");
}

其中由于动态分配原因,采用*((d.p) + (i * d.n + j))来模拟二维的定位。

3.行列式的计算

贴一张行列式的计算公式

可以看出,我们只需要解决两个问题,一个是找出p1p2p3……pn的全排列,并以此找到一组a进行相加,另一个是找到p1p2p3……pn的逆序数,从而确定每一组a前面的符号。

对于全排列,我在上一文章有讲实现原理,在此不加赘述,想要了解可以自行传送~_~,https://blog.csdn.net/2301_79847688/article/details/136762462

贴个代码:

int fac(int n)//计算阶乘
{
	int result=1;
	for (int i = n; i > 0; i--)
	{
		result *= i;
	}
	return result;
}

void change(int* a, int* b)//交换函数
{
	int c;
	c = *b;
	*b = *a;
	*a = c;
}

void bubble_sort(int* arrange,int n)//排序
{
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (arrange[j] > arrange[j + 1])
				change(arrange+j, arrange+j+1);
		}
	}
}

void tran_arrange(int* arrange, int j, int n)//改变排列
{
	if (j == 0)//自然顺序做首项
	{
		return;
	}
	if (n == 2)
	{
		change(arrange, arrange + 1);
	}
	else if(n == 3)//等于3做奇偶不同的对换
	{
		if (j % 2 == 0)
		{
			change(arrange, arrange + 1);
		}
		else if (j % 2 == 1)
		{
			change(arrange + 1, arrange + 2);
		}
	}
	else //大于3递归
	{
		if (j % fac(n - 1) == 0)//在后面数循环结束后,调换首数和后面一个数,产生新的组合
		{
			int tmp = j;
			if (tmp > fac(n))
				tmp = tmp % fac(n);//tmp要在fac(n)内,防止(1)越界

			bubble_sort(arrange + 1,n-1);//排序方便调换
			if (tmp == 0)//自然顺序做首排列,第0次
			{
				return;
			}
			if (tmp == fac(n - 1))
				change(arrange, arrange + n - 1);//调换算法,第一次换最后一位
			else
				change(arrange, arrange + n - (tmp / fac(n - 1)) + 1);//(1)之后“/”
		}
		tran_arrange(arrange+1,j,n-1);
	}
}

对于逆序数,对于排列中一个元素,他后面有多少比他小的数,那他就构成了多少逆序数,而排列的总逆序数,就是所有元素对应逆序数的和。

大体思想是这样,看看代码:

int count_re(int* arrange,int n)//统计逆序数
{
	int count = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = i+1; j < n; j++)
		{
			if (arrange[i] > arrange[j])
				count++;
		}
	}
	if (count % 2 == 1)
		return -1;
	else
		return 1;
}

这样我们就解决了所有算法问题,只需要用循环得到每一个数再相加就可以了,看看代码:

int count_deter(determinant d)//计算行列式
{
	int result = 0;//行列式最终结果
	int one = 1;//行列式的每个积
	int *col_arrange = (int*)malloc(sizeof(int)*d.n);//创建一个记录列排列的数组
	if (col_arrange == NULL)
	{
		printf("%s", strerror(errno));
	}

	for (int i = 0; i < d.n; i++)
	{
		*(col_arrange+i) = i;
	}//赋值

	for (int r = 0; r < fac(d.n); r++)//所有行列式的结果
	{
		one = 1;
		tran_arrange(col_arrange,r,d.n);//确定一个列的排序
		for (int i = 0; i < d.n; i++)
		{
			int a = *(d.p+(i*d.n)+col_arrange[i]);//行列式每个数
			one = a*one;
		}
		result += one* count_re(col_arrange, d.n);
	}

	free(col_arrange);
	col_arrange = NULL;
	return result;
}

4.总结

这便是所有内容,感谢观看~_~,贴个代码: 

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

typedef struct
{
	int n;
	int* p;
}determinant;

int fac(int n)//计算阶乘
{
	int result=1;
	for (int i = n; i > 0; i--)
	{
		result *= i;
	}
	return result;
}

void change(int* a, int* b)//交换函数
{
	int c;
	c = *b;
	*b = *a;
	*a = c;
}

void bubble_sort(int* arrange,int n)//排序
{
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (arrange[j] > arrange[j + 1])
				change(arrange+j, arrange+j+1);
		}
	}
}

void tran_arrange(int* arrange, int j, int n)//改变排列
{
	if (j == 0)//自然顺序做首项
	{
		return;
	}
	if (n == 2)
	{
		change(arrange, arrange + 1);
	}
	else if(n == 3)//等于3做奇偶不同的对换
	{
		if (j % 2 == 0)
		{
			change(arrange, arrange + 1);
		}
		else if (j % 2 == 1)
		{
			change(arrange + 1, arrange + 2);
		}
	}
	else //大于3递归
	{
		if (j % fac(n - 1) == 0)//在后面数循环结束后,调换首数和后面一个数,产生新的组合
		{
			int tmp = j;
			if (tmp > fac(n))
				tmp = tmp % fac(n);//tmp要在fac(n)内,防止(1)越界

			bubble_sort(arrange + 1,n-1);//排序方便调换
			if (tmp == 0)//自然顺序做首排列,第0次
			{
				return;
			}
			if (tmp == fac(n - 1))
				change(arrange, arrange + n - 1);//调换算法,第一次换最后一位
			else
				change(arrange, arrange + n - (tmp / fac(n - 1)) + 1);//(1)之后“/”
		}
		tran_arrange(arrange+1,j,n-1);
	}
}


void build_deter(determinant *d)//创建行列式
{
	printf("请输入行列数:>");//输入行列式
	scanf("%d", &d->n);

	d->p = (int*)malloc(sizeof (int)* d->n*d->n);//为行列式分配空间
	if (d->p == NULL)
	{
		printf("%s", strerror(errno));
	}

	printf("请按行输入值:>");
	for (int i = 0; i < d->n; i++)
	{
		for (int j = 0; j < d->n; j++)
		{
			scanf("%d",(d->p)+(i*d->n+j));
		}
	}
	printf("building over!\n");
}

void dis_deter(determinant d)//打印行列式
{
	for (int i = 0; i < d.n; i++)
	{
		printf("|");
		for (int j = 0; j < d.n; j++)
		{
			printf("%-3d ", *((d.p) + (i * d.n + j)));
		}
		printf("|\n");
	}
	printf("printing over!\n");
}

int count_re(int* arrange,int n)//统计逆序数
{
	int count = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = i+1; j < n; j++)
		{
			if (arrange[i] > arrange[j])
				count++;
		}
	}
	if (count % 2 == 1)
		return -1;
	else
		return 1;
}


int count_deter(determinant d)//计算行列式
{
	int result = 0;//行列式最终结果
	int one = 1;//行列式的每个积
	int *col_arrange = (int*)malloc(sizeof(int)*d.n);//创建一个记录列排列的数组
	if (col_arrange == NULL)
	{
		printf("%s", strerror(errno));
	}

	for (int i = 0; i < d.n; i++)
	{
		*(col_arrange+i) = i;
	}//赋值

	for (int r = 0; r < fac(d.n); r++)//所有行列式的结果
	{
		one = 1;
		tran_arrange(col_arrange,r,d.n);//确定一个列的排序
		for (int i = 0; i < d.n; i++)
		{
			int a = *(d.p+(i*d.n)+col_arrange[i]);//行列式每个数
			one = a*one;
		}
		result += one* count_re(col_arrange, d.n);
	}

	free(col_arrange);
	col_arrange = NULL;
	return result;
}


void free_deter(determinant* d)//释放空间
{
	free(d->p);
	d->p = NULL;
}

int main()
{

	determinant d;
	build_deter(&d);
	dis_deter(d);
	printf("\n%d",count_deter(d));
	free_deter(&d);
	return 0;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值