数组和广义表的操作(课堂笔记)

一、矩阵的压缩存储

  1. 对称矩阵:对有n^2个元素的对称矩阵,可用长度为 [n(n+1)/2] 的一维矩阵存储。以行序为主序,存储下三角中的元:                                          当i >= j时,  k = i(i-1)/2+j-1;       当i < j时,k = j(j-1)/2+i-1;
  2. 稀疏矩阵

          (1)三元组顺序表

#define MAXSIZE 12500
typedef struct
{
    int i, j;  //行号、列号
    Elemtype e;
} Triple;
typedef struct 
{
    Triple data[MAXSIZE + 1];  //非零元三元组表,data[0]未用
    int mu, nu, tu;  //行数、列数、非零元数
};

        !!三元组矩阵转置算法!!

             a. 普通转置

void TransposeSMatrix(TSMatrix M,TSMatrix &T)
{
  T.mu = M.nu;
  T.nu = M.mu;
  T.tu = M.tu;
  if(T.tu)
  {
      q = 1;
      for (col = 1; col < M.nu;col++)
      {
          for (p = 1; p < M.tu;p++)
          {
              if(M.data[p].j==col)
              {
                  T.data[q].i = M.data[p].j;
                  T.data[q].j = M.data[p].i;
                  T.data[q].e = M.data[p].e;
                  q++;
              }
          }
      }
  }
}

            b. 快速转置

                增加num和cpot两个向量,num[col] 表示矩阵M中第col列中非零元的个数,cpot[col] 表示M中第col列的第一个非                                   零元在b.data中的恰当位置,有下列公式:

                 cpot[1] = 1;                                                                                                                                                                                                       cpot[col] = cpot[col-1] + num[col-1];       2 <= col <= a.nu

void FataTransposeSMatrix(TSMatric M,TSMtrix &T)
{
    T.mu = M.nu;
    T.nu = M.mu;
    T.tu = M.tu;
    if(T.tu)
    {
        for (col = 1; col <= M.nu;col++)
            num[col] = 0;
        for (t = 1; t <= M.tu;t++)
            num[M.data[t].j];  //求M中每一列的非零元个数
        cpot[1] = 1;
        for (col = 2; col <= M.tu;col++)
          cpot[col] = cpot[col - 1] + num[col - 1];//求第col列中第一个非零元在b.data中的序号
        for (p = 1; p <= M.tu;p++)
        {
            col = M.data[p].j;
            q = cpot[col];
            T.data[q].i = M.data[p].j;
            T.data[q].j = M.data[p].i;
            T.data[q].e = M.data[p].e;
            cpot[col]++;
        }
    }
}

      (2)行逻辑链接的顺序表

typedef struct
{
    int i, j;  //行号、列号
    Elemtype e;
} Triple;
typedef struct 
{
    Triple data[MAXSIZE + 1];  //非零元三元组表,data[0]未用
    int rpos[MAXSIZE+1];  //各行第一个非零元的位置表
    int mu, nu, tu;  //行数、列数、非零元数
};

     (3)十字链表

typedef struct OLNode
{
    int i, j;
    Elemtype e;
    struct OLNode *right, *down;
} OLNode, *OLink;

typedef struct 
{
    OLink *rhead, *chead;
    int mu, nu, tu;
} CrossList;

 二、广义表

        1. 当广义表非空时,称第一个元素为表头,其余元素组成的表是表尾;

        2. 存储结构

             (1)头尾链表存储表示

typedef enum
{
    ATOM,
    LIST
} ElemTag;
typedef struct GLNode
{
    ElemTag tag;  //用于区分是原子结点还是表结点
    union{
        AtomType atom;
        struct
        {
            struct GLNode *hp, *tp;
        } ptr; //表结点指针域,分别指向表头和表尾
    };
} * GList;

           (2)扩展线性链表存储表示

typedef enum
{
    ATOM,
    LIST
} ElemTag;
typedef struct GLNode
{
    ElemTag tag;  //用于区分是原子结点还是表结点
    union{
        AtomType atom;
        struct GLNode *hp;
    };
    struct GLNode *tp; //表结点指针域,分别指向表头和表尾
} * GList;

         3.m元多项式的表示:m 元多项式先分解成主变元的多项式,则可将其看作一元多项式,而每个系数则是 m-1 元多项式;利用此法可将m-1 元多项式进一步分解,直至每个系数为常数。

         4.广义表的递归算法

              (1)采用头尾链表存储结构,求广义表L的深度

int GListDepth(GList L)
{
    if(!L)
        return 1;
    if(L->tag==ATOM)
        return 0;
    for (max = 0, pp = L; pp;pp=pp->ptr.hp)
    {
        dep = GListDepth(pp->ptr.hp); //求以pp->ptr.hp为头指针的子表深度
        if(dep>max)
            max = dep;
    }
    return max + 1;  //子表深度最大值+1
}

                (2)采用头尾链表存储结构,有广义表L复制得到广义表T

void CopyGList(GList &T,GList L)
{
    if(!L)
        T = NULL;//复制空表
    else
    {
        if(!(T=(GList)malloc(sizeof(GLNode))))
            exit(OVERFLOW);
        T->tag = L->tag;
        if(L->tag==ATOM)
            T->atom = L->atom;
        else
        {
            CopyGList(T->ptr.hp, L->ptr.hp);
            CopyGList(T->ptr.tp, L->ptr.tp);
        }
    }
}

                    (3)采用头尾链表存储结构,由广义表的书写形式串S创建广义表L,设emp = "()".

void CreateGlist(Glist &L,SString S)
{
    if(StrCompre(S,emp))
        L = NULL;
    else
    {
        if(!(L=(GList)malloc(sizeof(GLNode))))
            exit(OVERFLOW);
        if(StrLength(S)==1)
        {
            L->tag = ATOM;
            L->atom = S;
        }
        else
        {
            L->tag = LIST;
            p = L;
            SubString(sub, S, 2, StrLength(S) - 2);  //脱外层括号
            do
            {
                sever(sub, hsub);  //从sub中分离出表头串hsub
                CreateGList(p->ptr.hp, hsub);
                if(!StrEmpty(sub))
                {
                    if(!(p=(GLNode*)malloc(sizeof(GLNode))))
                        exit(OVERFLOW);
                    p->tag = LIST;
                    q->ptr.hp = p;
                }
            } while (!StrEmpty(sub));
            q->ptr.tp = NULL;
        }
    }
}

void sever(SString &str,SString &hstr)
{
    //将非空串str分割成两部分,hsub为第一个','之前的子串,str为之后的子串
    n = StrLength(str);
    i = 0;
    k = 0;
    do
    {
        i++;
        SubString(ch, str, i, 1);
        if(ch=='(')
            k++;
        else if(ch==')')
            k--;
    } while (i<n&&(ch!=','||k!=0));
    if(i<n)
    {
        SubString(hstr, str, 1, i - 1);
        SubString(str, str, i + 1, n - i);
    }
    else
    {
        StrCopy(hstr, str);
        ClearString(str);
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值