5613-4-三对角矩阵的构建与乘法运算

三对角矩阵见百度https://baike.baidu.com/item/%E4%B8%89%E5%AF%B9%E8%A7%92%E7%9F%A9%E9%98%B5

简而言之就是形如A的矩阵为三对角矩阵

图片来自百度百科。

那么,如何通过c语言构建一个三对角矩阵,并进行简单的乘法计算呢?

最容易想到的思路是,既然矩阵中的元素可以根据位置坐标来确定,比如上图中的b_{1}可以通过A_{1,1}来表示,那么,可不可在C语言中用形如A[m][n]的方式来表达呢?

实际上,在C语言中,这种A[m][n]的东西就是所谓的二维数组,http://c.biancheng.net/cpp/html/51.html说的比较清楚。

最简单也最容易实现的就是直接用静态的方式对二维数组赋值、运算啥的;但是,静态数组相较于动态数组,具有一定的局限性,详见:https://blog.csdn.net/Dariel/article/details/46118075

此时,问题来了,对于一位数组,很容易就能用malloc()进行动态内存分配,但是c语言中似乎并没有能够直接对二维数组进行动态内存分配的函数,那么要如何处理呢?

其实也很简单,由于二维数组的本质是“数组的数组”,两个不同维度的数组的关系类似于“包含”,那么,不妨先对其中一个数组进行内存分配,然后在对另一个数组进行内存分配,将其转化为2次一维数组的内存分配即可。

注意!对于二维数组A[m][n],必须先为行(m)分配内存,再为列(n)分配内存;释放的时候,必须先释放列(n),再释放行(m)。如果顺序相反,那么程序将会把列的地址给“擦除”,从而导致释放内存的时候找不到列的地址,进而导致segment fault,不要问我为什么知道的。

当然,在程序的最后,别忘了释放分配的内存。

嗯......好像也没啥好写的了,三对角矩阵本来也不是什么太难的东西,so show you my code:

#include
#include


typedef struct
{
	double* data_;
	int size;
	double** entry;
}
Tridiag;

// alloc_tridiag
Tridiag alloc_tridiag(int n)
{
	Tridiag t;
	t.size=n;
	int i,j;
	int k=0;	//i-j=0
	int l=0;	//i-j=1
	int m=0;	//i-j=-1

	t.data_=(double*)malloc(sizeof(double)*(3*n-2));
	t.entry=(double**)malloc(sizeof(double*)*n);

	for(i=0;i

稍微解释一下:

1,typedef struct,就是所谓的自定义类型,本文中将其定义为    

    double* data_;
    int size;
    double** entry;

并命名为Tridiag,如果要调用data_的话,调用方式为: Tridiag.data_ 其他两个同理。

2, 经典的问题,指针与数组到底有什么区别?

不妨参阅http://www.cnblogs.com/zhanjindong/archive/2013/02/15/2912892.html

3, k,l,m是什么鬼?

首先要说明Tridiag类型下的data_和entry到底是啥玩意:

data_:代表着三对角矩阵中的非零数据的集合。也就是A中的a, b, c 啥的。

entry: 代表着整个三对角矩阵,包括零。

具体而言,在上述的程序中,

t.entry:
4.000000  4.000000  0.000000  0.000000  0.000000  
4.000000  4.000000  4.000000  0.000000  0.000000  
0.000000  4.000000  4.000000  4.000000  0.000000  
0.000000  0.000000  4.000000  4.000000  4.000000  
0.000000  0.000000  0.000000  4.000000  4.000000  
t.data_:
4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000

这下懂了吧。

那么k l m这几个变量是用来干啥的呢?

程序中的用法:

			if(i-j==0)
			{
				t.entry[i][j]=t.data_[i+2*k];
				k++;
			}
			else if(i-j==1)
			{
				t.entry[i][j]=t.data_[i+2*l];
				l++;
			}
			else if(i-j==-1)
			{
				t.entry[i][j]=t.data_[i+2*m];
				m++;
			}
			else 
				t.entry[i][j]=0;

百度百科三对角矩阵的定义:三对角矩阵M是一个对角矩阵,当且仅当  时,有A(i,j)=0。在一个nxn的三对角矩阵T中,非0元素排列在如下的三条对角线上:

(1)主对角线即i=j;

(2)主对角线之下的对角线(称低对角线)即i=j+1;

(3)主对角线之上的对角线(称高对角线)即i=j-1。

这三条对角线上的元素总数为3n-2,故可以使用一个拥有3n-2个位置的一维数组来描述T,因为仅需要存储三条对角线上的元素。 

所以就很容易理解了,k l m是用来将data_与entry联系起来的计数器一般的变量。具体而言,比如,i-j=0时,对于第一行的entry[0][]而言,其的值等于data_中的data_[0+2*0]=data_[0]...其他情况同理。

4,矩阵乘法?

这个比较简单,这里偷懒就不详细说了。值得注意的是,本文程序中的乘法运算比较基础/简单,如果需要进一步的运用,还需要对其按要求进行适当的修改。

 

那么结果输出如何呢?

liu@ubuntu:~/5613/4$ ./4
t.entry:
4.000000  4.000000  0.000000  0.000000  0.000000  
4.000000  4.000000  4.000000  0.000000  0.000000  
0.000000  4.000000  4.000000  4.000000  0.000000  
0.000000  0.000000  4.000000  4.000000  4.000000  
0.000000  0.000000  0.000000  4.000000  4.000000  
t.data_:
4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  4.000000  

+t[0][0]*a[0]=4.000000 * 0.000000=0.000000
+t[0][1]*a[0]=4.000000 * 0.000000=0.000000
+t[0][2]*a[0]=0.000000 * 0.000000=0.000000
+t[0][3]*a[0]=0.000000 * 0.000000=0.000000
+t[0][4]*a[0]=0.000000 * 0.000000=0.000000
b[0]=0.000000

+t[1][0]*a[1]=4.000000 * 1.000000=4.000000
+t[1][1]*a[1]=4.000000 * 1.000000=8.000000
+t[1][2]*a[1]=4.000000 * 1.000000=12.000000
+t[1][3]*a[1]=0.000000 * 1.000000=12.000000
+t[1][4]*a[1]=0.000000 * 1.000000=12.000000
b[1]=12.000000

+t[2][0]*a[2]=0.000000 * 2.000000=0.000000
+t[2][1]*a[2]=4.000000 * 2.000000=8.000000
+t[2][2]*a[2]=4.000000 * 2.000000=16.000000
+t[2][3]*a[2]=4.000000 * 2.000000=24.000000
+t[2][4]*a[2]=0.000000 * 2.000000=24.000000
b[2]=24.000000

+t[3][0]*a[3]=0.000000 * 3.000000=0.000000
+t[3][1]*a[3]=0.000000 * 3.000000=0.000000
+t[3][2]*a[3]=4.000000 * 3.000000=12.000000
+t[3][3]*a[3]=4.000000 * 3.000000=24.000000
+t[3][4]*a[3]=4.000000 * 3.000000=36.000000
b[3]=36.000000

+t[4][0]*a[4]=0.000000 * 4.000000=0.000000
+t[4][1]*a[4]=0.000000 * 4.000000=0.000000
+t[4][2]*a[4]=0.000000 * 4.000000=0.000000
+t[4][3]*a[4]=4.000000 * 4.000000=16.000000
+t[4][4]*a[4]=4.000000 * 4.000000=32.000000
b[4]=32.000000

b[0]=0.000000
b[1]=12.000000
b[2]=24.000000
b[3]=36.000000
b[4]=32.000000

 

你可能感兴趣的:(HPC)