C/C++ - Изменение двухмерных массивов

Ответить
Аватара пользователя
mrcnn

C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

Как сделать так, чтобы была задействована только одна матрица?



Поэлементно что ли копировать? Предположим я поэлементно копирую в матрицу из промежуточного одномерного массива? А потом опять поэлементно заменять содержимое одномерного массива и снова копировать в матрицу?





Код:

Код: Выделить всё

	int matrix[X][Y] = {
		{4,-3,-3,4}, 
		{4,-1,0,5},
		{5,1,5,9}};
	kramer(matrix);
	int matrix1[X][Y] = {
		{3,-5,0,8}, 
		{3,-5,1,9},
		{-4,1,1,4}};
	kramer(matrix1);
	int matrix2[X][Y] = {
		{-4,2,-5,-11}, 
		{-1,2,-2,-5},
		{5,4,1,2}};
	kramer(matrix2);
	int matrix3[X][Y] = {
		{-2,3,-5,-20}, 
		{-5,1,5,-2},
		{-2,3,-3,-16}};
	kramer(matrix3);
	int matrix4[X][Y] = {
		{-2,4,0,-12}, 
		{2,3,1,0},
		{3,5,-1,-6}};
	kramer(matrix4);
	int matrix5[X][Y] = {
		{5,4,3,8}, 
		{-4,2,1,-10},
		{2,4,4,4}};
	kramer(matrix5);
	int matrix6[X][Y] = {
		{3,5,3,3}, 
		{3,5,-5,-21},
		{2,0,1,9}};
	kramer(matrix6);/**/

Я хотел сначала сделать так, но так нельзя



Код:

Код: Выделить всё

int matrix[X][Y] = {
		{4,-3,-3,4}, 
		{4,-1,0,5},
		{5,1,5,9}};
kramer(matrix);
	matrix[X][Y] = {
		{3,-5,0,8}, 
		{3,-5,1,9},
		{-4,1,1,4}};
	kramer(matrix);
Аватара пользователя
mrcnn

Re: C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

1. как объявить указатель на двухмерный массив?



2. как передать двухмерный массив в функцию?



3. как описать функцию, которая получает указатель на двухмерный массив?



Код: Выделить всё

/*
вычеркивание из матрицы d строки и i столбца и 
копирование полученной вычеркиванием матрицы в data
*/
#include <stdio.h>
#define X 3
void main()
{
	int matrix[X][X] = {
		{4,-3,-3}, 
		{4,-1,0},
		{5,1,5}};
	int size=X-1;
	int **data; /*как описать этот указатель правильно*/
	int d=0;
	int i=0;
	int k,l,datai,dataj;
	data = new int[size][size];
	datai=0;
	dataj=0;
	for (k=0 ; k<X; k++) //проход про строкам
		{
			if (k != d){
				for (l=0; l<X;l++) //проход по столбцам строки
				{
					if (l!=i){
						data[datai][dataj]=matrix[k][l];
						dataj++;
					}
				}
				datai++;
				dataj=0;
			}
		}
	for (k=0;k<size;k++)
	{
		for(l=0;l<size;l++)
		{
		printf("%d ",data[k][l]);
		}
		printf("\n");
	}
	delete[] data;
}
Аватара пользователя
mrcnn

Re: C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

С первым вопросом вроде бы разобрался.

Код: Выделить всё

#include <stdio.h>
#define X 3
void main()
{
	int matrix[X][X] = {
		{4,-3,-3}, 
		{4,-1,0},
		{5,1,5}};
	int size=X-1;
	int** data; /*как описать этот указатель правильно*/
	int d=0;
	int i=0;
	int k,l,datai,dataj;
	data = new int*[size];
	for(k=0;k<size;k++)
	{
		data[k]=new int[size];
	}
	datai=0;
	dataj=0;
	for (k=0 ; k<X; k++) //проход про строкам
		{
			if (k != d){
				for (l=0; l<X;l++) //проход по столбцам строки
				{
					if (l!=i){
						*((*(data+datai))+dataj)=matrix[k][l];
						dataj++;
						//printf ("matrix[%d][%d]=%d\n", k,l,matrix[k][l]);
					}
				}
				datai++;
				dataj=0;
			}
		}
	for (k=0;k<size;k++)
	{
		for(l=0;l<size;l++)
		{
		printf("%d ",data[k][l]);
		}
		printf("\n");
	}
	for(k=0;k<size;k++)
	{
		delete[] data[k];
	}
	delete[] data;
}
Аватара пользователя
mrcnn

Re: C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

Написал нахождение определителя разложением по строке заодно разобрался с двухмерными массивами. Хотя алгоритм очень неэффективный из-за копирования . Можно и без копирования обойтись, но там нужно как-то пересчет индексов для алгебраического дополнения делать, чтобы -1 возвести в нужную степень.





Код: Выделить всё

#include <stdio.h>
#include <windows.h>
#include <time.h>
#define XYZZ 10
void print_matrix(int **m);
void random_matrix(int **m);
int opredelitel(int **m, int d,int sz);
int poww(int,int);
void main()
{
int mainopr;
	int size=XYZZ;
	int** matrix;
	matrix = new int*[size];
	for(int k=0;k<size;k++)
		{
		matrix[k]=new int[size];
		}
	random_matrix(matrix);
	print_matrix(matrix);
	mainopr=opredelitel(matrix,0,XYZZ);
	printf("%d\n",mainopr);
}
void print_matrix(int **m)
{
int i,j;
for (i=0 ; i<XYZZ; i++)
	{
		for (j=0; j<XYZZ;j++)
		{
			printf("%d ", m[i][j]);
		}
		printf("\n");
	}
}
void random_matrix(int **m)
{
int i,j;
srand (time(NULL));
for (i=0 ; i<XYZZ; i++)	
	for (j=0; j<XYZZ;j++)		
		m[i][j]=rand()%10;
}
int opredelitel(int **m, int d,int sz)
{
	int** data;
	int result, size,i,k,l,reali,realj,datai,dataj,n,correction,t;
	result = 0;
	if ( sz > 2){
		for( i = 0 , reali = d+1 , realj = i+1; i < sz ; i++ , realj=i+1)
		{
			correction = poww(-1,reali+realj);     // (-1)^(i+j)
				// копирование матрицы
				size = sz - 1;
				data = new int*[size];
				for(k=0;k<size;k++)
				{
					data[k]=new int[size];
				}
				datai=0;
				dataj=0;
				for (k=0 ; k<sz; k++) //проход про строкам
				{
					if (k != d){
						for (l=0; l<sz;l++) //проход по столбцам строки
						{
							if (l!=i){
								data[datai][dataj]=m[k][l];
								dataj++;
							}
						}
						datai++;
						dataj=0;						
					}
				}
				n=opredelitel(data,0,size);
				t=m[d][i]*correction*n;
				result+=t;
			}
		}
	else
		{
			if (sz==2)
				{
				return (m[0][0]*m[1][1]-m[0][1]*m[1][0]);
				}
			else
			{
				if (sz==1)
					{
					return (m[0][0]);
					}			
				else 
					{
					printf ("Error");
					return (-1);
					}
			}
		}
	return(result);	
}
int poww(int d,int t){
	int st=1;
	int result=1;
	for(st=1; st<=t; st++)
	{
		result*=d;
	}
	return (result);
}
Аватара пользователя
mrcnn

Re: C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

Нахождение определителя редукцией.

Количество действий

(n-1)*n+(n-2)*(n-1)+..+3*2+2*1

где n - размерность квадратной матрицы



Код: Выделить всё

#include <stdio.h>
#include <windows.h>
#include <time.h>
#define XYZZ 10
void print_matrix(double **m);
void random_matrix(double **m);
double opredelitel(double **m, int sz);
int poww(int,int);
void change_lines(double **m, int d,int t);
void main()
{
	double mainopr;
	int size=XYZZ;
	double** matrix;
	matrix = new double*[size];
	for(int k=0;k<size;k++)
		{
		matrix[k]=new double[size];
		}	
	random_matrix(matrix);
	print_matrix(matrix);
	mainopr=opredelitel(matrix,XYZZ);
	printf("%f\n",mainopr);
	for(k=0;k<XYZZ;k++)
	{
		delete[] matrix[k];
	}
	delete[] matrix;
}
void print_matrix(double **m)
{
int i,j;
for (i=0 ; i<XYZZ; i++)
	{
		for (j=0; j<XYZZ;j++)
		{
			printf("%f ", m[i][j]);
		}
		printf("\n");
	}
}
void random_matrix(double **m)
{
int i,j;
srand (time(NULL));
for (i=0 ; i<XYZZ; i++)	
	for (j=0; j<XYZZ;j++)		
		m[i][j]=rand()%10;
}
double opredelitel(double **m, int sz)
{
	double x,result;
	int i,j,k,l,n, num_of_changes;
	result = 1;
	num_of_changes=0;
	if ( sz > 2)
		{
			for(i=0,j=0;i<sz-1;i++,j++)
				{
					if (m[i][j]==0)
						{
						//ищем строку, где не равны нулю, и переставляем
							for(k=i+1;k<sz;k++)
							{
								if(m[k][j]!=0)
								{
									change_lines(m,i,k);
									num_of_changes++;
									break;
								}
							}
						}
					//m[i][j] не равен 0
					//проход по строке l
					for(l=i+1;l<sz;l++)
						{							
							if (m[l][j] != 0)
								{
									//m[0][0]*x+m[1][0]=0 => x=-m[1][0]/m[0][0]
									//x=-m[1][0]/m[0][0];
									x=-m[l][j]/m[i][j];
									//проход по столбцу
									for (n=j;n<sz;n++)
									{
										m[l][n]=m[i][n]*x+m[l][n];											
									}
								}
						}
				}
		}
	else if (sz==2)
		{
		return (m[0][0]*m[1][1]-m[0][1]*m[1][0]);
		}
	else if (sz==1)
		{
		return (m[0][0]);
		}			
	else 
		{
		printf ("Error");
		return (-1);
		}
	for(i=0,j=0;i<sz;i++,j++)
	{
		result *= m[i][j] ;
	}
	result *= poww(-1,num_of_changes);
	return(result);	
}
void change_lines(double **m, int d,int t)
{
	int i;
	double temp;
	for (i=0;i< XYZZ;i++)
	{
		temp=m[d][i];
		m[d][i]=m[t][i];
		m[t][i]=temp;
	}
}
int poww(int d,int t){
	int st=1;
	int result=1;
	for(st=1; st<=t; st++)
	{
		result*=d;
	}
	return (result);
}
Аватара пользователя
mrcnn

Re: C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

Нахождение обратной матрицы

В качестве матрицы взята матрица из №840 учебника Проскурякова



Код: Выделить всё

#include <stdio.h>
#include <windows.h>
#include <time.h>
#define XYZZ 3
void print_matrix(double **m, int sz);
void random_matrix(double **m, int sz);
double opredelitel(double **m, int sz);
void obratnaya_matrix(double **m, double **newm, double mainopr, int sz);
int poww(int,int);
void change_lines(double **m, int sz, int d,int t);
void copy_matrix(double **m, double **newm, int sz);
void copy_matrix(double **m, double **newm, int sz, int d, int i);
void main()
{
	double mainopr;
	int size=XYZZ;
	double** matrix;
	double** newmatrix;
	matrix = new double*[size];
	newmatrix = new double*[size];
	for(int k=0;k<size;k++)
		{
		matrix[k]=new double[size];
		newmatrix[k]=new double[size];
		}
	matrix[0][0]=2;matrix[0][1]=5;matrix[0][2]=7;
	matrix[1][0]=6;matrix[1][1]=3;matrix[1][2]=4;	
	matrix[2][0]=5;matrix[2][1]=-2;matrix[2][2]=-3;/*Учебник Проскурякова №840*/
	//random_matrix(matrix);
	print_matrix(matrix,size);
	mainopr=opredelitel(matrix,size);
	printf("Main determinant: %f\n",mainopr);
	/*Обратная матрица существует, если определитель не равен нулю*/
	if (mainopr !=0)
	{
		obratnaya_matrix(matrix, newmatrix, mainopr, size);
		printf("Obratnaya matritsa: \n");
		print_matrix(newmatrix,size);
	}
	else
	{
		printf("Net obratnoy matricy\n");
	}
	for(k=0;k<size;k++)
	{
		delete[] matrix[k];
		delete[] newmatrix[k];
	}
	delete[] matrix;
	delete[] newmatrix;
}
void print_matrix(double **m, int sz)
{
int i,j;
for (i=0 ; i<sz; i++)
	{
		for (j=0; j<sz;j++)
		{
			printf("%f ", m[i][j]);
		}
		printf("\n");
	}
}
void random_matrix(double **m, int sz)
{
int i,j;
srand (time(NULL));
for (i=0 ; i<sz; i++)	
	for (j=0; j<sz;j++)		
		m[i][j]=rand()%10;
}
void copy_matrix(double **m, double **newm, int sz)
{
	int i,j;
	for (i=0 ; i<sz; i++)	
		for (j=0; j<sz;j++)		
			newm[i][j]=m[i][j];
}
void copy_matrix(double **m, double **newm, int sz, int d, int i)
{
	int k,l,newmi,newmj;
	newmi=0;
	newmj=0;
	for (k=0 ; k<sz; k++) 
		{
		if (k != d)
			{
				for (l=0; l<sz;l++)
				{
					if (l!=i)
					{
						newm[newmi][newmj]=m[k][l];
						newmj++;
					}
				}
				newmi++;
				newmj=0;						
			}
		}
}
double opredelitel(double **m, int sz)
{
	double x,result;
	int i,j,k,l,n, num_of_changes;
	double** matrix_copy;
	matrix_copy = new double*[sz];
	for(k=0;k<sz;k++)
		matrix_copy[k]=new double[sz];
	copy_matrix(m,matrix_copy,sz);
	result = 1;
	num_of_changes=0;
	if ( sz > 2)
		{
			for(i=0,j=0;i<sz-1;i++,j++)
				{
					if (matrix_copy[i][j]==0)
						{						
							for(k=i+1;k<sz;k++)
							{
								if(matrix_copy[k][j]!=0)
								{
									change_lines(matrix_copy,sz,i,k);
									num_of_changes++;
									break;
								}
							}
						}
					for(l=i+1;l<sz;l++)
						{							
								if (matrix_copy[l][j] != 0)
									{
										x=-matrix_copy[l][j]/matrix_copy[i][j];
										for (n=j;n<sz;n++)
										{
											matrix_copy[l][n]=matrix_copy[i][n]*x+matrix_copy[l][n];
										}
									}
						}
				}
		}
	else if (sz==2)
		{
		return (m[0][0]*m[1][1]-m[0][1]*m[1][0]);
		}
	else if (sz==1)
		{
		return (m[0][0]);
		}			
	else 
		{
		printf ("Error");
		return (-1);
		}
	for(i=0,j=0;i<sz;i++,j++)
	{
		result *= matrix_copy[i][j] ;
	}
	result *= poww(-1,num_of_changes);
	for(k=0;k<sz;k++)
		delete[] matrix_copy[k];	
	delete[] matrix_copy;
	return(result);	
}
void change_lines(double **m, int sz, int d,int t)
{
	int i;
	double temp;
	for (i=0;i< sz;i++)
	{
		temp=m[d][i];
		m[d][i]=m[t][i];
		m[t][i]=temp;
	}
}
int poww(int d,int t){
	int st=1;
	int result=1;
	for(st=1; st<=t; st++)
	{
		result*=d;
	}
	return (result);
}
void obratnaya_matrix(double **m, double **newm, double mainopr, int sz)
{	
	/*
	Алгоритм
	1. находим алгебраической дополнение
	2. делим алг. дополнение на определитель
	3. заносим в новую матрицу
	*/
	double** data;
	int size, i,j,k,reali,realj,correction;
	double opr, obr_element;
	size = sz - 1;//Размер алгебраического дополнения
	for (i=0;i<sz;i++)
	{
		for( j=0;j<sz;j++)
		{
			//алгебраическое дополнение
			data = new double*[size]; 
			for(k=0;k<size;k++)
			{
				data[k]=new double[size];
			}
			// Находим алгебраическое дополнение
			// Вычеркиваемая строка  i,j
			copy_matrix(m, data,sz,i,j);
			//Находим определитель алгебраического дополнения
			opr=opredelitel(data,size);	
			reali=i+1;
			realj=j+1;
			correction = poww(-1,reali+realj);
			//Уничтожаем алгебраическое дополнение
			for(k=0;k<size;k++)
				{
					delete[] data[k];
				}
			delete[] data;
			//Находим обратный элемент
			obr_element = (opr*correction)/mainopr;
			//Заносим в обратную матрицу
			newm[j][i]=obr_element;
		}
	}
}
Аватара пользователя
mrcnn

Re: C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

Решение системы линейных уравнений методом Крамера



Код: Выделить всё

#include <stdio.h>
#include <windows.h>
#include <time.h>
#define XYZZ 4
void print_matrix(double **m, int sz);
void print_vector(double *m, int sz);
void random_matrix(double **m, int sz);
void random_vector(double *m, int sz);
double opredelitel(double **m, int sz);
void change_lines(double **m, int sz, int d,int t);
int poww(int,int);
void copy_matrix(double **m, double **newm, int sz);
void change_column_matrix(double **m, double **newm, double *line, int num_column, int sz);
void kramer(double **m, double *line, double mainopr,int sz);
void main()
{
	double mainopr;
	int size=XYZZ;
	double* line;
	double** matrix;
	matrix = new double*[size];	
	for(int k=0;k<size;k++)
	{
		matrix[k]=new double[size];		
		}
	line = new double[size];
	/* Проскуряков #567*/
	/*matrix[0][0]=3;matrix[0][1]=-2;matrix[0][2]=-5;matrix[0][3]=1;
	matrix[1][0]=2;matrix[1][1]=-3;matrix[1][2]=1;matrix[1][3]=5;	
	matrix[2][0]=1;matrix[2][1]=2;matrix[2][2]=0;matrix[2][3]=-4;
	matrix[3][0]=1;matrix[3][1]=-1;matrix[3][2]=-4;matrix[3][3]=9;
	line[0]=3; line[1]=-3; line[2]=-3;line[3]=22;/**/
	/* Проскуряков #568*/
	/*matrix[0][0]=4;matrix[0][1]=-3;matrix[0][2]=1;matrix[0][3]=5;
	matrix[1][0]=1;matrix[1][1]=-2;matrix[1][2]=-2;matrix[1][3]=-3;	
	matrix[2][0]=3;matrix[2][1]=-1;matrix[2][2]=2;matrix[2][3]=0;
	matrix[3][0]=2;matrix[3][1]=3;matrix[3][2]=2;matrix[3][3]=-8;
	line[0]=7; line[1]=3; line[2]=-1;line[3]=-7;/**/
	random_matrix(matrix,size);
	printf("Matrix:\n");
	print_matrix(matrix,size);
	random_vector(line,size);
	printf("Vector:\n");
	print_vector(line,size);	
	mainopr=opredelitel(matrix,size);
	printf("Main determinant: %f\n",mainopr);
	if (mainopr !=0)
	{
		printf("Reshenie: \n");
		kramer(matrix, line,mainopr, size);
	}
	else
	{
		printf("Systema nekramerovskaya\n");
	}
	for(k=0;k<size;k++)
	{
		delete[] matrix[k];			
	}
	delete[] matrix;
	delete[] line;	
}
void kramer(double **m, double *line, double mainopr,int sz)
{
	int i;
	double** newmatrix;
	double x;
	newmatrix = new double*[sz];
	for(int k=0;k<sz;k++)
	{
		newmatrix[k]=new double[sz];
	}
	for(i=0; i<sz;i++)
	{
		change_column_matrix(m, newmatrix, line, i, sz);
		x=opredelitel(newmatrix,sz)/mainopr;
		printf("x[%d]=%f\n",i,x);
	}
	for(k=0;k<sz;k++)
	{
		delete[] newmatrix[k];
	}
	delete[] newmatrix;
}
void change_column_matrix(double **m, double **newm, double *line, int num_column, int sz)
{
	int i,j;
	if (num_column <sz){
		for (i=0 ; i<sz; i++)
		{	
			for (j=0; j<sz;j++)	
			{	
				if (j != num_column)
				{
					newm[i][j]=m[i][j];
				}
				else
				{
					newm[i][j]=line[i];
				}
			}
		}
	}
	else
	{
		printf("Error\n");
	}
}
void print_matrix(double **m, int sz)
{
int i,j;
for (i=0 ; i<sz; i++)
	{
		for (j=0; j<sz;j++)
		{
			printf("%f ", m[i][j]);
		}
		printf("\n");
	}
}
void print_vector(double *m, int sz)
{
int i;
for (i=0 ; i<sz; i++)
	printf("%f ", m[i]);
printf("\n");
}
void random_matrix(double **m, int sz)
{
int i,j;
srand (time(NULL));
for (i=0 ; i<sz; i++)	
	for (j=0; j<sz;j++)		
		m[i][j]=rand()%10;
}
void random_vector(double *m, int sz)
{
int i;
srand (time(NULL));
for (i=0 ; i<sz; i++)	
		m[i]=rand()%10;
}
void copy_matrix(double **m, double **newm, int sz)
{
	int i,j;
	for (i=0 ; i<sz; i++)	
		for (j=0; j<sz;j++)		
			newm[i][j]=m[i][j];
}
double opredelitel(double **m, int sz)
{
	double x,result;
	int i,j,k,l,n, num_of_changes;
	double** matrix_copy;
	matrix_copy = new double*[sz];
	for(k=0;k<sz;k++)
		matrix_copy[k]=new double[sz];
	copy_matrix(m,matrix_copy,sz);
	result = 1;
	num_of_changes=0;
	if ( sz > 2)
		{
			for(i=0,j=0;i<sz-1;i++,j++)
				{
					if (matrix_copy[i][j]==0)
						{						
							for(k=i+1;k<sz;k++)
							{
								if(matrix_copy[k][j]!=0)
								{
									change_lines(matrix_copy,sz,i,k);
									num_of_changes++;
									break;
								}
							}
						}
					for(l=i+1;l<sz;l++)
						{							
								if (matrix_copy[l][j] != 0)
									{
										x=-matrix_copy[l][j]/matrix_copy[i][j];
										for (n=j;n<sz;n++)
										{
											matrix_copy[l][n]=matrix_copy[i][n]*x+matrix_copy[l][n];
										}
									}
						}
				}
		}
	else if (sz==2)
		{
		return (m[0][0]*m[1][1]-m[0][1]*m[1][0]);
		}
	else if (sz==1)
		{
		return (m[0][0]);
		}			
	else 
		{
		printf ("Error");
		return (-1);
		}
	for(i=0,j=0;i<sz;i++,j++)
	{
		result *= matrix_copy[i][j] ;
	}
	result *= poww(-1,num_of_changes);
	for(k=0;k<sz;k++)
		delete[] matrix_copy[k];	
	delete[] matrix_copy;
	return(result);	
}
void change_lines(double **m, int sz, int d,int t)
{
	int i;
	double temp;
	for (i=0;i< sz;i++)
	{
		temp=m[d][i];
		m[d][i]=m[t][i];
		m[t][i]=temp;
	}
}
int poww(int d,int t){
	int st=1;
	int result=1;
	for(st=1; st<=t; st++)
	{
		result*=d;
	}
	return (result);
}
Аватара пользователя
mrcnn

Re: C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

Решение системы линецных уравнений методом обратной матрицы



Код: Выделить всё

#include <stdio.h>
#include <windows.h>
#include <time.h>
#define XYZZ 4
void print_matrix(double **m, int sz);
void print_vector(double *m, int sz);
void random_matrix(double **m, int sz);
void random_vector(double *m, int sz);
double opredelitel(double **m, int sz);
void obratnaya_matrix(double **m, double **newm, double mainopr, int sz);
int poww(int,int);
void change_lines(double **m, int sz, int d,int t);
void copy_matrix(double **m, double **newm, int sz);
void copy_matrix(double **m, double **newm, int sz, int d, int i);
void multiplicate_matrix_and_vector(double **m, double *line, double *result, double mainopr,int sz);
void main()
{
	double mainopr;
	int size=XYZZ;
	double* line;
	double* result;
	double** matrix;
	matrix = new double*[size];	
	for(int k=0;k<size;k++)
	{
		matrix[k]=new double[size];		
		}
	line = new double[size];
	result = new double[size];
	/* Проскуряков #567*/
	/*matrix[0][0]=3;matrix[0][1]=-2;matrix[0][2]=-5;matrix[0][3]=1;
	matrix[1][0]=2;matrix[1][1]=-3;matrix[1][2]=1;matrix[1][3]=5;	
	matrix[2][0]=1;matrix[2][1]=2;matrix[2][2]=0;matrix[2][3]=-4;
	matrix[3][0]=1;matrix[3][1]=-1;matrix[3][2]=-4;matrix[3][3]=9;
	line[0]=3; line[1]=-3; line[2]=-3;line[3]=22;/**/
	matrix[0][0]=4;matrix[0][1]=-3;matrix[0][2]=1;matrix[0][3]=5;
	matrix[1][0]=1;matrix[1][1]=-2;matrix[1][2]=-2;matrix[1][3]=-3;	
	matrix[2][0]=3;matrix[2][1]=-1;matrix[2][2]=2;matrix[2][3]=0;
	matrix[3][0]=2;matrix[3][1]=3;matrix[3][2]=2;matrix[3][3]=-8;
	line[0]=7; line[1]=3; line[2]=-1;line[3]=-7;
	//random_matrix(matrix,size);
	printf("Matrix:\n");
	print_matrix(matrix,size);
	//random_vector(line,size);
	printf("Vector:\n");
	print_vector(line,size);	
	mainopr=opredelitel(matrix,size);
	printf("Main determinant: %f\n",mainopr);
	if (mainopr !=0)
	{
		printf("Reshenie metodom obratn matricy: \n");
		multiplicate_matrix_and_vector(matrix, line,result, mainopr, size);
	}
	else
	{
		printf("Matritsa ne imeet obratnoy. Metod neprimenim\n");
	}
	for(k=0;k<size;k++)
	{
		delete[] matrix[k];			
	}
	delete[] matrix;
	delete[] line;
	delete[] result;
}
void print_matrix(double **m, int sz)
{
int i,j;
for (i=0 ; i<sz; i++)
	{
		for (j=0; j<sz;j++)
		{
			printf("%f ", m[i][j]);
		}
		printf("\n");
	}
}
void print_vector(double *m, int sz)
{
int i;
for (i=0 ; i<sz; i++)
	printf("%f ", m[i]);
printf("\n");
}
void random_matrix(double **m, int sz)
{
int i,j;
srand (time(NULL));
for (i=0 ; i<sz; i++)	
	for (j=0; j<sz;j++)		
		m[i][j]=rand()%10;
}
void random_vector(double *m, int sz)
{
int i;
srand (time(NULL));
for (i=0 ; i<sz; i++)	
		m[i]=rand()%10;
}
void copy_matrix(double **m, double **newm, int sz)
{
	int i,j;
	for (i=0 ; i<sz; i++)	
		for (j=0; j<sz;j++)		
			newm[i][j]=m[i][j];
}
void copy_matrix(double **m, double **newm, int sz, int d, int i)
{
	int k,l,newmi,newmj;
	newmi=0;
	newmj=0;
	for (k=0 ; k<sz; k++) 
		{
		if (k != d)
			{
				for (l=0; l<sz;l++)
				{
					if (l!=i)
					{
						newm[newmi][newmj]=m[k][l];
						newmj++;
					}
				}
				newmi++;
				newmj=0;						
			}
		}
}
double opredelitel(double **m, int sz)
{
	double x,result;
	int i,j,k,l,n, num_of_changes;
	double** matrix_copy;
	matrix_copy = new double*[sz];
	for(k=0;k<sz;k++)
		matrix_copy[k]=new double[sz];
	copy_matrix(m,matrix_copy,sz);
	result = 1;
	num_of_changes=0;
	if ( sz > 2)
		{
			for(i=0,j=0;i<sz-1;i++,j++)
				{
					if (matrix_copy[i][j]==0)
						{						
							for(k=i+1;k<sz;k++)
							{
								if(matrix_copy[k][j]!=0)
								{
									change_lines(matrix_copy,sz,i,k);
									num_of_changes++;
									break;
								}
							}
						}
					for(l=i+1;l<sz;l++)
						{							
								if (matrix_copy[l][j] != 0)
									{
										x=-matrix_copy[l][j]/matrix_copy[i][j];
										for (n=j;n<sz;n++)
										{
											matrix_copy[l][n]=matrix_copy[i][n]*x+matrix_copy[l][n];
										}
									}
						}
				}
		}
	else if (sz==2)
		{
		return (m[0][0]*m[1][1]-m[0][1]*m[1][0]);
		}
	else if (sz==1)
		{
		return (m[0][0]);
		}			
	else 
		{
		printf ("Error");
		return (-1);
		}
	for(i=0,j=0;i<sz;i++,j++)
	{
		result *= matrix_copy[i][j] ;
	}
	result *= poww(-1,num_of_changes);
	for(k=0;k<sz;k++)
		delete[] matrix_copy[k];	
	delete[] matrix_copy;
	return(result);	
}
void change_lines(double **m, int sz, int d,int t)
{
	int i;
	double temp;
	for (i=0;i< sz;i++)
	{
		temp=m[d][i];
		m[d][i]=m[t][i];
		m[t][i]=temp;
	}
}
int poww(int d,int t){
	int st=1;
	int result=1;
	for(st=1; st<=t; st++)
	{
		result*=d;
	}
	return (result);
}
void obratnaya_matrix(double **m, double **newm, double mainopr, int sz)
{	
	/*
	Алгоритм
	1. находим алгебраической дополнение
	2. делим алг. дополнение на определитель
	3. заносим в новую матрицу
	*/
	double** data;
	int size, i,j,k,reali,realj,correction;
	double opr, obr_element;
	size = sz - 1;//Размер алгебраического дополнения
	for (i=0;i<sz;i++)
	{
		for( j=0;j<sz;j++)
		{
			//алгебраическое дополнение
			data = new double*[size]; 
			for(k=0;k<size;k++)
			{
				data[k]=new double[size];
			}
			// Находим алгебраическое дополнение
			// Вычеркиваемая строка  i,j
			copy_matrix(m, data,sz,i,j);
			//Находим определитель алгебраического дополнения
			opr=opredelitel(data,size);	
			reali=i+1;
			realj=j+1;
			correction = poww(-1,reali+realj);
			//Уничтожаем алгебраическое дополнение
			for(k=0;k<size;k++)
				{
					delete[] data[k];
				}
			delete[] data;
			//Находим обратный элемент
			obr_element = (opr*correction)/mainopr;
			//Заносим в обратную матрицу
			newm[j][i]=obr_element;
		}
	}
}
void multiplicate_matrix_and_vector(double **m, double *line, double *result, double mainopr,int sz)
{
	int i,j;
	double x;
	double** newmatrix;
	newmatrix = new double*[sz];
	for(int k=0;k<sz;k++)
		{
		newmatrix[k]=new double[sz];
		}
	if (mainopr !=0)
	{
		obratnaya_matrix(m, newmatrix, mainopr, sz);
		printf("Obratnaya matritsa: \n");
		print_matrix(newmatrix,sz);
		for (i=0;i<sz;i++)
		{
			x=0;
			for (j=0; j<sz;j++)
			{				
				x += newmatrix[i][j]*line[j];
							}
			result[i]=x;
			printf("result[%d]=%f\n",i,result[i]);			
		}
	}
	else
	{
		printf("Error\n");
	}
	for(k=0;k<sz;k++)
	{		
		delete[] newmatrix[k];
	}
	delete[] newmatrix;
}
Аватара пользователя
Drongo

Re: C/C++ - Изменение двухмерных массивов

Сообщение Drongo »

mrcnn,
Цитата mrcnn:



Решение системы линецных уравнений методом обратной матрицы
C/C++ - Изменение двухмерных массивов




Давно хотел посмотреть на это решение. Спасибо. Вот ещё ссылка на подобный вопрос -
Нахождение обратной матрицы
, если это конечно, то?
Аватара пользователя
mrcnn

Re: C/C++ - Изменение двухмерных массивов

Сообщение mrcnn »

Цитата Drongo:



Давно хотел посмотреть на это решение. Спасибо. Вот ещё ссылка на подобный вопрос - Нахождение обратной матрицы, если это конечно, то?
C/C++ - Изменение двухмерных массивов




Там по-видимому другой метод используют. Меня учили находить обратную матрицу через алгебраические дополнения. Другие методы я не знаю.



А системы еще можно решить методом блочной матрицы (воздействием на единичную), методом Гаусса. Метод Гаусса решения систем я тоже хочу реализовать, в принципе он простой.



Хочу создать классы для работы с векторами и матрицами, чтобы хорошо разобраться в ООП в С++.
Ответить

Вернуться в «Программирование и базы данных»