そして、テーブルの幅広いです

要件:

  1. 特性および保存表現と高レベルのプログラミング言語で実装し、マスタアドレス計算方法「行為マスターへ」および「列ベースの」ストレージ・アレイ表現の多次元配列型を理解します。
  2. 圧縮された記憶表現の特別なマスターマトリックス。
  3. 疎行列で使用方法を処理トリプレット表現行列演算を理解すべきで疎行列、そのアプリケーションを保存する圧縮方法の特徴を理解します。

1つの行列

スパース行列

スパース行列が定義されています:

これらのはるかに非零要素のゼロ要素の数、およびマトリックスの非零要素の分布よりもために不規則スパース行列(疎)と呼ばれます。

圧縮されたストレージの疎行列

より少ない非ゼロのスパース行列の要素、よりゼロ要素、ひいては圧縮ストレージの格納方法の唯一の非ゼロ要素を使用することができるからです。

疎な行列と関連する操作の順次格納(1)

一般的に使用される方法は、順次擬似アドレスと表記の疎な行列表現でトリプルを格納されています。

トリプル表記

トリプレットデータ構造は、テーブルでは、Nの長さであり、各要素は、構成要素が図3に示すように、行インデックスおよび列インデックスに等しく、表3、線形成分を有します。素子構造は以下のように:

typedef struct{
    int value; //如果题目中要求使用其他类型,则将int替换为题目要求的类型。
    int i,j;
}Trimat;

あなたは非ゼロ要素のmaxtermsを含むスパース行列を定義したい場合は、プログラムでは、単純に次のコードのように記述:

Trimat trimat[maxterms]; //maxterms是已经定义的常量

構造上に定義した方法は、以下のいずれかにトリプル、配列の直接のアプリケーションを定義簡潔にするために使用されなくてもよいです。

int trimat[maxterms][3];
//如果题目中要求使用其他类型,则将int替换为题目要求的类型。

trimat [K] [0]は、元の行列の値を表す行の優先順位に従って、k番目の非ゼロ要素である。trimat [K] [1]、trimat [K] [2]におけるk番目の非ゼロ要素を表します行列の位置。なお、この時点で見ることができ、我々は、行0の三つの要素は、それぞれの非ゼロ要素の数、行数と列数を格納するために使用される所定の3行のmaxtermsのtrimatアレイです。

例えば:

サイズMXNは、対応するトリプルストアを確立し、そして三重行列Aに印刷スパース行列A(float型)、与えられました

アルゴリズム分析:トリプルコアの問題を確立することは、元の行列の非零要素の数が必要であり、元の配列中の非零要素の値の位置は、この問題は比較的単純なアルゴリズムであり、行列Aは、それによって確立、スキャンデータを取得することができることですトリプレット、命名B、最終的な印刷は、次の通り:

以下のトリプレットの設立後:

②擬似アドレス表現

    伪地址即元素在矩阵中按照行优先或者列优先存储的相对位置。用伪地址方法存储稀疏矩阵和三元组方法相似,只是三元组每一行中有两个存储单元存放位置,而伪地址只需要一个,对于一个mxn的稀疏矩阵A,元素A[i][j]的伪地址计算方法为n(i-1)+j。根据这个公式,不仅可以计算矩阵中一个给定元素的伪地址,还可以反推出给定元素在原矩阵中的真实地址。

(2)稀疏矩阵的链式存储及相关操作

在稀疏矩阵的链式存储方法中,最常用的有两种:邻接表表示法和十字链表表示法。

邻接表表示法

邻接表表示法将矩阵中每一行的非零元素连成一个链表,链表结点中有两个分量,分别表示该结点对应的元素值及其列号。

对于上面的矩阵A,用邻接表表示如下:

②十字链表表示法

在稀疏矩阵的十字链表存储结构中,矩阵的每一行用一个带头结点的链表表示,每一列也用一个带头结点的链表表示,这种存储结构中的链表结点都有五个分量:行分量、列分量、数据域分量、指向下方结点的指针,指向右方结点的指针,

    十字链表是由一些单链表纵横交织而成的,其中最左边和最上边是头结点数组,不存储数据信息,左上角的结点可以视为整个十字链表的头结点,它有五个分量,分别存储矩阵的行数,列数、非零元素个数以及指向两个头结点数组的指针。十字链表结点中除头结点以外的结点就是存储矩阵非零元素相关信息的普通结点。

十字链表的两种结点的结构定义如下:

1、普通结点结构定义
typedef struct OLNode{
    int row,col;           //行号和列号
    struct OLNode *right,*down;    //指向右边结点和下方结点的指针
    float val;
}OLNode;

2、头结点结构定义
typedef struct {
    PLNode *rhead,*chead;   //指向两头结点数组的指针
    int m,n,k;     //矩阵行数、列数以及非零结点总数。
}CrossList;

2 广义表

一句话概括广义表:表元素可以是原子或者广义表的一种线性表的拓展结构。

广义表的存储结构:

    由于广义表的元素类型不一定相同,因此难以用顺序存储结构存储表中元素,通常采用链接存储方式来存储广义表元素,并称之为广义链表。

    采用链式存储结构,每个数据元素可用一个节点表示:

   (1)表结点,用以表示子表

   (2)元素结点,用以表示单元素

为区别表结点和元素结点,可用一个标志位tag来区分,节点的结构可以设计成如下形式

当tag=0元素结点由标志域,值域构成,当tag=1时,表结点由标志域,头指针域和尾指针域三部分组成。头指针域指向原子或者广义表结点,尾指针域为空或者指向本层中的下一个广义表结点。

typedef struct GenealNode{
    int tag;
    union{
        Datatype data;
        struct{
            struct GenenealNode \*hp,\*tp;
        }ptr;
    };
}*Glist;

下图展示了1)到5)中广义表的头尾链表存储结构的存储情况。

此外还有一种拓展线性表存储结构。其中也有两种结点,即原子结点和广义表结点,不同的是原子结点有是三个域:标记域、数据域和尾指针域;广义表结点也有3个域:标记域、头指针域与尾指针域。其中,标记域用于区分当前节点是原子(用0表示),还是广义表(用1表示)。这种存储结构类似于带头结点的单链表存储结构(而上一种类似于不带头结点的单链表存储结构),每一个子表都有一个不带存储信息的头结点来标记其存在,如表A。

广义表的基本操作

取广义表的表头GetHead()和取广义表的表尾GetTail()

任何一个非空广义表的表头是第一个元素,它可能是原子,也可能是广义表,而其表尾必定是广义表。

例如上面的例子中

GetHead(C)=b             GetTail(C)=((c,d))

GetHead(D)=B             GetTail(D)=(C)

取表头算法为

GList GetHead(GList p)
{//表空时返回NULL,否则返回头指针
 if(!p||p->tag==0)//空表或单个元素,函数无意义 
 {
    printf("空表或单个元素");
     return NULL; 
 } 
 else
 {
    return p->ptr.hp;
 }
}

取表尾算法为

GList GetTail(GList p)
{//表空时返回NULL,否则返回头指针
 if(!p||p->tag==0)//空表或单个元素,函数无意义 
 {
    printf("空表或单个元素");
     return NULL; 
 } 
 else
 {
    return p->ptr.tp;
 }
}

求广义表的深度

设非空广义表为Ls=(a1,a2,a3...an),其中ai(i=1,2,3...)是原子或者Ls的子表。求Ls的深度可以用递归算法来处理。

具体过程:把原问题转化为求n个子问题ai的深度,Ls的深度为ai(i=1,2,3..)的深度中最大值加1,对于每个子问题,若ai是原子,则由定义知其深度为0,若ai为空表,其深度为1,若ai为非空广义表,则采用与上述同样的处理方法。

int depth(Glist ls)
{
    int max;
    Glist tmp=ls;
    if(tmp==NULL)
    {
        return 1;
    }
    if(tmp->tag==0)
    {
        return 0;
    }
    max=0;
    while(tmp!=NULL)
    {
        dep=depth(tmp->ptr.hp)
        if(dep>max)
        max=dep;
        tmp=tmp->ptr.tp;
    }
    return max+1;
}

おすすめ

転載: www.cnblogs.com/lin546/p/11981045.html