【数据结构】双链表(定义 创建 插入 删除 销毁 查找)完整代码

3.2 双链表

3.2.1 定义
  • 作用

方便找上一个结点。

typedef struct DNode {
	ElemType data;
	struct DNode* prior, * next;//指向上一个和下一个的结点
}DNode,*DLinklist;
//DNode强调是结点,*DLinklist强调是链表

//初始化双链表
bool InitDLinkList(DLinklist& L) {
	L = (DNode*)malloc(sizeof(DNode));//分配一个头结点
	if (L == NULL)return false;
	L->prior = NULL;//头结点的prior永远指向null
	L->next = NULL;
	return true;
}
3.2.2 插入
  • 步骤

    1.插入节点的next指向后继节点;

    2.后继节点的prior指向插入节点;

    3.插入节点的prior指向前驱节点;

    4.前驱节点的next指向插入节点。

//p后插s
bool InsertNextDNode(DLinklist& L, int i, ElemType e) {
	if (i < 1)return false;

	DNode* p;//指针指向当前扫描到的节点
	int j = 0;//当前p指向的是第几个节点
	//查找第i个位置
	p = L;//L指向头节点,头节点是第0个节点
	while (p != NULL && j < i )
	{
		p = p->next;
		j++;
	}

	//非法参数
	if (p == NULL)return false;

	DNode* s = (DNode*)malloc(sizeof(DNode));
	s->data = e;
	s->next = p->next;//指向后继节点
	if (p->next != NULL)//如果插入位置不是链表末尾
	{
		p->next->prior = s;//后继节点指向插入节点
	}
	s->prior = p;//插入节点指向前驱节点
	p->next = s;//前驱节点指向插入节点
	return true;
}

//p前插s
//找到待插入位置的前驱节点,再进行后插
bool InsertPriorDNode(DLinklist& L, int i, ElemType e) {
	if (i < 1)return false;

	DNode* p;//指针指向当前扫描到的节点
	int j = 0;//当前p指向的是第几个节点
	//查找第i个位置
	p = L;//L指向头节点,头节点是第0个节点
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}

	//非法参数
	if (p == NULL)return false;

	DNode* s = (DNode*)malloc(sizeof(DNode));
	s->data = e;
	s->next = p->next;//指向后继节点
	if (p->next != NULL)//如果插入位置不是链表末尾
	{
		p->next->prior = s;//后继节点指向插入节点
	}
	s->prior = p;//插入节点指向前驱节点
	p->next = s;//前驱节点指向插入节点
	return true;
}
3.2.3 删除
  • 步骤

    1.前驱节点的next指向后驱节点;

    2.后继节点的prior指向前驱节点;

    3.释放要删除的节点。

bool ListDelete(DLinklist& L, int i, ElemType& e)
{
	if (i < 1)return false;

	DNode* p;//指针p指向当前扫描到的结点
	int j = 0;//当前p指向的是第几个结点

	//循环找到第i-1个结点
	p = L;//指向头结点
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	//i值不合法
	if (p == NULL || p->next == NULL)return false;

	DNode* q = p->next;//令q指向被删除结点
	e = q->data;//用e返回元素的值
	p->next = q->next;//将*q结点从链中断开
	if (q->next != NULL)//q不是最后一个
	{
		q->next->prior = p;
	}
	free(q);//释放结点存储空间
	return true;
}
3.2.4 销毁

相当于循环删除每个节点。

void DestoryList(DLinklist& L)
{
	//循环释放各节点
	DNode* p = L->next;
	while (p != NULL)
	{
		DNode* q = p->next;
		if (q != NULL)
		{
			p->next = q->next;
			if (q->next != NULL)
			{
				q->next->prior = p;
			}
			free(q);
		}
		p = p->next;
	}
	free(L);//释放头结点
	L = NULL;
}
3.2.5 查找

同单链表查找

时间复杂度:O(n)

* 双链表完整代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define ElemType int

//----------------定义-----------------
typedef struct DNode {
	ElemType data;
	struct DNode* prior, * next;//指向上一个和下一个的结点
}DNode,*DLinklist;
//DNode强调是结点,*DLinklist强调是链表
//*DNode等价于DLinklist

//初始化双链表
bool InitDLinkList(DLinklist& L) {
	L = (DNode*)malloc(sizeof(DNode));//分配一个头结点
	if (L == NULL)return false;
	L->prior = NULL;//头结点的prior永远指向null
	L->next = NULL;
	return true;
}


//---------------建立单链表---------------

//头插法建立单链表
DLinklist List_HeadInsert(DLinklist& L)
{
	int m;
	printf("\n1.手动输入\n2.自动生成\n");
	scanf_s("%d", &m);

	if (m == 1)
	{
		DNode* s;
		int x;
		scanf_s("%d", &x);//输入结点值
		//插入表中
		while (x != 9999)//9999表示结束
		{
			//创建新结点
			s = (DNode*)malloc(sizeof(DNode));
			s->data = x;
			s->next = L->next;//新结点指针域指向原来的第一个结点
			s->prior = L;
			//头结点指向新结点
			L->next = s;
			scanf_s("%d", &x);
		}
		return L;
	}
	else if (m == 2)
	{
		DNode* s;
		int n = 10;//结点个数
		srand(time(0));//初始化随机数种子
		while (n--)
		{
			//创建新结点
			s = (DNode*)malloc(sizeof(DNode));
			s->data = rand() % 100 + 1;//随机产生100以内的数
			s->next = L->next;
			L->next = s;
		}
	}
	else
	{
		printf("请重新输入!\n");
		List_HeadInsert(L);
	}

}

//尾插法建立链表
DLinklist List_TailInsert(DLinklist& L)
{
	int m;
	printf("\n1.手动输入\n2.自动生成\n");
	scanf_s("%d", &m);

	if (m == 1)
	{
		DNode* s, * r = L;//r为表尾指针
		int x;
		scanf_s("%d", &x);//输入结点值
		//插入表中
		while (x != 9999)//9999表示结束
		{
			//创建新结点
			s = (DNode*)malloc(sizeof(DNode));
			s->data = x;
			s->prior = r;
			//表尾指针指向新结点
			r->next = s;
			//更新表尾结点
			r = s;
			scanf_s("%d", &x);
		}
		r->next = NULL;//尾结点指针置空
		return L;
	}
	else if (m == 2)
	{
		DNode* s, * r = L;
		int n = 10;//结点个数
		srand(time(0));//初始化随机数种子
		while (n--)
		{
			//创建新结点
			s = (DNode*)malloc(sizeof(DNode));
			s->data = rand() % 100 + 1;//随机产生100以内的数
			r->next = s;
			r = s;
		}
		r->next = NULL;
		return L;
	}
	else
	{
		printf("请重新输入!\n");
		List_TailInsert(L);
	}
}


//-------------------插入操作-----------------------
//p后插s
bool InsertNextDNode(DLinklist& L, int i, ElemType e) {
	if (i < 1)return false;

	DNode* p;//指针指向当前扫描到的节点
	int j = 0;//当前p指向的是第几个节点
	//查找第i个位置
	p = L;//L指向头节点,头节点是第0个节点
	while (p != NULL && j < i )
	{
		p = p->next;
		j++;
	}

	//非法参数
	if (p == NULL)return false;

	DNode* s = (DNode*)malloc(sizeof(DNode));
	s->data = e;
	s->next = p->next;//指向后继节点
	if (p->next != NULL)//如果插入位置不是链表末尾
	{
		p->next->prior = s;//后继节点指向插入节点
	}
	s->prior = p;//插入节点指向前驱节点
	p->next = s;//前驱节点指向插入节点
	return true;
}

//p前插s
//找到待插入位置的前驱节点,再进行后插
bool InsertPriorDNode(DLinklist& L, int i, ElemType e) {
	if (i < 1)return false;

	DNode* p;//指针指向当前扫描到的节点
	int j = 0;//当前p指向的是第几个节点
	//查找第i个位置
	p = L;//L指向头节点,头节点是第0个节点
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}

	//非法参数
	if (p == NULL)return false;

	DNode* s = (DNode*)malloc(sizeof(DNode));
	s->data = e;
	s->next = p->next;//指向后继节点
	if (p->next != NULL)//如果插入位置不是链表末尾
	{
		p->next->prior = s;//后继节点指向插入节点
	}
	s->prior = p;//插入节点指向前驱节点
	p->next = s;//前驱节点指向插入节点
	return true;
}


//-----------------删除------------------
bool ListDelete(DLinklist& L, int i, ElemType& e)
{
	if (i < 1)return false;

	DNode* p;//指针p指向当前扫描到的结点
	int j = 0;//当前p指向的是第几个结点

	//循环找到第i-1个结点
	p = L;//指向头结点
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	//i值不合法
	if (p == NULL || p->next == NULL)return false;

	DNode* q = p->next;//令q指向被删除结点
	e = q->data;//用e返回元素的值
	p->next = q->next;//将*q结点从链中断开
	if (q->next != NULL)//q不是最后一个
	{
		q->next->prior = p;
	}
	free(q);//释放结点存储空间
	return true;
}


//-----------------销毁------------------
void DestoryList(DLinklist& L)
{
	//循环释放各节点
	DNode* p = L->next;
	while (p != NULL)
	{
		DNode* q = p->next;
		if (q != NULL)
		{
			p->next = q->next;
			if (q->next != NULL)
			{
				q->next->prior = p;
			}
			free(q);
		}
		p = p->next;
	}
	free(L);//释放头结点
	L = NULL;
}


//---------------查找----------------
//按序号查找结点
DNode* GetElem(DLinklist L, int i)
{
	if (i < 1)return NULL;
	int j = 1;
	DNode* p = L->next;//第1个结点指针赋给p
	while (p != NULL && j < i)
	{
		p = p->next;
		j++;
	}
	return p;
}

//按值查找
DNode* LocateElem(DLinklist L, ElemType e)
{
	DNode* p = L->next;
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	if (p != NULL)
	{
		printf("Success!\n");
	}
	else
	{
		printf("没有这个值!\n");
	}
	return p;
}


void Menu()
{
	printf("\n----------菜单----------\n");
	printf("1.头插法创建\n2.尾插法创建\n");
	printf("3.后插\n4.前插\n");
	printf("5.删除节点\n6.销毁双链表\n");
	printf("7.按序号查找\n8.按值查找\n");
}

void Listprint(DLinklist& L)
{
	if (L == NULL)
	{
		printf("链表为空!\n");
		return;
	}
	DLinklist t = L->next;
	while (t->next != NULL)
	{
		printf("%d ", t->data);
		t = t->next;
	}
	printf("%d\n", t->data);
}


int main()
{
	DLinklist L;
	InitDLinkList(L);

	int x;
	Menu();
	while (~scanf_s("%d", &x)) {
		if (x == 1)
		{
			List_HeadInsert(L);
			Listprint(L);
		}
		else if (x == 2)
		{
			List_TailInsert(L);
			Listprint(L);
		}
		else if (x == 3)
		{
			int pos;
			ElemType data;
			printf("请输入要插入的位置和值:\n");
			scanf_s("%d %d", &pos,& data);
			InsertNextDNode(L, pos,data);
			Listprint(L);
		}
		else if (x == 4)
		{
			int pos;
			ElemType data;
			printf("请输入要插入的位置和值:\n");
			scanf_s("%d %d", &pos, &data);
			InsertPriorDNode(L, pos, data);
			Listprint(L);
		}
		else if (x == 5)
		{
			int pos;
			ElemType x;
			printf("请输入要删除的位置:\n");
			scanf_s("%d", &pos);
			ListDelete(L, pos, x);
			printf("已删除元素:%d\n", x);
			Listprint(L);
		}
		else if (x == 6)
		{
			DestoryList(L);
			printf("Success!\n");
			Listprint(L);
		}
		else if (x == 7)
		{
			DNode* p;
			int n;
			printf("请输入需要查找的序号:\n");
			scanf_s("%d", &n);
			p = GetElem(L, n);
			printf("查找结点的值:%d", p->data);
		}
		else if (x == 8)
		{
			DNode* p;
			int n;
			printf("请输入需要查找的结点值:\n");
			scanf_s("%d", &n);
			p = LocateElem(L, n);
		}

		Menu();
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值