三对角矩阵见百度https://baike.baidu.com/item/%E4%B8%89%E5%AF%B9%E8%A7%92%E7%9F%A9%E9%98%B5
简而言之就是形如A的矩阵为三对角矩阵
图片来自百度百科。
那么,如何通过c语言构建一个三对角矩阵,并进行简单的乘法计算呢?
最容易想到的思路是,既然矩阵中的元素可以根据位置坐标来确定,比如上图中的可以通过来表示,那么,可不可在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