双向链表的数据结构:
1 /* c2-4.h 线性表的双向链表存储结构 */ 2 typedef struct DuLNode 3 { 4 ElemType data; 5 struct DuLNode *prior,*next; 6 }DuLNode,*DuLinkList;
插入:
删除:
代码实现:
1 /* bo2-5.c 双链循环线性表(存储结构由c2-4.h定义)的基本操作(14个) */ 2 Status InitList(DuLinkList *L) 3 { /* 产生空的双向循环链表L */ 4 *L=(DuLinkList)malloc(sizeof(DuLNode)); 5 if(*L) 6 { 7 (*L)->next=(*L)->prior=*L; 8 return OK; 9 } 10 else 11 return OVERFLOW; 12 } 13 14 Status DestroyList(DuLinkList *L) 15 { /* 操作结果:销毁双向循环链表L */ 16 DuLinkList q,p=(*L)->next; /* p指向第一个结点 */ 17 while(p!=*L) /* p没到表头 */ 18 { 19 q=p->next; 20 free(p); 21 p=q; 22 } 23 free(*L); 24 *L=NULL; 25 return OK; 26 } 27 28 Status ClearList(DuLinkList L) /* 不改变L */ 29 { /* 初始条件:L已存在。操作结果:将L重置为空表 */ 30 DuLinkList q,p=L->next; /* p指向第一个结点 */ 31 while(p!=L) /* p没到表头 */ 32 { 33 q=p->next; 34 free(p); 35 p=q; 36 } 37 L->next=L->prior=L; /* 头结点的两个指针域均指向自身 */ 38 return OK; 39 } 40 41 Status ListEmpty(DuLinkList L) 42 { /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */ 43 if(L->next==L&&L->prior==L) 44 return TRUE; 45 else 46 return FALSE; 47 } 48 49 int ListLength(DuLinkList L) 50 { /* 初始条件:L已存在。操作结果:返回L中数据元素个数 */ 51 int i=0; 52 DuLinkList p=L->next; /* p指向第一个结点 */ 53 while(p!=L) /* p没到表头 */ 54 { 55 i++; 56 p=p->next; 57 } 58 return i; 59 } 60 61 Status GetElem(DuLinkList L,int i,ElemType *e) 62 { /* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */ 63 int j=1; /* j为计数器 */ 64 DuLinkList p=L->next; /* p指向第一个结点 */ 65 while(p!=L&&j<i) /* 顺指针向后查找,直到p指向第i个元素或p指向头结点 */ 66 { 67 p=p->next; 68 j++; 69 } 70 if(p==L||j>i) /* 第i个元素不存在 */ 71 return ERROR; 72 *e=p->data; /* 取第i个元素 */ 73 return OK; 74 } 75 76 int LocateElem(DuLinkList L,ElemType e,Status(*compare)(ElemType,ElemType)) 77 { /* 初始条件:L已存在,compare()是数据元素判定函数 */ 78 /* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */ 79 /* 若这样的数据元素不存在,则返回值为0 */ 80 int i=0; 81 DuLinkList p=L->next; /* p指向第1个元素 */ 82 while(p!=L) 83 { 84 i++; 85 if(compare(p->data,e)) /* 找到这样的数据元素 */ 86 return i; 87 p=p->next; 88 } 89 return 0; 90 } 91 92 Status PriorElem(DuLinkList L,ElemType cur_e,ElemType *pre_e) 93 { /* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */ 94 /* 否则操作失败,pre_e无定义 */ 95 DuLinkList p=L->next->next; /* p指向第2个元素 */ 96 while(p!=L) /* p没到表头 */ 97 { 98 if(p->data==cur_e) 99 { 100 *pre_e=p->prior->data; 101 return TRUE; 102 } 103 p=p->next; 104 } 105 return FALSE; 106 } 107 108 Status NextElem(DuLinkList L,ElemType cur_e,ElemType *next_e) 109 { /* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */ 110 /* 否则操作失败,next_e无定义 */ 111 DuLinkList p=L->next->next; /* p指向第2个元素 */ 112 while(p!=L) /* p没到表头 */ 113 { 114 if(p->prior->data==cur_e) 115 { 116 *next_e=p->data; 117 return TRUE; 118 } 119 p=p->next; 120 } 121 return FALSE; 122 } 123 124 DuLinkList GetElemP(DuLinkList L,int i) /* 另加 */ 125 { /* 在双向链表L中返回第i个元素的位置指针(算法2.18、2.19要调用的函数) */ 126 int j; 127 DuLinkList p=L; 128 for(j=1;j<=i;j++) 129 p=p->next; 130 return p; 131 } 132 133 Status ListInsert(DuLinkList L,int i,ElemType e) /* 改进算法2.18 */ 134 { /* 在带头结点的双链循环线性表L中第i个位置之前插入元素e,i的合法值为1≤i≤表长+1 */ 135 DuLinkList p,s; 136 if(i<1||i>ListLength(L)+1) /* i值不合法 */ 137 return ERROR; 138 p=GetElemP(L,i-1); /* 在L中确定第i-1个元素的位置指针p */ 139 if(!p) /* p=NULL,即第i-1个元素不存在 */ 140 return ERROR; 141 s=(DuLinkList)malloc(sizeof(DuLNode)); 142 if(!s) 143 return OVERFLOW; 144 s->data=e; /* 在第i-1个元素之后插入 */ 145 s->prior=p; 146 s->next=p->next; 147 p->next->prior=s; 148 p->next=s; 149 return OK; 150 } 151 152 Status ListDelete(DuLinkList L,int i,ElemType *e) /* 算法2.19 */ 153 { /* 删除带头结点的双链循环线性表L的第i个元素,i的合法值为1≤i≤表长+1 */ 154 DuLinkList p; 155 if(i<1||i>ListLength(L)) /* i值不合法 */ 156 return ERROR; 157 p=GetElemP(L,i); /* 在L中确定第i个元素的位置指针p */ 158 if(!p) /* p=NULL,即第i个元素不存在 */ 159 return ERROR; 160 *e=p->data; 161 p->prior->next=p->next; 162 p->next->prior=p->prior; 163 free(p); 164 return OK; 165 } 166 167 void ListTraverse(DuLinkList L,void(*visit)(ElemType)) 168 { /* 由双链循环线性表L的头结点出发,正序对每个数据元素调用函数visit() */ 169 DuLinkList p=L->next; /* p指向头结点 */ 170 while(p!=L) 171 { 172 visit(p->data); 173 p=p->next; 174 } 175 printf(" "); 176 } 177 178 void ListTraverseBack(DuLinkList L,void(*visit)(ElemType)) 179 { /* 由双链循环线性表L的头结点出发,逆序对每个数据元素调用函数visit()。另加 */ 180 DuLinkList p=L->prior; /* p指向尾结点 */ 181 while(p!=L) 182 { 183 visit(p->data); 184 p=p->prior; 185 } 186 printf(" "); 187 }