之前讨论的链式存储结构的结点中只有一个指示直接后继的指针域,由此,从某个结点出发只能顺着指针往后找其他的结点,若要查找结点的直接前驱,只能从表头出发,因此为了克服单链表的这种缺点,引入了双向链表。双向链表结点中有两个指针域,其一指向直接后继,另一指向直接前驱。
1、双向链表的存储结构
//------线性表的双向链表的存储结构------ typedef struct DuLNode{ int data;//数据域 struct DuLNode *prior;//直接前驱 struct DuLNode *next;//直接后继 }DuLNode,*DuLinkList;
双向链表的循环结构示意图:
2、双向链表的删除操作
Status ListDelete_DuL(DuLinkList &L, int i, ElemType &e){ //删除带头结点的双向链表L的第i个元素,i的合法范围:1<=i<=表长 DuLinkList p; if(!(p = GetElemp_DuL(L,i)))//在L中确定第i个元素的位置指针p return ERROR; e = p->data; p->prior->next = p->next; p->next->prior = p->prior; free(p); return OK; }
2、双向链表的插入操作
Status ListInsert_DuL(DuLinkList &L, int i, ElemType e){ //在带头结点的双向链表L中第i个位置之前插入元素e //i的合法范围1<=i<=表长+1 DuLinkList p,s; if(!(p = GetElemP_DuL(L,i)));//在L中确定插入的位置 return ERROR; if(!(s = (DuLinkList)malloc(sizeof(DuLNode))) return ERROR; s->data = e; s->prior = p->prior; p->prior->next = s; s->next = p; p->prior = s; return OK; }
双向链表实践
#include<stdio.h> #include<stdlib.h> #include<malloc.h> #define OK 1 #define ERROR 0 typedef char ElemType; typedef int Status; typedef struct DualNode{ ElemType data; struct DualNode *prior; struct DualNode *next; }DualNode,*DuLinkList; //初始化双向链表(双向循环链表) Status InitList(DuLinkList &L){ DuLinkList p,q; L = (DuLinkList)malloc(sizeof(DualNode)); if( !L ) return ERROR; L->next = L->prior = NULL; p = L; for( int i = 0; i < 26; i++){ q = (DuLinkList)malloc(sizeof(DualNode)); if( !q ) return ERROR; q->data = 'A'+i;//ACCIS码赋值,A,B,C...... q->prior = p; q->next = p->next; p->next = q; p = q; } p->next = L->next; L->next->prior = p;//双向循环链表 return OK; } void Caesar(DuLinkList &L, int i){ if( i > 0 ){ do{ L = L->next; }while( --i ); } if( i < 0 ){ do{ L = L->next; }while( ++i ); } } int main(){ DuLinkList L; InitList(L); printf("请输入一个整数:"); int n; scanf("%d",&n); printf(" "); Caesar(L,n); for( int i = 0; i < 26; i++ ){ L = L->next; printf("%c ",L->data); } printf(" "); return 0; }