数据结构学习笔记5——双链表

数据结构学习笔记5——双链表

以下笔记为笔者复习时使用,仅供参考.

存储结构

双链表的存储结构同单链表类似,逻辑上相邻的元素,在内存中并不相邻,但是增加了一个前驱指针,指向上一个节点。
以不带头结点的双链表为例:
双链表
物理存储结构:
双链表内存存储结构

数据结构

双链表的数据结构定义如下:

typedef struct L_node
{
	elem_t data;
	struct L_node* pprior;//前驱指针
	struct L_node* pnext;//后继指针
}DLinklist, * p_dlist;

基本操作

初始化

双链表的初始化

DLinklist InitDlinklist(p_dlist L)
{
	L = (p_dlist)calloc(1, sizeof(DLinklist));//申请节点并初始化
	if (NULL == L)
	{
		printf("memory is full\n");;//内存不足分配失败
	}
	return *L;
}

头插法、尾插法

//头插法
DLinklist Head_insert(p_dlist L_head, p_dlist L_tail)
{
	int i;
	while (scanf("%d", &i) != EOF)
	{
		p_dlist pnew = (p_dlist)calloc(1, sizeof(DLinklist));
		pnew->data = i;
		if (0 == L_head->data)
		{//链表为空时,首尾指针指向pnew
			L_head = pnew;
			L_tail = pnew;
		}
		else
		{//链表非空时,头插
			pnew->pnext = L_head;
			L_head->pprior = pnew;//更改前驱指针
			L_head = pnew;
		}
	}
	return *L_head;
}
//尾插法
DLinklist Tail_insert(p_dlist L_head, p_dlist L_tail)
{
	int i;
	while (scanf("%d",&i)!=EOF)
	{
		p_dlist pnew = (p_dlist)calloc(1, sizeof(DLinklist));
		pnew->data = i;
		if (0 == L_head->data)
		{//链表为空时,首尾指针都指向新节点pnew
			L_head = pnew;
			L_tail = pnew;
		}
		else
		{//链表非空时则尾插
			L_tail->pnext = pnew;
			pnew->pprior = L_tail;//新节点的前驱指针指向原链表的尾部
			L_tail = pnew;
		}
	}
	return *L_head;
}

以下是笔者写的有序插入(未测试),可用于参考思路

DLinklist Sort_insert(p_dlist L_head,p_dlist L_tail)
{
	int i;
	while (scanf("%d",&i)!=EOF)
	{
		p_dlist pnew = (p_dlist)calloc(1, sizeof(DLinklist));
		p_dlist pcur, ppre;//定义两个哨兵,关羽(pcur)、张飞(ppre)
		pcur = L_head;//让两个哨兵都指向头节点
		ppre = pcur;
		pnew->data = i;
		if (0 == L_head->data) 
		{//链表为空时,首尾指针都指向新节点
			L_head = pnew;
			L_tail = pnew;
		}
		else if(pnew->data<L_head->data)
		{//新节点的元素小于链表的第一个元素,头插
			pnew->pnext = L_head;
			L_head->pprior = pnew;
			L_head = pnew;
		}
		else
		{
			while (pcur)
			{//遍历链表
				if (pnew->data < pcur->data)
				{
				//当新元素小于关羽(pcur),即大于张飞时,则插入
					ppre->pnext = pnew;
					pnew->pprior = ppre;
					pnew->pnext = pcur;
					pcur->pprior = pnew;
					break;
				}
				//关羽(pcur)先走一步,张飞(ppre)紧随其后,遍历链表
				ppre = pcur;
				pcur = pcur->pnext;
			}
			if (NULL == pcur)
			{//遍历到链表尾部,则尾插
				L_tail->pnext = pnew;
				pnew->pprior = L_tail;
				L_tail = pnew;
			}
		}
	}
	return *L_head;
}

删除

DLinklist List_delete(p_dlist L_head, p_dlist L_tail)
{//未测试
	int i;
	while (scanf("%d",&i)!=EOF)
	{
		p_dlist pcur, ppre;
		pcur = L_head;
		ppre = pcur;
		if (0 == L_head->data) //初始化后0为空,亦或者 if(NULL==L_head->data)
		{
			printf("The list is empty\n");
		}
		else if (i == L_head->data)
		{//删除的节点是头节点
			L_head = pcur->pnext;
			free(pcur);
			pcur = NULL;
			if (0 == L_head->data)//if(NULL==L_tail)
			{//删除的节点是最后一个节点
				L_tail = NULL;
				L_head = NULL;
			}
		}
		else
		{//删除的节点是中间节点
			while (pcur)
			{
				if (i == pcur->data)
				{
					ppre->pnext = pcur->pnext;
					pcur->pnext->pprior = ppre;
					free(pcur);
					pcur = NULL;
					break;
				}
				ppre = pcur;
				pcur = pcur->pnext;
			}
			if (NULL == pcur)
			{//删除的节点是尾节点
				L_tail = ppre;
			}
		}
	}
	return *L_head;
}

查找

按位序查找和按值查找,代码如下:

int List_find(p_dlist L_head, p_dlist L_tail)
{//按位序查找
	int cnt = 0;
	int i;
	if (NULL == L_head)
	{
		fprintf(stderr, "error:The list is empty\n");
		return 0;
	}
	printf("Input the num you want to find:\n");
	scanf("%d", &i);
	while (L_head)
	{
		if (i == L_head->data)
		{
			break;
		}
		L_head = L_head->pnext;
		cnt++;
	}
	return cnt;
}
bool List_locate(p_dlist L_head)
{//按值查找
	int i;
	p_dlist pcur = L_head;
	if (NULL == L_head)
	{
		fprintf(stderr, "Error:The list is empty\n");
		return false;
	}
	printf("Input the num you want to find:\n");
	scanf("%d", &i);
	while (pcur)
	{
		if (i == pcur->data)
		{
			printf("The number you find is:%d\n", pcur->data);
			return true;
		}
		pcur = pcur->pnext;
	}
}

销毁

void List_Destory(p_dlist L_head)
{//带头结点的链表销毁
	while (L_head->pnext!=NULL)//遍历链表
	{
		if (NULL == L_head)
		{
			printf("The List is empty\n");
		}
		p_dlist pcur = L_head->pnext;
		if (NULL == pcur)
		{//链表只有一个节点的情况
			printf("The List doesn't has next node\n");
		}
		L_head->pnext = pcur->pnext;
		if (pcur->pnext != NULL)//pcur不是最后一个节点
		{//释放节点空间
			pcur->pnext->pprior = L_head;
		}
		free(pcur);
	}
	free(L_head);
	L_head = NULL;
}

本文思维导图大致如下:
思维导图
笔者个人能力有限,不足之处请给予指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值