双向链表的基本操作

1.双向链表的定义


单向链表特点
  1.我们可以轻松的到达下一个节点, 但是回到前一个节点是很难的.
  2.只能从头遍历到尾或者从尾遍历到头(一般从头到尾)
双向链表特点
  1.每次在插入或删除某个节点时, 需要处理四个节点的引用, 而不是两个. 实现起来要困难一些
  2.相对于单向链表, 必然占用内存空间更大一些.
  3.既可以从头遍历到尾, 又可以从尾遍历到头
双向链表的定义:
  双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。下图为双向链表的结构图。

在这里插入图片描述

  从上中可以看到,双向链表中各节点包含以下 3 部分信息:
  指针域:用于指向当前节点的直接前驱节点;
  数据域:用于存储数据元素。
  指针域:用于指向当前节点的直接后继节点;

 在这里插入图片描述

双向循环链表的定义:
  双向链表也可以进行首尾连接,构成双向循环链表,如下图所示
在创建链表时,只需要在最后将收尾相连即可(创建链表代码中已经标出)。其他代码稍加改动即可。

在这里插入图片描述

 2.双向链表的实现以及基本操作

   1.双向链表的结构体定义

   2.双向链表的初始化

   3.双向链表之创建新结点

   4.双向链表的打印

   5.双向链表的尾插

   6.双向链表的尾删

   7.双向链表的头插

   8.双向链表的头删

   9.双向链表的查找

   10.双向链表之在ptr位置之前插入

   11.双向链表之删除ptr位置

   12.双向链表的销毁

//双链表

#include<stdio.h>     //scanf
#include<stdlib.h>    //malloc
#include<assert.h>
//malloc时动态内存分配函数,用于申请一块连续的指定大小的
//内存块区域以void*类型返回分配的内存区域地址



//typedef为一种数据类型定义一个新名字,这里的数据类型包括内部数据类型
//(int,char等)和自定义的数据类型struct
typedef  int ElemType;
typedef struct DuNode  //双
{
	struct DuNode* prev;    //前驱
	struct DuNode* next;     //后继
	ElemType data;           //数据
}DuNode, * PDuNode;     //结点类型  指针类型

typedef struct
{
	PDuNode head;   //指向头节点
	int cursize;    //整个链表里面的数据结点的个数
}DuLinkList;  //双循环链表结构


DuNode* Buynode(DuNode* parg = nullptr, DuNode* narg = nullptr)   //购买一个结点 parg代表前驱  narg代表后继
{
	DuNode* s = (DuNode*)malloc(sizeof(DuNode*));
	if (nullptr == s) exit(1);  // .c NULL
	s->prev = parg == nullptr ? s : parg;
	s->next = narg == nullptr ? s : narg;
	return s;
}

void InitList(DuLinkList* plist)
{
	assert(plist != nullptr);
	plist->cursize = 0;
	plist->head = Buynode();
}

void Insert(DuLinkList* plist, DuNode* ptr, ElemType val)         //购买一个结点S 在PTR之前插入一个结点s
{
	assert(plist != nullptr && ptr != nullptr);
	ptr->prev = Buynode(ptr->prev, ptr);
	DuNode* s = ptr->prev;
	s->prev->next = s;
	s->data = val;
	plist->cursize += 1;
#if 0
	DuNode* s = Buynode();
	s->data = val;
	s->next = ptr;       //s的next指向ptr                           1
	s->prev = ptr->prev;      //s的prev指向12(原ptr的prev 23的prev)          2
	ptr->prev = s;         // ptr的prev指向s               3
	s->prev->next = s;                                    //              4
	plist->cursize++;
#endif
}

void Push_Front(DuLinkList* plist, ElemType val)
{
	assert(plist != nullptr);
	Insert(plist,plist->head->next, val);
}
void Push_Back(DuLinkList* plist, ElemType val)
{
	assert(plist!= nullptr);
	Insert(plist, plist->head, val);
}

void Earse(DuLinkList* plist, DuNode* ptr) {     //删除指定结点     ptr
	assert(plist != nullptr && ptr != nullptr);
	ptr->next->prev = ptr->prev;
	ptr->prev->next = ptr->next;      
	free(ptr);
	plist->cursize -= 1;
}

void Pop_Front(DuLinkList* plist)           
{
	assert(plist != nullptr);
	Earse(plist, plist->head->next);//删掉第一个数据结点 plist->head->next
}
void Pop_Back(DuLinkList* plist)           //尾删
{
	assert(plist != nullptr);
	Earse(plist, plist->head->prev);
}

int GetSize(DuLinkList* plist)        //获取链表的结点个数
{
	assert(plist != nullptr);
	return plist->cursize;
}

bool IsEmpty(DuLinkList* plist)      //判空操作
{
	assert(plist != nullptr);
	return GetSize(plist) == 0;
}

void Clear(DuLinkList* plist) {
	while (plist != nullptr) {
		Earse(plist, plist->head->next);
		free(plist->head->next);
	}
}

void DestoryList(DuLinkList* plist)
{
	assert(plist != nullptr);
	Clear(plist);
	free(plist->head);
	plist->head = nullptr;
}


void Print(DuLinkList* plist)   //打印链表
{
	assert(plist != nullptr);
	DuNode* p = plist->head->next;
	while (p != plist->head)
	{
		printf("%d", p->data);
		p = p->next;
	}
	printf("/n");
}

DuNode* FindValue(DuLinkList* plist, ElemType val) //找value
{
	assert(plist != nullptr);
	DuNode* p = plist->head->next;
	while (p != plist->head && p->data != val);
	{
		p = p->next;

	}
	if (p == plist->head)
	{
		p = nullptr;
	}
	return p;
}

int main() 
{
	DuLinkList mylist;
	InitList(&mylist);   //初始化
	for (int i = 0; i < 10; ++i)
	{
		Push_Back(&mylist, i);
		Print(&mylist);
	}
	while (!IsEmpty(&mylist))
	{
		Pop_Back(&mylist);
		Print(&mylist);
	}
	return 0;
}

注:

1).insert插入 

2)删除指定结点

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值