数据结构笔记--双链表

双链表的构建

单链表从某个结点出发只能顺指针向后寻查其他的结点。若要寻查结点的直接前驱,则必须从表头指针出发。位克服单链表的单向性的缺点,可利用双链表。
双链表的模型:
在这里插入图片描述

typedef struct Node{			//定义双链表节点类型
	ElemType data;      		//数据域
	struct Node *prior,*next;	//前驱和指针域
}Node,*LinkList; 			

双链表也可以有循环表在这里插入图片描述

初始化双链表(带头结点)

 bool InitLinkList(LinkList &L){
	L=(Node*)malloc(sizeof(NMode));			//分配头结点
	if(L==NULL){							//内存不足,分配失败
		return false;				
	}
	L->prior=NULL;								//头结点的p永远指向NULL
	L->next=NULL;							//头结点之后暂时没有节点
	return true;
}
void testLinkList(){
//初始化双链表
	LinkList L;
	InitLinkList(L);
}

判断双链表是否为空(带头结点)

bool Empty(LinkList L){
	if (L->next == NULL)
		return true;
	else
		return false;
}

双链表的插入

在p结点之后插入s结点

bool InsertNextNode(Node *p,Node *s){
	if (p==NULL || s==NULL )
		return false;
	s->next=p->next;			//将结点*s插入到结点*p之后
	if (p->nezt != NULL)		//如果p结点后面有后继结点
	p->next->prior=s;
	s->prior=p;
	p->next=s;
}

在这里插入图片描述

前插操作可以看作是前驱节点的后插
例如:在a2前面插入节点可以转换成a1的后插操作
在这里插入图片描述

双链表的删除

删除结点不是尾结点:

在这里插入图片描述
删除p的后继结点q

p->next=q->next;
q->next->prior=p;
free(p);
改进做法:判断删除节点是否为尾结点在这里插入图片描述

//删除p结点的后继结点

bool DeleteNextNode(Node *p){
	if (p == NULL)
		return false;
	Node *q = p->next;			//找到p的后继结点q
	if (q == NULL)
		return false;			//p没有后继
	p->next=q->next;
	if (q->next != NULL)		//q结点不是最后一个结点
		q->next->prior=p;
	free(q);					//释放结点空间
	return true;
}

销毁一个双链表

void DestoryList(LinkList &L){
	//循环释放各个数据结点
	while (l->next != NULL)
		DeleteNextNode(L);
	free(L);			//释放头节点
	L=NULL;				//头指针指向NULL
}

双链表的遍历

向后遍历

while(p!=NULL){
	//对结点p做出相应的处理,如打印
	p=p->next;
}

向前遍历

while(p!=NULL){
	//对结点p做出相应的处理
	p=p->prior;
}

双链表不可随机存取,按位查找、按值查找操作都只能用遍历的方式实现。
时间复杂度O(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值