在循环双向链表存储结构中,每个结点都有两个指针域:prior和next,prior指向直接前驱,next指向直接后继,最后一个结点的next指向头结点,头结点的prior指向最后一个结点。显然,通过指向结点的指针p的p->next可以直接得到某结点的后继结点地址,也可以通过p->prior直接得到某结点的前驱结点的地址,而p->prior->next表示的是p自身存储的地址;同样,p->next->prior也是p本身存储的地址。
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int ElemType;
typedef struct Node
{
ElemType elem;
struct Node* next;
struct Node* prior;
}Node,*Ptr;
typedef Ptr *SqLisrPtr;
typedef enum Status
{
success, fial, fatal, range_error
}Status;
Status List_Retrieve(SqLisrPtr L, int pos, ElemType* elem)
{
Status s = range_error;
Ptr p = (*L)->next;
int i = 0;
while (p != *(L) && i < pos)
{
p = p->next;
i++;
}
if (p != (*L) && i == pos)
{
*elem = p->elem;
s = success;
}
return s;
}
Status List_Locate(SqLisrPtr L, ElemType elem, int* pos)
{
Status s = range_error;
Ptr p = (*L)->next;
int i = 0;
while (p != (*L))
{
if (p->elem == elem)
{
break;
}
i++;
p = p->next;
}
if (p != (*L))
{
*pos = i;
s = success;
}
return s;
}
Status List_SetPosition(SqLisrPtr L, int pos,Ptr* ptr)
{
Status s = range_error;
Ptr p = (*L)->next;
int i = 0;
if (pos == -1)
{
*ptr = (*L);
s = success;
return s;
}
while (p != (*L) && i < pos)
{
p = p->next;
i++;
}
if (p != (*L) && i == pos)
{
*ptr = p;
s = success;
}
return s;
}
Status List_Insert(SqLisrPtr L, int pos, ElemType elem)
{
Status status;
Ptr p, s;
status = List_SetPosition(L, pos - 1, &p);
if (status == success)
{
s = (Ptr)malloc(sizeof(Node));
if (s)
{
s->elem = elem;
s->next = p->next;
p->next = s;
s->next->prior = s;
s->prior = p;
status = success;
}
else
{
status = fatal;
}
}
else
{
status = range_error;
}
return status;
}
Status List_Remove(SqLisrPtr L, int pos)
{
Status status;
Ptr p, s;
status = List_SetPosition(L, pos - 1, &p);
if (status == success)
{
s = p->next;
p->next = s->next;
p->next->prior = p;
free(s);
s = NULL;
status = success;
}
return status;
}
Status List_Init(SqLisrPtr L)
{
Status status = fatal;
(*L) = (Ptr)malloc(sizeof(Node));
if (*L)
{
(*L)->next = *L;
(*L)->prior = *L;
status = success;
}
return status;
}
void List_Clear(SqLisrPtr L)
{
Ptr p, q;
p = (*L);
q = p->next;
while (q != (*L))
{
p->next = q->next;
free(q);
q = p->next;
}
}
void List_Destroy(SqLisrPtr L)
{
List_Clear(L);
free((*L));
}
bool List_Empty(SqLisrPtr L)
{
return (*L)->next == (*L);
}
int List_Size(SqLisrPtr L)
{
int length = 0;
Ptr p = (*L)->next;
while (p != (*L))
{
p = p->next;
length++;
}
return length;
}
Status List_Prior(SqLisrPtr L, int pos, ElemType* elem)
{
Status status;
Ptr p;
status = List_SetPosition(L, pos - 1, &p);
if (status == success)
{
*elem = p->elem;
}
return status;
}
Status List_Next(SqLisrPtr L, int pos, ElemType* elem)
{
Status status;
Ptr p;
status = List_SetPosition(L, pos + 1, &p);
if (status == success)
{
*elem = p->elem;
}
return status;
}
Status List_Create(SqLisrPtr L, ElemType* elem, int len)
{
Status s;
s = List_Init(L);
if (s == success)
{
for(int i = len -1; i >=0; i--)
{
List_Insert(L, 0, elem[i]);
}
}
return s;
}
void List_Show(SqLisrPtr L)
{
Ptr p = (*L)->next;
while (p != (*L))
{
printf("%d ", p->elem);
p = p->next;
}
printf("\n");
}
int main()
{
SqLisrPtr L = (SqLisrPtr)malloc(sizeof(Ptr));
Status status;
ElemType my_elem[5] = { 1,2,3,4,5 };
if ((status = List_Create(L,my_elem,5)) != success)
{
printf("create error\n");
exit(-1);
}
printf("created\n");
return 0;
}
总结:单链表只能从头结点开始遍历整个链表,而循环双向链表可以从任意结点开始遍历整个链表。另外,单链表访问直接前驱只能从链表的头结点开始,顺着各结点的next域进行,其时间复杂度为O(n),循环双向链表可以通过p->prior直接访问其直接前驱,时间复杂度为O(1)。