双向链表的表示与实现(C++版)

双向链表的结点存储结构描述如下:

typedef struct Node
{
	DataType data;
	struct Node *next;
	struct Node *prior;
}DListNode,*DLinkList;

双向链表的有些操作,如求链表的长度、查找链表的第i个结点等,与单链表中的算法实现基本没有什么差异。但是基于双向循环链表的插入和删除操作,因为涉及的前驱结点指针和后继结点指针,所以需要修改两个方向的指针。

(1)插入操作

插入操作就是在带头结点的双向循环链表中的第i个位置插入一个元素值为e的结点。插入成功返回1,否则返回0.算法思想是,首先找到第i个结点,用p指向该结点。在申请一个新结点,由s指向该结点,将e放入到数据域中。然后开始修改p和s指向的结点的指针域:修改s的prior域,使其指向p的直接前驱结点,即s->prior=p->prior;修改p的直接前驱结点的next域,使其指向s指向的结点,即p->prior->next=s;修改s的next域,使其指向p指向的结点,即s->next=p;修改p的prior域,使其指向s指向的结点,即p->prior=s。

代码实现如下:


int InsertDList(DLinkList head,int i,DataType e)
{
	DListNode *p,*s;
	int j=0;
	p=head->next;
	while(p!=head&&j<i)
	{
		p=p->next;
		j++;
	}
	if (j!=i)
	{
		printf("插入位置不正确");
		return 0;
	}
	s=(DListNode*)malloc(sizeof(DListNode));
	if (!s)
	{
		return -1;
	}
	s->data=e;
	s->prior=p->prior;
	p->prior->next=s;
	s->next=p;
	p->prior=s;
	return 1;
}
(2)删除操作

删除操作就是将带头结点的双向循环链表中的第i个结点删除。删除成功返回1,否则返回0.算法思想是,首先找到第i个结点,用p指向该结点。然后开始修改p指向的结点的直接前驱结点和直接后继结点的指针域,从而将p与链表断开。将p指向的结点与链表断开需要两步:第一步,修改p的前驱结点的next域,使其指向p的直接后继结点,即p->prior->next=p->next;第二步,修改p的直接后继结点的prior域,使其指向p的直接前驱结点,即p->next->prior=p->prior。代码实现如下:

int DeleteDList(DLinkList head,int i,DataType *e)
{
	DListNode *p;
	int j=0;
	p=head->next;
	while(p!=head&&j<i)
	{
		p=p->next;
		j++;
	}
	if (j!=i)
	{
		printf("删除位置不正确");
		return 0;
	}
	p->prior->next=p->next;
	p->next->prior=p->prior;
	free(p);
	return 1;
}

插入和删除操作的时间耗费主要在查找结点上,两者的时间复杂度都为O(n)。


注意:双向链表的插入和删除操作需要修改结点的prior和next域,比单链表操作要复杂些,因此要注意修改结点的指针域的顺序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值