For faster navigation, this Iframe is preloading the Wikiwand page for 双向链表.

双向链表

双向链表,又稱為双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表

存储结构

[编辑]
/* c2-4.h 线性表的双向链表存储结构 */
typedef struct DuLNode
{
	ElemType data;
	struct DuLNode *prior,*next;
}DuLNode,*DuLinkList;

基本操作

[编辑]
/* bo2-5.c 带头结点的双向循环链表(存储结构由c2-4.h定义)的基本操作(14个),包括算法2.18,2.19 */
void InitList(DuLinkList *L)
{	/* 产生空的双向循环链表L */
	*L=(DuLinkList)malloc(sizeof(DuLNode));
	if(*L)
		(*L)->next=(*L)->prior=*L;
	else
		exit(OVERFLOW);
}

void DestroyList(DuLinkList *L)
{	/* 操作结果:销毁双向循环链表L */
	DuLinkList q,p=(*L)->next; /* p指向第一个结点 */
	while(p!=*L) /* p没到表头 */
	{
		q=p->next;
		free(p);
		p=q;
	}
	free(*L);
	*L=NULL;
}

void ClearList(DuLinkList L) /* 不改变L */
{	/* 初始条件:L已存在。操作结果:将L重置为空表 */
	DuLinkList q,p=L->next; /* p指向第一个结点 */
	while(p!=L) /* p没到表头 */
	{
		q=p->next;
		free(p);
		p=q;
	}
	L->next=L->prior=L; /* 头结点的两个指针域均指向自身 */
}

Status ListEmpty(DuLinkList L)
{	/* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
	if(L->next==L&&L->prior==L)
		return TRUE;
	else
		return FALSE;
}

int ListLength(DuLinkList L)
{	/* 初始条件:L已存在。操作结果:返回L中数据元素个数 */
	int i=0;
	DuLinkList p=L->next; /* p指向第一个结点 */
	while(p!=L) /* p没到表头 */
	{
		i++;
		p=p->next;
	}
	return i;
}

Status GetElem(DuLinkList L,int i,ElemType *e)
{	/* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
	int j=1; /* j为计数器 */
	DuLinkList p=L->next; /* p指向第一个结点 */
	while(p!=L&&j<i) /* 顺指针向后查找,直到p指向第i个元素或p指向头结点 */
	{
		p=p->next;
		j++;
	}
	if(p==L||j>i) /* 第i个元素不存在 */
		return ERROR;
	*e=p->data; /* 取第i个元素 */
	return OK;
}

int LocateElem(DuLinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
{	/* 初始条件:L已存在,compare()是数据元素判定函数 */
	/* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
	/*           若这样的数据元素不存在,则返回值为0 */
	int i=0;
	DuLinkList p=L->next; /* p指向第1个元素 */
	while(p!=L)
	{
		i++;
		if(compare(p->data,e)) /* 找到这样的数据元素 */
			return i;
		p=p->next;
	}
	return 0;
}

Status PriorElem(DuLinkList L,ElemType cur_e,ElemType *pre_e)
{	/* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
	/*           否则操作失败,pre_e无定义 */
	DuLinkList p=L->next->next; /* p指向第2个元素 */
	while(p!=L) /* p没到表头 */
	{
		if(p->data==cur_e)
		{
			*pre_e=p->prior->data;
			return TRUE;
		}
		p=p->next;
	}
	return FALSE;
}

Status NextElem(DuLinkList L,ElemType cur_e,ElemType *next_e)
{	/* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
	/*           否则操作失败,next_e无定义 */
	DuLinkList p=L->next->next; /* p指向第2个元素 */
	while(p!=L) /* p没到表头 */
	{
		if(p->prior->data==cur_e)
		{
			*next_e=p->data;
			return TRUE;
		}
		p=p->next;
	}
	return FALSE;
}

DuLinkList GetElemP(DuLinkList L,int i) /* 另加 */
{	/* 在双向链表L中返回第i个元素的地址。i为0,返回头结点的地址。若第i个元素不存在,*/
	/* 返回NULL(算法2.18、2.19要调用的函数) */
	int j;
	DuLinkList p=L; /* p指向头结点 */
	if(i<0||i>ListLength(L)) /* i值不合法 */
		return NULL;
	for(j=1;j<=i;j++)
		p=p->next;
	return p;
}

Status ListInsert(DuLinkList L,int i,ElemType e)
{	/* 在带头结点的双链循环线性表L中第i个位置之前插入元素e,i的合法值为1≤i≤表长+1 */
	/* 改进算法2.18,否则无法在第表长+1个结点之前插入元素 */
	DuLinkList p,s;
	if(i<1||i>ListLength(L)+1) /* i值不合法 */
		return ERROR;
	p=GetElemP(L,i-1); /* 在L中确定第i个元素前驱的位置指针p */
	if(!p) /* p=NULL,即第i个元素的前驱不存在(设头结点为第1个元素的前驱) */
		return ERROR;
	s=(DuLinkList)malloc(sizeof(DuLNode));
	if(!s)
		return OVERFLOW;
	s->data=e;
	s->prior=p; /* 在第i-1个元素之后插入 */
	s->next=p->next;
	p->next->prior=s;
	p->next=s;
	return OK;
}

Status ListDelete(DuLinkList L,int i,ElemType *e) /* 算法2.19 */
{	/* 删除带头结点的双链循环线性表L的第i个元素,i的合法值为1≤i≤表长 */
	DuLinkList p;
	if(i<1) /* i值不合法 */
		return ERROR;
	p=GetElemP(L,i);  /* 在L中确定第i个元素的位置指针p */
	if(!p) /* p=NULL,即第i个元素不存在 */
		return ERROR;
	*e=p->data;
	p->prior->next=p->next;
	p->next->prior=p->prior;
	free(p);
	return OK;
}

void ListTraverse(DuLinkList L,void(*visit)(ElemType))
{	/* 由双链循环线性表L的头结点出发,正序对每个数据元素调用函数visit() */
	DuLinkList p=L->next; /* p指向头结点 */
	while(p!=L)
	{
		visit(p->data);
		p=p->next;
	}
	printf("\n");
}

void ListTraverseBack(DuLinkList L,void(*visit)(ElemType))
{	/* 由双链循环线性表L的头结点出发,逆序对每个数据元素调用函数visit()。另加 */
	DuLinkList p=L->prior; /* p指向尾结点 */
	while(p!=L)
	{
		visit(p->data);
		p=p->prior;
	}
	printf("\n");
}

[1]

参考文献

[编辑]
  1. ^ 高一凡. 《数据结构》算法实现及解析 2004年10月第2版. 西安: 西安电子科技大学出版社. ISBN 9787560611761 (中文). 
{{bottomLinkPreText}} {{bottomLinkText}}
双向链表
Listen to this article

This browser is not supported by Wikiwand :(
Wikiwand requires a browser with modern capabilities in order to provide you with the best reading experience.
Please download and use one of the following browsers:

This article was just edited, click to reload
This article has been deleted on Wikipedia (Why?)

Back to homepage

Please click Add in the dialog above
Please click Allow in the top-left corner,
then click Install Now in the dialog
Please click Open in the download dialog,
then click Install
Please click the "Downloads" icon in the Safari toolbar, open the first download in the list,
then click Install
{{::$root.activation.text}}

Install Wikiwand

Install on Chrome Install on Firefox
Don't forget to rate us

Tell your friends about Wikiwand!

Gmail Facebook Twitter Link

Enjoying Wikiwand?

Tell your friends and spread the love:
Share on Gmail Share on Facebook Share on Twitter Share on Buffer

Our magic isn't perfect

You can help our automatic cover photo selection by reporting an unsuitable photo.

This photo is visually disturbing This photo is not a good choice

Thank you for helping!


Your input will affect cover photo selection, along with input from other users.

X

Get ready for Wikiwand 2.0 🎉! the new version arrives on September 1st! Don't want to wait?