数据结构之广义线性表

  • 数组(定义、顺序存储结构)
  • 矩阵的压缩存储
  • 广义表
  1. 数组的顺序存储(将二维的数组压缩要一维存储)
    1. 行优先,低下标(aij的位序为k<以1作为开始>,每行n个元素):
      1. k = (i - 1) * n + (j - 1) + 1 = (i - 1) * n + j
      2. LOC(i,j) = LOC(1,1) + (k -1 ) *L
    2. 列优先,高下标
      1. k = (j -1) * m + i
      2. LOC(i, j) = LOC(1,1) + (k - 1) * L
  2. 矩阵的压缩存储(对称阵)
    1. 方式:取下三角形按照行的顺序放入数组
    2. 下标公式(取大的下标):
      1. k = i * (i + 1) / 2 + j   , when i >= j
      2. k = j * (j + 1) / 2 + i   , when j  > i      
  3. 矩阵的压缩存储(三角阵:有一个三角区域都是一个常量c)
    1. 方式:将三角部分的元素根据对称阵的方式存储,然后在最后添加c(k = n(n+1)/2)<n是右下角元素的坐标即正方形的宽度+1(0开始计算)>
    2. 下标公式(以上三角形常量为例子):
      1. k = i(i+1)/2+j , when i >= j
      2. k = n*(n+1)/2     *必须是0开始
  4. 矩阵压缩(对角阵:各对角线有大量相同的元素)
    1. 方式:略
    2. 下标公式
      1. k = 2i + j
      2. LOC(i, j) = Locate(0,0) + (2i+j)*L
  5. 稀疏矩阵的压缩
    1. 存储方式:
      1. 三元组顺序存储 
        template <class T>
        struct MTNode{
            int i, j;
            T e;
        };
        template <class T>
        typedef struct L 
        {
            MTNode<T> *data;
            int mu, nu, tu;
        }TSMatrix;
      2. 行逻辑链接的顺序表(简化版非链表结构)
        template <class T>
        struct MTNode{
            int i, j;
            T e;
        };
        
        typedef struct L
        {
            MTNode *data;
            int *rpos /*the index of evey firstnotnull 
                        in the row TSMtrix.*/
            int mu,nu,tu;
        }SMatrix;
      3. 带行指针向量的链式存储(上面的链表版本)
        typedef struct L
        {
            MTNode *data;
            int *rpos /*the index of evey firstnonull 
                        in the row TSMtrix.*/
            int mu,nu,tu;
        }SMatrix;
      4. 十字链表(拓展2、3,不仅仅是停留在行的层面,我把它理解为稀疏矩阵提取元素二维数组链表化)
        struct MTNode{
            int i, int j;
            T e;
            MTNode * dowm;
            MTNode * right;
            //used to bulid linked list
        }
        
        typedef struct L
        {
            int mu,nu,tu;
            MTNode *rpos;
            MTNode *cpos;
        }LMatrix;
  6. 稀疏矩阵的运算
    1. 矩阵转置:
      1. 直接取顺序存(傻瓜式,从A中按照列的升序直接取元素按照顺序存入B中)
        void MatrixTrans_I(TSMatrix A, TSMatrix &B){
            B.mu = A.nu;
            B.nu = A.mu;
            B.tu = A.tu;
            //A convert the arguments to B;
            if(B.tu) //confirm it has element
            {
                q = 0;
                //q is the index of the TSMatrix B
                for(col = 0; col < A.nu; col++)
                    for(p = 0; p < A.mu; p++) 
                        //p is the index of the TSMatrix A
                        //search every row.
                        if(A.data[p].j == col)
                        {
                            B.data[q].i = A.data[p].j;
                            B.data[q].j = A.data[p].i;
                            B.data[q].e = A.data[p].e;
                            ++q;
                        }
            }
        }
      2. 顺序取直接存(快速转置,提前需要知道每一个列号的Index数组cpot[col]和它有几个元素num[col],从A中顺序取元素,直接存到B)
        void MatrixTrans_II(TSMatrix A, TSMatrix &B){
            B.mu = A.nu;
            B.nu = A.mu;
            B.tu = A.tu;
            int i, k, p,q;
            int * num, * cpot;
            num = new int[B.nu];
            cpot = new int[B.nu];
            if(B.tu){
                for(i = 0; i < B.nu; i++){
                    num[i] = 0;
                    //initialization
                }
                for(k = 0; k < B.nu; k++){
                    num[A.data[k].j]++;
                    //counter
                }
                copt[0] = 0;
                for(k = 1; k < B.nu; k++){
                    cpot[k] =copt[k - 1] + num[k - 1]; 
                }
        
                for(p = 0; p < A.nu; p++){
                    //get the elemnt int A in sequence
                    //and then insert it into the right
                    //postion.
                    q = copt[A.data[p].j];
                    B.data[q].i = A.data[p].j;
                    B.data[q].j = A.data[p].i;
                    B.data[q].e = A.data[p].e;
                    copt[A.data[p].j]++;
                }
            }
        }
    2. 矩阵加法(有时间补充)
    3. 矩阵乘法(有时间补充)
  7. 广义表
    1. 逻辑结构:广义表(generalized Lists)又称列表(lists),是n(n>=0)个数据元素a1,a2,a3,...,ai,...,an的有限序列,一般记作:LS = (a1,a2,...,ai,...,an).ai是广义表LS的成员,它可以是单个元素,也可以是一个广义表,分别称为LS的单元素(也可以成为原子)和子表。用大写字母表示广义表,数据元素是原子时用小写字母,数据元素是子表时,用'()"括起来。其中,深度表示嵌套层数,长度是元素个数。注意!如果E = (a, E)这样嵌套的话,长度是2,但是深度是无穷大!  一棵树可以用一个广义表来表示。
    2. 广义表的存储(由于数据元素具有不同的结构,因此难以用顺序结构表示,所以使用链式存储结构):
      1. 头尾表示法(层级设计,层层扫描,一个括号归于一层,原子必归于表节点,一次一个输出):
        enum Elemtag{Atom,List};
        //0 is atom node, 1 is list node;
        template <class T>
        struct GLNode
        {
            Elemtag tag;
            union
            {
                T data;
                struct 
                {
                    GLNode * hp, *tp;
                }ptr;
            };
        };
      2. 孩子兄弟表示法(一个节点一定有兄弟(可以是Null,tp),一个节点可能有儿子(hp),若是儿子没有孩子,我们就像看看他长什么样子,有没有兄弟,并且为什么不可以用tag告诉我到底是什么呢?)
        enum Elemtag{Atom, List};
        template <class T>
        struct GLNode
        {
            Elemtag tag;
            union{
                T data;
                struct  GLnode* hp;
                //hp point to the son
            }
            struct GLNode *tp;
                //tp point to the brother
        }ptr;
      3. 计算头尾表示法的广义表的深度
        int depth(GLNode * ls){
            int h,t;
            if(ls == NULL)//if the node is not exist return 1
                return 1;
            else if(ls -> tag == 0)
                return 0;//if the node is atom return 0
            else {
                h = depth(ls -> hp);
                t = depth(ls -> tp);
                if(t > h)
                    return t;
                else 
                    return h+1;
                //recursion
            } 
        }
      4. 计算头尾表示法的广义表的长度
        int Length(GLNode *ls){
            if(ls == NULL)
                return 0;
            int max = 1;
            //search in y
            GLNode* p = ls -> tp;
            while(p){
                max++;
                p = p -> tp;
            }
            return max;
        }
      5. 创建广义表(首尾表示法,使用递归的方法)
        template <class T>
        GLNode<T>* Crtlists(string st){
            if(st == "()")
                ls = NULL;
            else
                if(st.Length() == 1){
                    ls = new GLNode<T>;
                    ls -> tag = 0;
                    ls -> data = st[0];
                } else {
                    ls = new GLNode<T>;
                    ls -> data = 1;
                    p = ls; 
                    st = st.substring(1, st.length()-2);
                            //remove the "()"
                    do{
                        Server(sub,hsub);
                        p -> ptr.hp = Crtlists(hsub);
                        q = p;
                        //This is a sub remove "()"outside
                        //and the element in it.
                        if(sub!="")
                        {
                            p = new GLNode<T>;
                            p -> tag = 1;
                            q -> ptr.tp = p;
                        };
                    }
                    while(sub != "");
        
                    q -> ptr.tp = NULL;//seal the last one.
                }
                return(ls);
        }

这个章节的内容理解并不是很难,要是想要实现各种递归还真的是头疼。。。

猜你喜欢

转载自www.cnblogs.com/dreamworldclark/p/9939770.html