數據結構(二):線性表的使用原則以及鏈表的應用-稀疏矩陣的三元組表示
上一篇博文中主要總結線性表中的鏈式存儲結構實現,比方單向鏈表、循環鏈表。還通過對照鏈表和順序表的多項式的存儲表示。說明鏈表的長處。能夠參看上篇博文http://blog.csdn.net/lg1259156776/article/details/47018813
以下先對沒有介紹的鏈表中的雙鏈表進行介紹。並通過稀疏矩陣的三元組的鏈式結構來深入理解較為復雜的鏈表存儲結構。
最後對三次博文所講述的內容進行梳理。以幫助在實際應用中選擇最合適的存儲結構:順序表和鏈表。來組織實現自己的算法和功能。
雙向鏈表
以下用示意圖對照一下幾種鏈表的表示:
單向鏈表表頭
單向鏈表的結構例如以下:
循環鏈表的結構例如以下:
在循環單鏈表中,從隨意一個結點出發,沿著向後鏈可以訪問到表中的全部元素;
對循環鏈表的操作與普通單鏈表基本同樣,僅僅是判表空和推斷表尾元素的條件有所不同
推斷表尾:p->next == head
推斷表空:head->next == head
雙向鏈表
指在前驅和後繼方向都能遍歷的線性鏈表,每一個結點結構例如以下圖所看到的:
雙向鏈表結構例如以下:
雙向鏈表的長處是:實現雙向查找(單鏈表不easy做到),缺點是:空間開銷大。
雙向鏈表通常採用帶表頭結點的循環鏈表形式。結構例如以下:
雙向鏈表結點CDNode的抽象數據類型:
typedef struct CDNode
{
CDNode *m_pNext, *m_pPrev;
}
CDNode的基本操作例如以下:
void SetDNode(DNode *front);
DNode *GetPrev(DNode *ptr);
DNode *GetNext(DNode *ptr);
void InsertPrev(DNode *pNode);
void InsertNext(DNode *pNode);
Void DeleteDNode(DNode *ptr);
雙向鏈表CDList的實現:
typedef CDList
{
CDNode *m_pHead;
int Size;
}
CDList的基本操作:
Void SetDLList();//構造
Void FreeDLList();//析構
int DLListSize ();
int DLListIsEmpty();//
int DLListLocate();
DataType DLListGetData();
void DLListInsert();
void DLListDelete();
針對幾個比較抽象的操作進行圖例說明:
********************************************************************************************
註:在鏈表的操作中要註意改動指針的順序
********************************************************************************************
有序表
有序表的插入
在有順序表L中插入新的結點,使得L仍然有序
void OrderInsert( SqList L, ElemType x ) {
//L非遞減有序的順序表。插入新元素x,使L仍然有序
i=L.length-1; //i指向表尾元素
while(i>=0 && x<L.elem[i]) {
L.elem[i+1]=L.elem[i]; //大於x的元素右移
i--;
} //while
L.elem[i+1]=x; L.length++;
} //OrderInser
void OrderInsert( LinkList *L, ElemType e ) {
//L是帶頭結點且非遞減有序的單鏈表,插入新元素e,使L仍然有序
p=L;
while(p->next!=NULL &&p->next->data<e)
p=p->next; //找插入位置
s=(LNode*)malloc(sizeof(LNode));
s->next=p->next; s->data=e;
p->next=s;
} //OrderInsert O(n)
有序表的合並
使得合並後的表仍然有序:
void MergeList( LinkList *La, LinkList *Lb ) {
//La和Lb是帶頭結點且非遞減有序的單鏈表。將他們歸並成Lc
pa=La->next; pb=Lb->next;
Lc=pc=La; //La的頭結點作為Lc的頭結點
while(pa&& pb)
if(pa->data<=pb>data)
{
pc->next=pa; pc=pa; pa=pa->next;
}
else {
pc->next=pb; pc=pb; pb=pb->next;
}
pc->next = pa? pa : pb;
delete Lb;
}
鏈表應用:稀疏矩陣
稀疏矩陣:僅僅有少數非 0 矩陣元素
順序結構:
三元組順序表: (i,j,data)
Typedef struct{
Int I,j;
DataType item;
}Triple;
Typedef struct{
Triple data[MaxSize+1];
Int mu,nu,tu;
}TSMatrix;
在矩陣操作時矩陣非零元素會發生動態變化,用稀疏矩陣的鏈接表示可適應這樣的情況
稀疏矩陣的鏈接表示採用正交鏈表:行鏈表列鏈表十字交叉
行鏈表與列鏈表都是帶表頭結點的循環鏈表用表頭結點表征是第幾行,第幾列。
稀疏矩陣的行列表頭結點結構:0行0列表頭結點共用一個表頭結點。
列表頭:next: 給出下一個列表頭結點地址;down:給出本列中第一個非0矩陣元素結點地址
行表頭:right:給出本行中第一個非0矩陣元素結點地址
給出稀疏矩陣的正交鏈表表示的圖示:
數據結構的實現:
type struct OLNode
{
int i,j;//row,col
DataType e;
struct OLNode *rnext,*cnext;
}OLNode,OLink
typedef struct{
OLink *rhead,*chead;
int m,n,t;
}
線性表總結
下面幾個綱要是線性表的最基本的內容:
<1> 線性表的邏輯結構和各種存儲表示方法
<2> 定義在邏輯結構上的各種基本運算(操作)
<3> 在各種存儲結構上怎樣實現這些基本運算
<4> 各種基本運算的時間復雜性
<5> 線性表的長度是否能預先確定?處理過程中變化範圍怎樣?
長度確定、變化小時用順序表
長度變化大、難以預計最大長度時宜採用鏈表
<6> 對線性表的操作形式怎樣?
查詢操作多、刪除和插入操作少時使用順序表
頻繁插入和刪除操作宜採用鏈表
*************************************************************************************************************************************
數據結構(二):線性表的使用原則以及鏈表的應用-稀疏矩陣的三元組表示