1. 程式人生 > >行邏輯三元組稀疏矩陣加減乘的程式設計實現

行邏輯三元組稀疏矩陣加減乘的程式設計實現

目的:
        程式設計實現稀疏矩陣的四則運算。
實現:
1. 稀疏矩陣的儲存結構採用行邏輯表示的三元組
2.

#define MAXSIZE  12500
#define MAXRC 12500
typedef struct {
    int i, j;
    int e;
}Triple;
typedef struct {
    Triple data[MAXSIZE + 1];
    int rpos[MAXRC + 1];
    int mu, nu, tu;
}RLSMatrix;

        先通過建立mu nu tu的值再根據這些值採用迴圈輸入得到data,之後再通過掃描確定rpos的值則可以完成建立。
        通過三元組的形式將非零元對應的行列以及數值儲存下來,再由稀疏矩陣結構存下矩陣的行數列數以及非零元個數,即可囊括稀疏矩陣的所有資訊。這樣就可以以三元組的形式把矩陣非零元素儲存下來,節省了儲存量的同時便於矩陣運算。

  1. 矩陣的加法
           根據矩陣的相關知識,兩個矩陣相加要求兩個矩陣的行數,列數要相等。故需要設定判斷是否滿足矩陣相加的條件。若滿足條件,則進行加法運算。根據矩陣加法法則,得到的新矩陣擁有與原來兩矩陣相同的行數和列數,其元素數值則為兩矩陣對應位置的元素值之和。

  2. 矩陣的減法
           和加法相同地根據三種情況採用三個迴圈處理對應的資料,只不過兩個都有的情況結果要變為兩者之差,N有M沒有的情況要改為N元素的相反數,其餘相同。則可以得到減法的演算法。

  3. 矩陣的乘法
            根據矩陣乘法的理論,在滿足M.nu==N.mu的情況下,新矩陣Q(i,j)的值即滿足M(i,k)與N(k,j)的所有元素乘積之和。對於稀疏矩陣不需要對滿足條件的每個元素都進行乘積,因為兩者中若有一個為零則其乘積為零。所以只要在所有非零元中找到滿足條件的配對進行相乘,在將乘積進行累加即可得到該位置的元素值。結合rpos可以高效地進行迴圈查詢。
    程式程式碼:
    Matrix.h檔案

#include<stdio.h>
#define MAXSIZE  12500
#define MAXRC 12500
#define ERROR 0
#define OK 1
typedef struct {
    int i, j;
    int e;
}Triple;
typedef struct {
    Triple data[MAXSIZE + 1];
    int rpos[MAXRC + 1];
    int mu, nu, tu;
}RLSMatrix;
void CreateMatrix(RLSMatrix *M);
void Initrpos(RLSMatrix *M);
void
Printrpos(RLSMatrix M); int Add(RLSMatrix M, RLSMatrix N, RLSMatrix *sum); int Minus(RLSMatrix M, RLSMatrix N, RLSMatrix *minus); int Multi(RLSMatrix M, RLSMatrix N, RLSMatrix *multi); void PrintMatrix(RLSMatrix M);

Matrix.c檔案

#include<stdio.h>
#include"Matrix.h"
void CreateMatrix(RLSMatrix *M) {
    printf("請輸入矩陣的行數,列數,和非零元個數\n");
    scanf("%d%d%d", &M->mu, &M->nu, &M->tu);
    if (M->tu > (M->mu)*(M->nu)) { printf("該矩陣不存在!請重新輸入!\n"); CreateMatrix(&M); }
    int s;
    for (s = 1; s <= M->tu; s++) {
        printf("請輸入第%d非零元所在的行,列,及其數值\n", s);
        scanf("%d%d%d", &M->data[s].i, &M->data[s].j, &M->data[s].e);
        if (M->data[s].i < 0) { printf("行數須為正數!\n"); s -= 1; continue; }
        if(M->data[s].j < 0) { printf("列數須為正數!\n"); s -= 1; continue; }
        if(M->data[s].e==0){ printf("非零元不能為零!\n"); s -= 1; continue; }
    }
}
void Initrpos(RLSMatrix *M) {
    int i, j, tag, s;
    for (i = M->mu; i >= 1; i--) {
        tag = 0;
        for (j = 1; j <= M->nu; j++) {
            for (s = 1; s <= M->tu; s++) {
                if (M->data[s].i == i&&M->data[s].j == j) {
                    M->rpos[i] = s; tag = 1; break;
                }
            }
            if (tag == 1)break;
        }
        if (i == M->mu&&tag == 0)M->rpos[i] = M->tu + 1;
        if (i != M->mu&&tag == 0)M->rpos[i] = M->rpos[i + 1];
    }
}
void Printrpos(RLSMatrix M) {
    int i;
    printf("rpos\n");
    for (i = 1; i <= M.mu; i++) {
        printf("第%d行:%d\n", i, M.rpos[i]);
    }
}

int Add(RLSMatrix M, RLSMatrix N, RLSMatrix *sum) {
    int m, n, c = 1;
    if (M.mu != N.mu || M.nu != N.nu) { printf("無法相加!\n"); return ERROR; }
    sum->mu = M.mu;
    sum->nu = M.nu;
    for (m = 1; m <= M.tu; m++) {
        for (n = 1; n <= N.tu; n++) {
            if (N.data[n].i == M.data[m].i&&N.data[n].j == M.data[m].j) {
                sum->data[c].i = N.data[n].i;
                sum->data[c].j = N.data[n].j;
                sum->data[c].e = M.data[m].e + N.data[n].e;
                c++;
            }

        }       
    }
    for (m = 1; m <= M.tu; m++) {
        for (n = 1; n <= N.tu; n++) {
            if (N.data[n].i == M.data[m].i && N.data[n].j == M.data[m].j) {
                 break;
            }           
        }
        if (n-1 == N.tu) {
            sum->data[c].i = M.data[m].i;
            sum->data[c].j = M.data[m].j;
            sum->data[c].e = M.data[m].e;
            c++;
        }
    }

    for (n = 1; n <= N.tu; n++) {
        for (m = 1; m <= M.tu; m++) {
            if (N.data[n].i == M.data[m].i && N.data[n].j == M.data[m].j) {
                break;
            }
        }
        if (m-1 == M.tu) {
            sum->data[c].i = N.data[n].i;
            sum->data[c].j = N.data[n].j;
            sum->data[c].e = N.data[n].e;
            c++;
        }
    }
    sum->tu = c - 1;
    return OK;
}

int Minus(RLSMatrix M, RLSMatrix N, RLSMatrix *minus) {
    int m, n, c = 1;
    if (M.mu != N.mu || M.nu != N.nu) { printf("無法相減!\n"); return ERROR; }
    minus->mu = M.mu;
    minus->nu = M.nu;
    for (m = 1; m <= M.tu; m++) {
        for (n = 1; n <= N.tu; n++) {
            if (N.data[n].i == M.data[m].i&&N.data[n].j == M.data[m].j) {
                minus->data[c].i = N.data[n].i;
                minus->data[c].j = N.data[n].j;
                minus->data[c].e = M.data[m].e - N.data[n].e;
                c++;
            }

        }
    }
    for (m = 1; m <= M.tu; m++) {
        for (n = 1; n <= N.tu; n++) {
            if (N.data[n].i == M.data[m].i && N.data[n].j == M.data[m].j) {
                 break;
            }           
        }
        if (n-1 == N.tu) {
            minus->data[c].i = M.data[m].i;
            minus->data[c].j = M.data[m].j;
            minus->data[c].e = M.data[m].e;
            c++;
        }
    }
    for (n = 1; n <= N.tu; n++) {
        for (m = 1; m <= M.tu; m++) {
            if (M.data[m].i == N.data[n].i && M.data[m].j == N.data[n].j) {
               break;
            }           
        }
        if (m-1 == M.tu) {
            minus->data[c].i = N.data[n].i;
            minus->data[c].j = N.data[n].j;
            minus->data[c].e = -N.data[n].e;
            c++;
        }
    }
    minus->tu = c - 1;
    return OK;
}
int Multi(RLSMatrix M, RLSMatrix N, RLSMatrix *Q) {
    if (M.nu != N.mu)return ERROR;
    Q->mu = M.mu; Q->nu=N.nu; Q->tu = 0;
    int tp; int i;
    int p, brow;
    int q, ccol;
    if (M.tu*N.tu != 0) {
        int arow;
        int ctemp[12500];
        for (arow = 1; arow <= M.mu; ++arow) {
            for (i = 1; i <= M.nu; i++) ctemp[i] = 0;
            Q->rpos[arow] = Q->tu + 1;
            if (arow < M.mu)tp = M.rpos[arow + 1];
            else { tp = M.tu + 1; }
            for (p = M.rpos[arow]; p<tp; ++p) {
                brow = M.data[p].j;
                int t;
                if (brow < M.mu)t = N.rpos[brow + 1];
                else { t = N.tu + 1; }
                for (q = N.rpos[brow]; q < t; ++q) {
                    ccol = N.data[q].j;
                    ctemp[ccol] += M.data[p].e * N.data[q].e;
                }
            }
            for (ccol = 1; ccol <= Q->nu; ++ccol) {
                if (ctemp[ccol]) {
                    if (++Q->tu > MAXSIZE)return ERROR;
                    Q->data[Q->tu].i = arow;
                    Q->data[Q->tu].j = ccol;
                    Q->data[Q->tu].e = ctemp[ccol];
                }
            }
        }
    }
    return OK;
}

void PrintMatrix(RLSMatrix M) {
    int m, n, s;
    int tag;
    for (m = 1; m <= M.mu; m++) {
        for (n = 1; n <= M.nu; n++) {
            tag = 0;
            for (s = 1; s <= M.tu; s++) {
                if (M.data[s].j == n && M.data[s].i == m) { 
                    if(M.data[s].e>=0)printf(" %d ", M.data[s].e);
                    else if(M.data[s].e<0){ printf("%d ", M.data[s].e); }
                    tag = 1;
                }
            }
            if(tag==0)printf(" 0 ");
        }printf("\n");
    }
}
}

Main.c檔案

#include<stdio.h>
#include<stdlib.h>
#include"Matrix.h"
int main() {
RLSMatrix M, N, temp;
int tag;
CreateMatrix(&M); Initrpos(&M); printf("所得矩陣為:\n"); PrintMatrix(M); Printrpos(M);
CreateMatrix(&N); Initrpos(&N); printf("所得矩陣為:\n"); PrintMatrix(N); Printrpos(N);
tag=Add(M, N, &temp); Initrpos(&temp); 
 if(tag == OK) {
     printf("兩矩陣相加所得為:\n"); PrintMatrix(temp);
  }
tag=Minus(M, N, &temp); Initrpos(&temp); 
if (tag == OK) {
      printf("兩矩陣相減所得為:\n"); PrintMatrix(temp);
  }
tag=Multi(M, N, &temp); Initrpos(&temp); 
  if(tag == OK){ 
      printf("兩矩陣相乘所得為:\n"); 
      PrintMatrix(temp);
  }
system("pause");
}

演示示例如下:


matrix
注:
1. 為了使輸出的矩陣更加形狀好看規則,設計了元素的正負判定(因為負數輸出時會多一個負號),使得正數和負數的數字部分可以對齊。
2. 為了減少非法輸入的可能,在建立矩陣的函式中加入了非零元素不能多於矩陣行列數乘積的判定。以及列數行數必須為正整數,輸入非零元不能為零的判定。
3. 在矩陣不滿足加法減法(或是乘法)條件的時候,需要報錯。為此將運算函式設定為int型別,根據返回值來判斷該列印運算結果還是直接列印報錯。
4. 在主函式的設計過程中,在建立函式和rpos初始化結束後立即列印輸出矩陣和對應的rpos值便於立即檢驗函式建立的矩陣是否正確,也便於使用者檢視對比。

相關推薦

邏輯三元稀疏矩陣程式設計實現

目的:         程式設計實現稀疏矩陣的四則運算。 實現: 1. 稀疏矩陣的儲存結構採用行邏輯表示的三元組 2. #define MAXSIZE 12500 #define MAXRC 12500 typedef struct {

三元稀疏矩陣快速轉置

稀疏矩陣是隻儲存非零元的行值、列值、元素值 data[0]來儲存矩陣的行數、列數、非零元個數 struct Position { int row; int col; in

稀疏矩陣——三元十字連結串列的C語言實現

粗淺學習稀疏矩陣——三元組十字連結串列。 程式碼實現了新建矩陣、矩陣相加、矩陣逆置和矩陣列印在螢幕上。 慚愧於命名規範和程式設計水平,不足的地方請大牛們多多指教: 直接上程式碼 crosslist.h #ifndef _crosslist_h_ #define

線性代數-矩陣- C和C++實現

for 通過 turn oba c語言 bsp operator column name 原理解析: (此處補圖) 本節編寫矩陣的加法和減法,兩個矩陣相加,即把兩個相同大小的矩陣對應的元素分別相加 。兩個矩陣相減,把兩個相同大小矩陣的對應元素分別相減。 C++語言: 矩

python 列表元除法

python list python 列表 div 加減 其他 type 加減乘除 相加 元組(typle)列表(list)沒有減法和除法,但有加法和乘法。 1、加法,即把元素相加。只可以list和tuple相加,不能加其他類型。 t= (1, ) + (2, 3, 4)

深入詳細理解矩陣 (矩陣、轉置、共軛、共軛轉置)

https://blog.csdn.net/know9163/article/details/80551764 矩陣:英文名Matrix。在數學名詞中,矩陣用來表示統計資料等方面的各種有關聯的資料。這個定義很好地解釋了Matrix程式碼製造世界的數學邏輯基礎。矩陣是數學中最重要的基本概念之一,是

三元建立矩陣 一次定位快速轉置 矩陣的加法、減法、乘法

首先說說我們經常見到或者使用的矩陣: (1):三角矩陣:對角線一側的元素沒有限制,另一側全為0或者常數c。常見的有上三角矩陣和下三角矩陣。 (2):對角矩陣:對角矩陣是指有效元素集中在對角線兩側,我們常用的三對角矩陣來將矩陣的壓縮。三對角矩陣指的是三條對角線

高精度實現

加法 #include<bits/stdc++.h> using namespace std; int a1[1000],a2[1000],c[1000]; int main(){ string s1,s2; cin>>s1>>s2; int l

大二上期資料結構實驗記錄(二)【初版】C實現簡單一元多項式求導及代值計算(有借鑑刪改)

想要記錄自己程式設計思維的成長所以發到部落格,歡迎並且感激大家指出缺點和錯誤! 一、【實驗構思(Conceive)】 本次實驗要求是用C或C++語言設計並實現一個一元稀疏多項式的簡單計算器,要求是要有如下功能 1、輸入並建立多項式 2、輸出多項式,序列按指數降序

購物車及器的實現

二級列表介面卡 public class MyAdapter extends BaseExpandableListAdapter { private Context context; private List<Data.DataBean> list; //建立有參和無參構造方

運籌學與最優化理論基礎——高精度乘除(C++實現)

概要 這是本學期運籌學和最優化理論課的第一次作業。導師要求是實現含分數的高精度加減乘除運算,不能含有浮點數,這樣會造成計算誤差。為了實現分數的高精度加減乘除運算,我們首先必須實現整數的高精度加減乘除運算,之後將分數運算轉化成分子和分母相關的高精度計算。所有程式碼

大數,,,除

大數相加模擬我們豎式的計算方法,從第位加起,超過10,則低位減10,計算高位時加1.123456789 + 987654321 = ?大數乘法(其中包括大數加法的演算法)同樣模擬我們豎式的計算方法eg:835*49實現程式碼:方案一:# -*- coding=utf-8 -*

Java中Double型資料的,,,除

privatestaticfinalint DEF_DIV_SCALE =10;     /**      * 兩個Double數相加      * @param v1      * @param v2      * @return Double      */publicstatic Double add

python中 使用列表推導自定義向量的

# coding=utf-8 class Vector(object): """docstring for Vector""" """根據座標軸列表輸入 建立向量, 並建立該向量所處的空

C# 之分數的 除 取餘數

定義分數(Fraction)類:  1)、成員變數 私有欄位以及可讀可寫屬性:分子、分母 2)、成員方法: * 列印分數資訊(例如: 1 / 3)   PrintFraction() * 約分 Reduction() * 建立一個方法交換分子和分母的值 Exchang

稀疏矩陣的十字連結串列實現:行列連結串列

<span style="font-size:12px;">//將current插入到其對應的行連結串列的合適位置,使行連結串列的元素按行號遞增順序排列 void Insert_R( OLNode *rhead, OLNode * current ) { if( ( rhead + cu

多項式的

這是我學資料結構寫的第一個比較"大型"的程式,唉,還是有不足之處啊。。。 # include <stdio.h> # include <iostream.h> # include <stdlib.h> # include <mall

計蒜客 結果填空:

請對於下面式子進行填空,填入加減乘,使這個表示式成立。11  22  33  44  55  66  77  88  99  1010 == 00請輸出一共有多少種方案可以使得表示式成立一開始忽略了有乘和加應該先算乘號。每算一步之前應該考慮先一步的符號,若是加減之間計算,否則

每日一練——大數乘除運算實現(網易筆試題)

前幾天做網易筆試題時最後一道題是設計一個大數類,實現加減運算,因為做這道題時只有5分鐘,結果我剛把類寫出來,考試時間就結束了。其實在去年12月我寫過一個RSA的加解密程式,其中就用到了大數的加減乘除運算(當然這只是RSA用到的一小部分),沒有把最後一題寫上去實在太可惜了(&

poj 3735 Training little cats 構造矩陣+稀疏矩陣加速連+矩陣快速冪

題面描述: Training little cats Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13366 Accepted: 3293 Description Facer's p