数据结构之线性表(双链表)


一、双链表的定义与表示

1.双链表结点结构

在这里插入图片描述

2.双链表结点结构的定义

typedef struct DLNode{
	Elemtype data;     //data中存放结点数据域
	struct DLNode *prior; //指向前驱结点的指针
	struct DLNode *next; //指向后继节点的指针
}DLNode,*DLinkList; //DLinList为指向结构体DLNode的指针类型

二、双链表

1.双链表结构的对称性

双链表结构的对称性(设指针p指向某一结点)
p->prior->next = p = p->next->prior
在这里插入图片描述
:在双链表的一些操作中(如:求表长,取元素值和查找元素等),如果只涉及到一个方向上的指针,它们的算法与线性表相同。但是,在插入、删除时,则需要同时修改两个方向上的指针。

2.建立双链表

2.1.头插法建表

//头插法建立双链表 
void createListH(DLinkList &L,int n){
	DLinkList s;
	L=(struct DLNode*)malloc(sizeof(struct DLNode)); //创建头结点
	L->next=NULL;  //后指针域设为空
	L->prior=NULL;  //前指针域设为空
	for(int i=0;i<n;i++){
		s=(struct DLNode*)malloc(sizeof(struct DLNode));  //循环建立数据结点
		scanf("%d",&s->data);
		s->next=L->next;   //将s结点插在头结点之后
		if(L->next!=NULL){  //若L中存在数据节点,修改L->next的前驱指针
			L->next->prior=s;
		}
		L->next=s;
		s->prior=L;	
	} 	
}

2.2.尾插法建表

//尾插法建立双链表
void creatListR(DLinkList &L,int n){
	DLinkList r,s;
	L=(struct DLNode*)malloc(sizeof(struct DLNode)); //创建头结点
	L->next=L->prior=NULL; //前后指针域置为空
	r=L;    //r始终指向尾结点,开始时指向头结点
	for(int i=0;i<n;i++){
		s=(struct DLNode*)malloc(sizeof(struct DLNode));  //创建数据结点s
		scanf("%d",&s->data);
		s->next=NULL;
		r->next=s;
		s->prior=r;
		r=s;
	} 	
}

3.插入数据结点

在双链表L中第i个位置上插入数据元素e

//插入数据元素
bool insertList(DLinkList &L,int i,ElemType e){
	DLinkList p,s;
	p=L;  //p指向头结点
	int j=0;    //j初始为0
	while(p->next!=NULL&&j<i-1){   //找到第i-个结点p
		j++;
		p=p->next;
	}
	if(p==NULL||i<=0){    //没有找到或者是参数错误,返回false
		return false;
	}
	else{
		s=(struct DLNode*)malloc(sizeof(struct DLNode));    //创建一个数据结点s
		s->data=e;
		s->next=p->next;
		if(p->next!=NULL){  //若p结点存在后继结点,修改这个后继结点的前驱指针
			p->next->prior=s;
		}
		s->prior=p;
		p->next=s;
		
		return true;	
	}
	
} 

4.删除数据结点

在双链表中删除第i个结点
:不管是在第i个位置上插入一个结点,还是删除第i 个结点,都要注意,要插入的结点的位置或者是要删除的那个结点是否存在后继结点。在写代码时,这点很容易被忽视。

//删除数据结点
bool delList(DLinkList &L,int i){
	DLinkList p,q,s;
	p=L;
	int j=0;
	while(p->next!=NULL&&j<i-1){  //找到第i-1个结点p
		j++;
		p=p->next;
	}
	if(p==NULL||i<=0){
		return false;
	}
	else{
		q=p->next;   //q指向第i个结点,也就是要删除的结点
		if(q==NULL){
			return false;
		}
		p->next=q->next;
		if(q->next!=NULL){ //若q结点存在后继结点,修改这个后继结点的前驱指针
			q->next->prior=p;
		}
		free(q);
		return true;	
	}
} 

5.输出双链表

//输出双链表
void printList(DLinkList L){
	DLinkList p;
	p=L->next;
	while(p){
		printf("%4d",p->data);
		p=p->next;
	}
	printf("\n");
} 

三、循环双链表

  1. 和单链表的循环表类似,双链表也有循环表
  2. 让头结点的前驱指针指向链表的最后一个结点
  3. 让最后一个结点的后继指针指向头结点
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小言同学Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值