数据结构之C语言实现双向循环链表(学习笔记)

一、双向循环链表

最后一个结点的后继指向头结点,头结点的前驱指向最后一个结点的双向链表

数据结构之C语言实现双向循环链表(学习笔记)_第1张图片

二、双向循环链表的基本操作

1.整表创建
void CreateDCLinkList(DCLinkList* L,int n)
{
	DCLinkList r,s;
	int data;
	(*L) = (DCLinkList)malloc(sizeof(DNode));
	(*L)->next = (*L); //初始化头结点的后继指针指向自己
	(*L)->prior = (*L); //初始化头结点的前驱指针指向自己
	r = (*L); //工作指针
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &data);
		s = (DCLinkList)malloc(sizeof(DNode));
		s->data = data;
		s->prior = r;     //连接上一结点
		s->next = (*L);  //新结点的后继指向头结点
		r->next = s;     //上一结点连接新结点
		(*L)->prior = s; //头结点的前继指向新节点
		r = s; //更新指针
	}
}
2.求表长
int GetLength(DCLinkList L)
{
	int count = 0;
	DCLinkList head = L; //记下头指针位置
	//画图细细品味
	while (L->next!=head)
	{
		L = L->next;
		count++;
	}
	return count;
}
3.获取结点
/*初始条件:表已经存在*/
/*操作结果:返回第i个位置的结点*/
DCLinkList GetNode(DCLinkList L, int i)
{
	int length = GetLength(L);
	DCLinkList p;
	if (i == 0)
		return L;
	if (i<0 || i>length) //位置不合法
		return NULL;
	if (i >= (length/ 2)) //从表尾开始遍历
	{
		p = L->prior;  //p被赋值为最后一个结点
		//当在表尾开始遍历时,只需要遍历(表长-i)次
		for (int j = 0; j < length - i; j++)
			p = p->prior;
	}
	else //从表头开始遍历
	{
		p = L; 
		//当在表头开始遍历时,只需要遍历i次
		for (int j = 0; j < i; j++)
			p = p->next;
	}
	return p;
}
4.插入结点

数据结构之C语言实现双向循环链表(学习笔记)_第2张图片

/*初始条件:表已经存在*/
/*操作结果:在第i个结点插入结点*/
int ListInsert(DCLinkList* L, int i, ElemType e)
{
	DCLinkList p, s;
	p = GetNode((*L), i - 1); //找到第i个结点的前驱结点
	if (p == NULL)
		return 0;
	s = (DCLinkList)malloc(sizeof(DNode));
	s->data = e;
	s->next = p->next; 
	s->prior = p;
	p->next->prior = s;
	p->next = s;
	return 1;
}
5.删除结点

数据结构之C语言实现双向循环链表(学习笔记)_第3张图片

/*初始条件:表已经存在*/
/*操作结果:删除第i个位置上的结点,并用e回收删除结点的数据域*/
int ListDelete(DCLinkList* L, int i, ElemType* e)
{
	DCLinkList p,s;
	p = GetNode((*L), i);
	if (p == NULL)
		return 0;
	p->prior->next = p->next;
	p->next->prior = p->prior;
	*e = p->data;
	free(p);
	return 1;
}
6.重置为空表
void ClearList(DCLinkList* L)
{
	DCLinkList p,s;
	p = (*L)->next; //从第一个结点开始删除
	while (p!= (*L)) //当p等于头结点时说明已经遍历完整表
	{
		s = p; //备份要删除的结点
		p = p->next; //移动到下一个结点
		free(s); //删除备份结点
	}
	//重置头结点的后继和前驱
	(*L)->next = (*L); 
	(*L)->prior = (*L);
}

你可能感兴趣的:(笔记)