資料結構之廣義線性表
阿新 • • 發佈:2018-11-11
- 陣列(定義、順序儲存結構)
- 矩陣的壓縮儲存
- 廣義表
- 陣列的順序儲存(將二維的陣列壓縮要一維儲存)
- 行優先,低下標(aij的位序為k<以1作為開始>,每行n個元素):
- k = (i - 1) * n + (j - 1) + 1 = (i - 1) * n + j
- LOC(i,j) = LOC(1,1) + (k -1 ) *L
- 列優先,高下標
- k = (j -1) * m + i
- LOC(i, j) = LOC(1,1) + (k - 1) * L
- 行優先,低下標(aij的位序為k<以1作為開始>,每行n個元素):
- 矩陣的壓縮儲存(對稱陣)
- 方式:取下三角形按照行的順序放入陣列
- 下標公式(取大的下標):
- k = i * (i + 1) / 2 + j , when i >= j
- k = j * (j + 1) / 2 + i , when j > i
- 矩陣的壓縮儲存(三角陣:有一個三角區域都是一個常量c)
- 方式:將三角部分的元素根據對稱陣的方式儲存,然後在最後新增c(k = n(n+1)/2)<n是右下角元素的座標即正方形的寬度+1(0開始計算)>
- k = i(i+1)/2+j , when i >= j
- k = n*(n+1)/2 *必須是0開始
- 矩陣壓縮(對角陣:各對角線有大量相同的元素)
- 方式:略
- 下標公式
- k = 2i + j
- LOC(i, j) = Locate(0,0) + (2i+j)*L
- 稀疏矩陣的壓縮
- 儲存方式:
- 三元組順序儲存
template <class
- 行邏輯連結的順序表(簡化版非連結串列結構)
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;
- 帶行指標向量的鏈式儲存(上面的連結串列版本)
typedef struct L { MTNode *data; int *rpos /*the index of evey firstnonull in the row TSMtrix.*/ int mu,nu,tu; }SMatrix;
- 十字連結串列(拓展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;
- 三元組順序儲存
- 儲存方式:
- 稀疏矩陣的運算
- 矩陣轉置:
- 直接取順序存(傻瓜式,從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; } } }
- 順序取直接存(快速轉置,提前需要知道每一個列號的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]++; } } }
- 直接取順序存(傻瓜式,從A中按照列的升序直接取元素按照順序存入B中)
- 矩陣加法(有時間補充)
- 矩陣乘法(有時間補充)
- 矩陣轉置:
- 廣義表
- 邏輯結構:廣義表(generalized Lists)又稱列表(lists),是n(n>=0)個數據元素a1,a2,a3,...,ai,...,an的有限序列,一般記作:LS = (a1,a2,...,ai,...,an).ai是廣義表LS的成員,它可以是單個元素,也可以是一個廣義表,分別稱為LS的單元素(也可以成為原子)和子表。用大寫字母表示廣義表,資料元素是原子時用小寫字母,資料元素是子表時,用'()"括起來。其中,深度表示巢狀層數,長度是元素個數。注意!如果E = (a, E)這樣巢狀的話,長度是2,但是深度是無窮大! 一棵樹可以用一個廣義表來表示。
- 廣義表的儲存(由於資料元素具有不同的結構,因此難以用順序結構表示,所以使用鏈式儲存結構):
- 頭尾表示法(層級設計,層層掃描,一個括號歸於一層,原子必歸於表節點,一次一個輸出):
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; }; };
- 孩子兄弟表示法(一個節點一定有兄弟(可以是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;
- 計算頭尾表示法的廣義表的深度
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 } }
- 計算頭尾表示法的廣義表的長度
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; }
- 建立廣義表(首尾表示法,使用遞迴的方法)
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); }
- 頭尾表示法(層級設計,層層掃描,一個括號歸於一層,原子必歸於表節點,一次一個輸出):
這個章節的內容理解並不是很難,要是想要實現各種遞迴還真的是頭疼。。。