1. 程式人生 > >資料結構之廣義線性表

資料結構之廣義線性表

  • 陣列(定義、順序儲存結構)
  • 矩陣的壓縮儲存
  • 廣義表
  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);
        }

         

這個章節的內容理解並不是很難,要是想要實現各種遞迴還真的是頭疼。。。