C语言实现双向循环链表[下]

本次实现的是带有头结点的双向循环链表。此文参考了百度文库中的内容。

其基本操作有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");
}


 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值