本次实现的是带有头结点的双向循环链表。此文参考了百度文库中的内容。
其基本操作有14个。
typedef struct DuLNode
{ ElemType data;
DuLNode *prior,*next;
}DuLNode,*DuLinkList;
//函数声明
void InitList(DuLinkList *L);//初始化链表
void ClearList(DuLinkList L);//清空表
void DestroyList(DuLinkList &L);//销毁双向链表
int ListEmpty(DuLinkList L);//判断表是否为空
int ListLength(DuLinkList L);//判断表的长度
int GetElem(DuLinkList L,int i,ElemType *e);//返回第i个元素的值
//返回L中第1个与e满足关系compare()的数据元素的位序
int LocateElem(DuLinkList L,ElemType e,int(*compare)(ElemType,ElemType));
int PriorElem(DuLinkList L,ElemType cur_e,ElemType *pre_e);//前驱判断
int NextElem(DuLinkList L,ElemType cur_e,ElemType *next_e);//后继判断
DuLinkList GetElemP(DuLinkList L,int i);//返回第i个元素的地址
int ListInsert(DuLinkList L,int i,ElemType e);//在表的第i个位置之前插入元素e
int ListDelete(DuLinkList L,ElemType *e);//删除表中第i个元素
void ListTraverse(DuLinkList L,void(*visit)(ElemType));//正序对每个元素调用函数visit()
void ListTraverseBack(DuLinkList L,void(*visit)(ElemType));//逆序对每个元素调用函数visit()
/* 产生空间的双向循环链表 */
void InitList(DuLinkList *L)
{
*L=(DuLinkList)malloc(sizeof(DuLNode));
if(NULL != (*L))
(*L)->next = (*L)->prior = (*L);
else
exit(0);
}
/* 清空链表 */
void ClearList(DuLinkList L)
{
DuLinkList p = L->next;//p指向第一个结点
while(p != L)
{
p = p->next;
free(p->prior);
}
L->next = L->prior = L;//头结点的两个指针域指向其身
}
/* 销毁双向循环链表L */
void DestroyList(DuLinkList *L)
{
DuLinkList q,p = (*L)->next; /* p指向第一个结点 */
while(p != (*L)) /* p没到表头 */
{
q = p->next;
free(p);
p = q;
}
free((*L));
(*L) = NULL;
}
/* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
int ListEmpty(DuLinkList L)
{
if(L->next == L && L->prior == L)
return true;
else
return false;
}
/* 返回表的长度 */
int ListLength(DuLinkList L)
{
int len = 0;
DuLinkList p = L->next;//p指向第一个结点
while(p != L)
{
len++;
p = p->next;
}
return len;
}
/* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
int GetElem(DuLinkList L,int i,ElemType *e)
{
int j =1 ;
DuLinkList p = L->next;//p指向第一个结点
while(p != L && j < i)//顺指针向后查找,直到p指向第i个元素
{
j++;
p = p->next;
}
if(p == L || j > i)
return -1;
*e = p->data;
return 0;
}
/* 初始条件:L已存在,compare()是数据元素判定函数 */
/* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int LocateElem(DuLinkList L,ElemType e,int(*compare)(ElemType,ElemType))
{
int i = 0;
DuLinkList p = L->next;
while(p != L)//p未指向头结点
{
i++;
if(compare(p->data,e))//找到这样的元素
return i;
p = p->next;
}
return 0;
}
/* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
/* 否则操作失败,pre_e无定义 */
int PriorElem(DuLinkList L,ElemType cur_e,ElemType *pre_e)
{
DuLinkList p = L->next->next;//p指向第2个元素
while(p != L)
{
if(p->data == cur_e)//p指向值为cur_e的结点
{
*pre_e = p->prior->data;//将p的前驱结点的值赋给
return 0;
}
p = p->next;
}
return -1;
}
/* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
/* 否则操作失败,next_e无定义 */
int NextElem(DuLinkList L,ElemType cur_e,ElemType *next_e)
{
DuLinkList p = L->next->next;//p指向第二个元素
while(p != L)
{
if(p->prior->data == cur_e)//p所指结点的前驱指向cur_e
{
*next_e = p->data;//将p所指结点的值赋给next_e
return 0;
}
p = p->next;
}
return -1;
}
/* 在双向链表L中返回第i个元素的地址。i为0,返回头结点的地址。若第i个元素不存在,返回NULL*/
DuLinkList GetElemP(DuLinkList L,int i)
{
int j;
DuLinkList p = L; //p指向头结点
if(i < 0 || i > ListLength(L))
return NULL;
for(j = 1;j <= i;j++) //p指向第i个结点
p = p->next; //p指向下一个结点
return p;
}
/* 在带头结点的双链循环线性表L中第i个位置之前插入元素e,i的合法值为1≤i≤表长+1 */
int ListInsert(DuLinkList L,int i,ElemType e)
{
DuLinkList p,s;
if(i < 1 || i > ListLength(L)+1)
return -1;
p = GetElemP(L,i-1);//在L中确定第i个结点前驱的位置指针p
if(!p)
return -1;
s = (DuLinkList)malloc(sizeof(DuLNode));//生成新结点
if(!s)
return -1;
s->data = e; //将e赋给新的结点
s->prior = p; //新结点的前驱为第i-1个结点
s->next = p->next; //新结点的后继为第i个结点
p->next->prior = s;//第i个结点的前驱指向新结点
p->next = s; //第i-1个结点的后继指向新结点
return 0;
}
/* 删除带头结点的双链循环线性表L的第i个元素,i的合法值为1≤i≤表长 */
int ListDelete(DuLinkList L, int i, ElemType *e)
{
DuLinkList p;
if(i < 1)
return -1;
p = GetElemP(L,i);//在L中确定第i个元素的位置指针
if(!p)
return -1;
*e = p->data;//把第i个结点的元素的值赋给e
p->prior->next = p->next;//第原i-1个结点的后继指向原第i+1个结点
p->next->prior = p->prior;//第原i+1个结点的前驱指向原第i-1个结点
free(p);
return OK;
}
/* 由双向循环链表的表头出发,正序对每个数据元素调用函数visit() */
void ListTraverse(DuLinkList L,void(*visit)(ElemType))
{
DuLinkList p = L->next;//p指向首元结点
while(p != L)
{
visit(p->data);//对p所指结点调用函数visit()
p = p->next;
}
printf("\n");
}
/* 由双向循环链表的表头出发,逆序对每个元素调用函数visit() */
void ListTraverseBack(DuLinkList L,void(*visit)(ElemType))
{
DuLinkList p = L->prior;//p指向尾结点
while(p != L)
{
visit(p->data);
p=p->prior;
}
printf("\n");
}