文章目录:
一: C++从键盘输入10个整数,用整型一维数组存储。要求输入时无序,输入完成后数组元素已按递增排序。输出此数组元素。(使用插入排序方法)
二:C++编制程序实现M*K阶矩阵A与K*N阶矩阵B的乘积矩阵C(M*N阶)的求解和输出,要求分别使用两种存储矩阵的方法(分别编程)
三:C++编制程序用高斯顺序消元法求解n阶线性方程组在增广矩阵中讨论
四:C++编写程序用高斯消元法(例如第3题中的系数矩阵:经2步消元后系数矩阵变换为上三角形矩阵,可以再做2步消元,将矩阵变换成对角线矩阵,最后再变换为单位矩阵)求n阶方阵的逆矩阵并验证正确与否。
一: C++从键盘输入10个整数,用整型一维数组存储。要求输入时无序,输入完成后数组元素已按递增排序。输出此数组元素。(使用插入排序方法)
代码实现
#include <iostream>
using namespace std;
int main()
{
int a[10] ; //定义数组长度
int i,j; //定义变量
//键盘循环输入10个数
for (i = 0; i < 10; i++)
{
cout<< "请输入10个整数存到数组,第"<<i+1<<"次输入为:"<<endl;
cin >>a[i];
}
//输出键盘的10个数
cout<<"你输入的数组为:";
for(int i=0;i<10;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
cout << "-----------------------------------------------------"<<endl;
//开始排序
for(i=1;i<10;i++)
{
//从后面无序的往前面有序的插
int temp = a[i];
for(j=i-1;j>=0;--j)
{
if(temp<a[j]){
a[j+1]=a[j];//在有序列表中比arr[j]大的元素后移
}else
{
break; //arr[j]大于有序表中的最后一位则不需要移动
}
}
a[j+1]=temp; //跳出内层循环插在合适的位置
}
cout<<"其插入排序后为:";
for(int i=0;i<10;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
system("pause");
return 0;
}
运行结果
二:C++编制程序实现M*K阶矩阵A与K*N阶矩阵B的乘积矩阵C(M*N阶)的求解和输出,要求分别使用两种存储矩阵的方法(分别编程)
- 用静态二维数组存储矩阵;例如Aij=a[i][j]
- 用静态一维数组存储矩阵。例如Aij=a[i*K+j]
注:矩阵的乘积——设A为m*k阶,B为k*n阶,则C为m*n阶,Cij=Ai0*B0j+……+ Ai,k-1*Bk-1,j
扩展
行 列
A: M*K
B: K*N
C=A*B:M*N
矩阵相乘:左行*右列
只有当左边矩阵的列数等于右边矩阵的行数时才能相乘
乘积矩阵:行数等于左边矩阵的行数;列数等于右边矩阵的列数
代码实现
#include <iostream>
using namespace std;
const int maxlong = 100;
int main()
{
int M,K,N;
//定义三个矩阵大小;初始化矩阵C
int A[maxlong][maxlong],B[maxlong][maxlong],C[maxlong][maxlong]={0};
//A: M*K B: K*N C:M*N
cout<<"请输入你要相乘的行列大小!!!"<<endl;
cout <<"请输入第一个矩阵的行大小:" <<endl;
cin>>M;
cout <<"请输入第一个矩阵的列大小——第二个矩阵的行大小:" <<endl;
cin>>K;
cout <<"请输入第二个矩阵的列大小:" <<endl;
cin>>N;
//矩阵A
cout<<"请输入矩阵A:"<<endl;
for(int i=0;i<M;i++){
for(int j=0;j<K;j++){
cin>>A[i][j];
}
}
//输出矩阵A
cout << "矩阵A为:"<<endl;
cout <<"----------------------"<<endl;
for(int i=0;i<M;i++){
for(int j=0;j<K;j++){
cout <<A[i][j]<< "\t";
/* if(j!=K-1){
cout <<" ";
}*/
}
cout <<endl;
}
cout <<"----------------------"<<endl;
//矩阵B
cout<<"请输入矩阵B:"<<endl;
for(int i=0;i<K;i++){
for(int j=0;j<N;j++){
cin>>B[i][j];
}
}
//输出矩阵B
cout << "矩阵B为:"<<endl;
cout <<"----------------------"<<endl;
for(int i=0;i<K;i++){
for(int j=0;j<N;j++){
cout <<B[i][j];
if(j!=N-1){
cout << "\t";
}
}
cout <<endl;
}
cout <<"----------------------"<<endl;
//乘积矩阵矩阵C
for(int i=0;i<M;i++){ //第一个矩阵的行大小
for(int j=0;j<N;j++){ //第二个矩阵的列大小
for(int y=0;y<K;y++){ //第一个矩阵的列大小——第二个矩阵的行大小
C[i][j] += A[i][y]*B[y][j]; //A数组中第i行第j列的值*B数组第y行第j列的值=C数组第i行第j列的值
}
}
}
//输出乘积矩阵矩阵C
cout << "乘积矩阵矩阵C为:"<<endl;
cout <<"----------------------"<<endl;
for(int i=0;i<M;i++){
for(int j=0;j<N;j++){
cout <<C[i][j];
if(j!=N-1){
cout << "\t";
}
}
cout <<endl;
}
cout <<"----------------------"<<endl;
system("pause");
return 0;
}
运行结果
三:C++编制程序用高斯顺序消元法求解n阶线性方程组在增广矩阵中讨论
1.存取在二维数组中
2.首先要确定是几阶,n-1步消元
3阶 需要3-1=2步消元
3.如果为几阶:行为n;列为n+1
如果为3阶:行为3,列为4
如果为4阶:行为4,列为5
4.消元:消元到底n阶为止
3阶:第0行,第1行,第2行
第1步消元:
倍数1:m1=a[1][0]/a[0][0] 第1行-第0行*m1=第1行
倍数2:m2=a[1][0]/a[0][0] 第2行-第0行*m2=第2行
第2步消元:
倍数3:m3=a[2][0]/a[1][0] 第2行-第行*m3=第2行
5.等式:几阶就是x几
倒着来:n行~1行
求得结果依次往上带入
6*x3=6 x3=1
3*x2+1*x3=-5 x2=-2
2*x1+2*x2+3*x3=3 x1=2
方法一: 误差较大
前面后面分开来,处理方法一样
代码实现
参考:https://blog.csdn.net/qq_26025363/article/details/53027926
#include<iostream>
#include <cmath>
using namespace std;
//定义是几个阶层
const int n = 3;
//定义实现n阶线性方程组的求解
//方程组前面部分 方程组后面部分
void liu(double a[n][n], double b[n])
{
//判断能否用高斯消元法,如果矩阵主对角线上有0元素存在是不能用的
for (int i = 0; i < n; i++)
if (a[i][i] == 0)
{
cout << "抱歉对角线有0元素,不能用高斯消元法!" << endl;
return;
}
int i, j, k;
//存储初等行变换的系数,用于行的相减
double c[n];
//开始消元
for (k = 0; k < n - 1; k++) //总共n-1次
{
for (i = k + 1; i < n; i++) //依次,求出第K次初等行变换的系数
c[i] = a[i][k] / a[k][k];
//依次,第K次的消元计算
for (i = k + 1; i < n; i++) //与上面相互对应
{
for (j = 0; j < n; j++)
{
a[i][j] = a[i][j] - c[i] * a[k][j]; //变换后的这一行更新
}
b[i] = b[i] - c[i] * b[k]; //后面部分也一样
}
}
//存储解
double x[n];
//先计算出最后一个未知数;
x[n - 1] = b[n - 1] / a[n - 1][n - 1]; //积/因子=未知数
//求出每个未知数的值,倒着来,从倒数第2个开始
//几个未知量
//当n=3时:1;0两种
for (i = n - 2; i >= 0; i--) //从第0个未知数~倒数第2个未知数
{
double sum = 0;
//层数
//当n等于3时:i=1 i=0
// 循环1次-循环2次;
for (j = i + 1; j < n; j++) //每一个方程 1,2
{
//除开未知量的项
//每一次,每组除开未知量的项的,及其和都不一样
sum += a[i][j] * x[j]; //3*1;2*(-2)——累加
}
//(结果-除开未知量的项)/未知量项系数=结果
x[i] = (b[i] - sum) / a[i][i]; //存储解的结果 [(-5)-1]/3=-2 {3-[3*1+2*(-2)]}/2=2
}
//遍历输出解
cout << " 这个n阶线性方程的各个解为:" << endl;
cout << endl;
for (i = 0; i < n; i++)
cout <<"x"<<i+1<<"="<< x[i] << endl;
}
int main (){
//这里更具自己需要填写
//输入n阶线性方程组的前面部分
double a[3][3] = {2,2,3,4,7,7,-2,4,5};
//输入n阶线性方程组的后面部分
double b[3] = { 3,1,-7};
//引用
liu(a, b);
system("pause");
return 0;
}
运行结果
方法二:误差较小
分开来,但是这里是找出最大的主元来依次消元
代码实现
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int m, n,i,j,k; // 行:m 列:n
double a[100][100],temp[100],d; //定义矩阵大小 ;和值存取数组;每行的倍数变量;
void main()
{
cout << "温馨提示:请输入标准的数值,不然会出现无穷、分母为0、越界等情况!"<<endl;
cout << "请输入系数矩阵的行数:";
cin >> m;
cout << "请输入系数矩阵的列数:";
cin >> n;
if (m <= 0 || n <= 0)
{
cout << "输入的格式有误!\n";
}
for (i = 0; i < m; i++)
{
cout << "请输入第" << i + 1 << "行"<<"的"<<n<<"个系数:"<<endl;;
for (j = 0; j < n; j++)
{
cin >> a[i][j];
}
}
cout << "请输入"<<m <<"个每行等式后面的值:"<<endl;;
for (i = 0; i < m; i++)
{
cin >> a[i][n];
}
cout << "该方程组的增广矩阵为:\n";
cout <<"---------------------------------------------"<<endl;
for (i = 0; i < m; i++)
{
for (j = 0; j < n+1; j++)
{
cout << a[i][j]<<"\t ";
}
cout << "\n";
}
cout <<"---------------------------------------------"<<endl;
//找列主元最大值
for (k = 0; k < n - 1; k++)
{
double max = 0;
int hang=0,num=0;
for (i = k; i < n; i++)
{
if (fabs(a[i][k]) > max)
{
max = fabs(a[i][k]);
hang = i;
}
}
//对角线
if (a[hang][k] == 0)
{
cout << "无法计算" << endl;
return;
}
//换行
if (k != hang)
{
for (i = 0; i < m+1; i++)
{
temp[i] = a[k][i];
a[k][i] = a[hang][i];
a[hang][i] = temp[i];
}
}
cout << "选取列主元之后的增广矩阵为:\n";
cout <<"---------------------------------------------"<<endl;
for (i = 0; i < m; i++)
{
for (j = 0; j < n + 1; j++)
{
cout << a[i][j] << "\t ";
}
cout << "\n";
}
cout <<"---------------------------------------------"<<endl;
//开始消元
for (i = k + 1; i < m; i++)
{
d = a[i][k] / a[k][k];
for (j = 0; j < n + 1; j++)
{
a[i][j] = a[i][j] - d * a[k][j];
}
}
cout <<"---------------------------------------------"<<endl;
cout << "消元后的增广矩阵为:\n";
for (i = 0; i < m; i++)
{
for (j = 0; j < n + 1; j++)
{
cout << a[i][j] << " \t";
}
cout << "\n";
}
cout <<"---------------------------------------------"<<endl;
}
//存取解
//将temp内存做初始化,内容全部设置为0,准备存放解向量
memset(temp, 0, 2* sizeof(double));
for (i = m-1; i >= 0; i--)
{
d = 0;
for (k = 0; k < n; k++)
{
d += temp[k] * a[i][k];
}
temp[i] = (a[i][n] - d) / a[i][i];
}
//输出解
cout << "此方程组的解为:"<<endl;
for (i = 0; i < m; i++)
{
cout << " "<< fixed << setprecision(2)<<"x"<<i+1 <<"=" << temp[i]<<endl;//小数位数取舍
}
system("pause");
}
运行结果
方法三:误差最小
前面两种方法都有一个共同特点就是, 线性方程组 前面和后面分开输入,要么自己输入代码,要么自定输入
可以尝试按照每一行包括【前面未知量+等式后半部分】,然后打印出来,进行初等变换,最后求解,可能有一丢丢麻烦
四:C++编写程序用高斯消元法(例如第3题中的系数矩阵:经2步消元后系数矩阵变换为上三角形矩阵,可以再做2步消元,将矩阵变换成对角线矩阵,最后再变换为单位矩阵)求n阶方阵的逆矩阵并验证正确与否。
求逆矩阵的基本操作方法是取一个与A同阶的单位矩阵A_1
用高斯-约当消元法(矩阵的初等行变换)将A消元成为单位矩阵,消元操作同时作用于A_1
最终A_1即为A的逆阵,以4阶为例
方法一 :原理法
1.原矩阵A n*n
2.取一个与A同阶的单位矩阵E
3.一左一右,组成一个新的矩阵B n*2n
4.开始消元
5.变成一右一左,构成一个新的矩阵B1 n*2n
6.右边矩阵A1,即为逆矩阵
方法二:公式法
参考:https://recomm.cnblogs.com/blogpost/5292287
代码实现
#include <cmath>
#include <malloc.h>
#include <iostream>
#include <iomanip>
using namespace std;
#define N 10 //定义方阵的最大阶数为10
//函数的声明部分
float MatDet(float *p, int n); //求矩阵的行列式
float Creat_M(float *p, int m, int n, int k); //求矩阵元素A(m, n)的代数余之式
void print(float *p, int n); //输出矩阵n*n
bool Gauss(float A[][N], float B[][N], int n); //采用部分主元的高斯消去法求方阵A的逆矩阵B
int main()
{
float *buffer, *p; //定义数组首地址指针变量
int row, num; //定义矩阵的行数和矩阵元素个数
int i, j;
float determ; //定义矩阵的行列式
float a[N][N], b[N][N];
int n;
cout << "采用逆矩阵的定义法求矩阵的逆矩阵!\n";
cout << "请输入矩阵的行数: ";
cin >> row;
num = 2 * row * row;
buffer = (float *)calloc(num, sizeof(float)); //分配内存单元
p = buffer;
if (NULL != p)
{
for (i = 0; i < row; i++)
{
cout << "请输入逆矩阵的第" << i+1 << " 行: "<<endl;
for (j = 0; j < row; j++)
{
cin >> *p++;
}
}
}
else
{
cout << "无法分配内存!\n";
}
cout << "你输入的矩阵为 : \n";
cout<<"----------------------------------"<<endl;
print(buffer, row); //打印该矩阵
cout<<"----------------------------------"<<endl;
determ = MatDet(buffer, row); //求整个矩阵的行列式
p = buffer + row * row;
if (determ != 0)
{
cout << "这个矩阵的行列式为: " << determ << endl;
for (i = 0; i < row; i++) //求逆矩阵
{
for (j = 0; j < row; j++)
{
*(p+j*row+i) = Creat_M(buffer, i, j, row)/determ;
}
}
cout<<"----------------------------------"<<endl;
cout << "求出的逆矩阵为: " << endl;
print(p, row); //打印该矩阵
cout<<"----------------------------------"<<endl;
}
else
{
cout << "行列式为0,没有逆矩阵!\n";
}
free(buffer); //释放内存空间
cout <<"开始验证:"<<endl;
cout << "采用部分主元的高斯消去法求方阵的逆矩阵!\n";
cout << "请输入方阵的阶数: ";
cin >> n;
cout << "请输入" << n << "阶方阵: \n";
//输入一个n阶方阵
for (i = 0; i < n; i++)
{
cout << "请输入验证矩阵的第" << i+1 << " 行: "<<endl;
for (j = 0; j < n; j++)
{
cin >> a[i][j];
}
}
cout<<"----------------------------------"<<endl;
cout << "你输入的验证矩阵为 : \n";
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
cout << a[i][j]<<" ";
}
cout <<endl;
}
cout<<"----------------------------------"<<endl;
//运用高斯消去法求该矩阵的逆矩阵并输出
if (Gauss(a, b, n))
{
cout << "验证后,该方阵的逆矩阵为: \n";
cout<<"----------------------------------"<<endl;
for (i = 0; i < n; i++)
{
cout << setw(4);
for (j = 0; j < n; j++)
{
cout << b[i][j] << setw(10);
}
cout << endl;
}
cout<<"----------------------------------"<<endl;
}
getchar();
return 0;
}
//-----------------------------------------------
//功能: 求矩阵(n*n)的行列式
//入口参数: 矩阵的首地址,矩阵的行数
//返回值: 矩阵的行列式值
//----------------------------------------------
float MatDet(float *p, int n)
{
cout <<"方法一:通过公式来求逆矩阵=矩阵*伴随矩阵" <<endl;
int r, c, m;
int lop = 0;
float result = 0;
float mid = 1;
if (n != 1)
{
lop = (n == 2) ? 1 : n; //控制求和循环次数,若为2阶,则循环1次,否则为n次
for (m = 0; m < lop; m++)
{
mid = 1; //顺序求和, 主对角线元素相乘之和
for (r = 0, c = m; r < n; r++, c++)
{
mid = mid * (*(p+r*n+c%n));
}
result += mid;
}
for (m = 0; m < lop; m++)
{
mid = 1; //逆序相减, 减去次对角线元素乘积
for (r = 0, c = n-1-m+n; r < n; r++, c--)
{
mid = mid * (*(p+r*n+c%n));
}
result -= mid;
}
}
else
result = *p;
return result;
}
//----------------------------------------------------------------------------
//功能: 求k*k矩阵中元素A(m, n)的代数余之式
//入口参数: k*k矩阵的首地址,矩阵元素A的下标m,n,矩阵行数k
//返回值: k*k矩阵中元素A(m, n)的代数余之式
//----------------------------------------------------------------------------
float Creat_M(float *p, int m, int n, int k)
{
int len;
int i, j;
float mid_result = 0;
int sign = 1;
float *p_creat, *p_mid;
len = (k-1)*(k-1); //k阶矩阵的代数余之式为k-1阶矩阵
p_creat = (float*)calloc(len, sizeof(float)); //分配内存单元
p_mid = p_creat;
for (i = 0; i < k; i++)
{
for (j = 0; j < k; j++)
{
if (i != m && j != n) //将除第i行和第j列外的所有元素存储到以p_mid为首地址的内存单元
{
*p_mid++ = *(p+i*k+j);
}
}
}
sign = (m+n)%2 == 0 ? 1 : -1; //代数余之式前面的正、负号
mid_result = (float)sign*MatDet(p_creat, k-1);
free(p_creat);
return mid_result;
}
//-----------------------------------------------------
//功能: 打印n*n矩阵
//入口参数: n*n矩阵的首地址,矩阵的行数n
//返回值: 无返回值
//-----------------------------------------------------
void print(float *p, int n)
{
int i, j;
for (i = 0; i < n; i++)
{
cout << setw(4);
for (j = 0; j < n; j++)
{
cout << setiosflags(ios::right) << *p++ << setw(10);
}
cout << endl;
}
}
//------------------------------------------------------------------
//功能: 采用部分主元的高斯消去法求方阵A的逆矩阵B
//入口参数: 输入方阵,输出方阵,方阵阶数
//返回值: true or false
//-------------------------------------------------------------------
bool Gauss(float A[][N], float B[][N], int n)
{
cout <<"方法二:通过高斯消去法求逆矩阵" <<endl;
int i, j, k;
float max, temp;
float t[N][N]; //临时矩阵
//将A矩阵存放在临时矩阵t[n][n]中
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
t[i][j] = A[i][j];
}
}
//初始化B矩阵为单位阵
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
B[i][j] = (i == j) ? (float)1 : 0;
}
}
for (i = 0; i < n; i++)
{
//寻找主元
max = t[i][i];
k = i;
for (j = i+1; j < n; j++)
{
if (fabs(t[j][i]) > fabs(max))
{
max = t[j][i];
k = j;
}
}
//如果主元所在行不是第i行,进行行交换
if (k != i)
{
for (j = 0; j < n; j++)
{
temp = t[i][j];
t[i][j] = t[k][j];
t[k][j] = temp;
//B伴随交换
temp = B[i][j];
B[i][j] = B[k][j];
B[k][j] = temp;
}
}
//判断主元是否为0, 若是, 则矩阵A不是满秩矩阵,不存在逆矩阵
if (t[i][i] == 0)
{
cout << "这里没有逆矩阵!";
return false;
}
//消去A的第i列除去i行以外的各行元素
temp = t[i][i];
for (j = 0; j < n; j++)
{
t[i][j] = t[i][j] / temp; //主对角线上的元素变为1
B[i][j] = B[i][j] / temp; //伴随计算
}
for (j = 0; j < n; j++) //第0行->第n行
{
if (j != i) //不是第i行
{
temp = t[j][i];
for (k = 0; k < n; k++) //第j行元素 - i行元素*j列i行元素
{
t[j][k] = t[j][k] - t[i][k]*temp;
B[j][k] = B[j][k] - B[i][k]*temp;
}
}
}
}
getchar();
return true;
}