鞍点的求解以及对称矩阵的存储和数据的获取



1.鞍点


如果在一个矩阵中,出现了一个数,它在矩阵中的所在的行里是最小的,但在所在的列里是最大的,测称这个数是这个矩阵的一个鞍点。


2、鞍点求解思路

首先先求出第一行中最小的数,然后求该数在所在列是否是最小,是的话说明是鞍点,否的话继续求下一行最小的数,接着循环求证是否是所在列最小。代码如下:


/*
鞍点,如果aij在第i行中最小但在第j列中最大,就是鞍点
*/

#include<iostream>

void printlnSaddlePoint(int group[5][5])
{
	//先求出改行中最小的值,然后再看其在该列中是否是最小值。然后继续判断下一行。

	for (int i = 0; i < 5; i++)//遍历每一行
	{
		int min = group[i][0];
		int minCol = 0;
		for (int k = 1; k < 5; k++)
		{
			if (group[i][k] < min)
			{
				min = group[i][k];
				minCol = k;
			}
		}
		//此时找出了行中最小数所在列
	    //判断该数时候在该列中是最大
		int j = 0;
		for (; j < 5; j++)
		{
			if (group[j][minCol]>group[i][minCol])//一旦出现比它大的数说明就不是鞍点
			{
				break;
			}
		}

		if (j == 5)
		{
			std::cout << "出现鞍点,位于第" << i << "行第" << minCol << "列,值是" << group[i][minCol] << std::endl;
			for (int m = 0; m < 5; m++)
			{
				for (int n = 0; n < 5; n++)
				{
					std::cout << group[m][n] << " ";
				}
				std::cout <<std::endl;
			}
		}

	}
}


main.cpp如下:

#include "SaddlePoint.h"
#include <math.h>

int main()
{

	int group[5][5] = {  };
	int k = 0;
	while (k<1000)
	{
		for (int i = 0; i < 5; i++)
		{
			for (int j = 0; j < 5; j++)
				group[i][j] = rand();
		}
		printlnSaddlePoint(group);
		k++;
	}
	
	
	system("pause");
	return 0;
}




3.对称矩阵



沿着矩阵对角线对折,所有的数都相等,则称为对角矩阵。对于对角矩阵而言,由于它的上三角(左上角到右下角为对角线,处于对角线上面的数)和下三角的数十一样的,所以我们只需要存储下三角和对角线的数即可,这样如果矩阵的阶是很大的话,可以节省出很多空间。


4、对称矩阵的存储与读取

关于求解思路,我在注释里面结合详细的例子给出了说明,这里就不再累赘。

/*
对称矩阵的存储与获取
*/
#include <algorithm>
#include <vector>

/*
初始化一个对称矩阵
这里只保存下三角的元素和对角线的元素
pOriginalGroup 含有数据源的数组指针
rowAndCol 阶数
pSaveGroup 保存数据的数组指针
*/
std::vector<int> initSymmetricMatrix(int *pOriginalGroup, int rowAndCol)
{
	/*
	1,2,3,4,5
	2,7,8,9,8
	3,8,9,8,7
	4,9,8,3,1
	5,8,7,1,5
	*/

	/*
	假设这里有一个N阶矩阵,则每行需要存储的元素(可用上述的5阶矩阵进行参考)如下:
	1,2,3,...,n-1,n
	接下来,我们需要计算一个存储常量。
	1,2,  3.., n-1,n
	+  n,n-1,n-2..,2, 1
	得出(n+1)*n/2
	即我们要存储的数量的总和了
	*/

	int sum = (rowAndCol + 1)*rowAndCol / 2;         //保存的数组长度

	/*
	以上面的5阶矩阵为例子,就需要存储15个元素。要存储的元素如下:
	group[15]{1,2,7,3,8,9,4,9,8,3,5,8,7,1,5}
	接下来就需要研究第i行第j列的元素与数组group的下标k的关系了,这样才能确定,第几个元素是几行几列。
	我们可以发现:
	1是第一行
	2,7是第二行
	3,8,9是第三行
	可以发现,i>=j,在这个前提下推理第i行第j列的元素存储在group的下标的关系:
	第i行元素之前存储了(i-1)+(i-2)+....+1,结果是i*(i-1)/2
	在第i行的时候,改行保存了(j-1)个元素,则k与i,j的关系如下
	k=i*(i-1)/2+(j-1)
	*/

	int k = 0;//数组下标
	int rule = 0;//记录当前下标应该对应的行列数
	std::vector<int> vect(sum);

	for (int i = 1; i <= rowAndCol; i++)
	{
		for (int j = 1; j <= rowAndCol; j++)
		{
			rule = i*(i - 1) / 2 + (j - 1);//记录按照保存规则,当前元素是否需要保存,只有满足表达式的才需要保存
			if (k == rule&&i>=j)
			{
				vect[k]=(*(pOriginalGroup + (i-1)*rowAndCol + j - 1));
				k++;
			}
				
		}
	}

	return vect;
}


/*
获取第row行第col列的元素
pGroup表示保存着存储元素的数据的数组指针
n表示阶数
*/
int getElement(int row, int col, int n, std::vector<int>::iterator iter)
{
	/*
	由上面可知道,k=(i-1)*i/2+(j-1),前提是,i>=j的情况下
	如果在i<j的情况下,即当前获取的元素是上三角的元素,应该怎么判断i,j和k的关系呢
	我们知道a[i][j]=a[j][i]
	即在i<j的情况下,
	k=(j-1)*j/2+(i-1)


	所以有
	{k=(i-1)*i/2+(j-1),i>=j;k=(j-1)*j/2+(i-1),i<j;}

	即最大的数总是被当作行处理,最小的数,当作列处理

	*/

	int maxNum = std::max(row, col);
	int minNum = std::min(row, col);

	if (maxNum == minNum)
		return *(iter + (maxNum-1)*maxNum/2 + maxNum - 1);
	else
		return *(iter + ((maxNum - 1)*maxNum / 2 + (minNum - 1)));
}



main.cpp


#include <iostream>
#include "SymmetricMatrixs.h"



int main()
{

	int group[5][5] = {
		{ 1, 2, 3, 4, 5 },
		{ 2, 7, 8, 9, 8 },
		{ 3, 8, 9, 8, 7 },
		{ 4, 9, 8, 3, 1 },
		{ 5, 8, 7, 1, 5 } };

	
	std::vector<int> vect = initSymmetricMatrix(&group[0][0], 5);

	for (int i = 1; i <= 5; i++)
	{
		for (int j = 1; j <= 5; j++)
		{
			std::cout << getElement(i, j,5,vect.begin())<<" ";
		}
		std::cout << std::endl;
	}

	system("pause");
	return 0;
}



通过以上就可以达到存储对称矩阵的所有元素,并节省空间的做法了。


---------文章写自:HyHarden---------

--------博客地址:http://blog.csdn.net/qq_25722767-----------




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值