循環單鏈表的出現,雖然能夠實現從任一結點出發沿着鏈能找到其前驅結點,但時間耗費是O(n)。
如果希望從表中快速確定某一個結點的前驅,另一個解決方法就是在單鏈表的每個結點里再增加一個指向其前驅的指針域prior。
這樣形成的鏈表中就有兩條方向不同的鏈,我們可稱之為雙(向)鏈表(DoubleLinked List)。雙鏈表的結構定義如下:
typedef structDNode { ElemType data; struct DNode*prior,*next; }DNode,*DoubleList;
與單鏈表類似,雙鏈表一般也是有頭指針唯一確定的,增加頭結點也能使雙鏈表的某些運算變得方便。同時雙向鏈表也可以有循環表,稱為雙向循環鏈表,其結構如圖2.15所示。
由於在雙向鏈表中既有前向鏈又有后向鏈,尋找任一個結點的直接前驅結點與直接后繼結點變得非常方便。設指針p指向雙鏈表中某一結點,則有下式成立:
P->prior->next=p=p->next->prior
在雙向鏈表中,那些只涉及后繼指針的算法,如求表長度、取元素、元素定位等,與單鏈表中相應的算法相同,但對於前插和刪除操作則涉及到前驅和后繼兩個方向的指針變化,因此與單鏈表中的算法不同。
1.雙向鏈表的前插操作
算法描述:欲在雙向鏈表第i個結點之前插入一個新的結點,則指針的變化情況如圖2.16所示。
int DlinkIns(DoubleList L,int i,ElemType e) { DNode *s,*p; …/*先檢查待插入的位置i是否合法(實現方法同單鏈表的前插操作)*/ …/*若位置i合法,則讓指針p指向它*/ s=(DNode *)malloc(sizeof(DNode)); if(s) { s->data=e; s->prior=p->prior;p->prior->next=s; s->next=p;p->prior=s; return TRUE; } else teturn fALSE; }
2.雙向鏈表的刪除操作
算法描述:欲刪除雙向鏈表中的第i個結點,則指針的變化情況如圖2.17所示。
int DlinkDel(DoubleList L,int i,ElemType *e) { DNode *p; …/*首先檢查待插入的位置i是否合法(實現方法同單鏈表的刪除操作)*/ …/*若位置i合法,則讓指針p指向它*/ *e=p->prior->next=p->next; p->next->prior->p=p->prior; free(p); return TRUE; }
轉自:
https://blog.csdn.net/csdanca11/article/details/7173856