热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

双向链表的基本操作C语言

双向链表的实现

本质: 其实就是定义两个指针域, 分别存放直接前驱结点的指针和直接后继结点的指针.

具体实现

定义一个双向链表

//定义一个双向链表
typedef struct LNode {
	int data;
	struct LNode* next;
	struct LNode* prior;
}LNode, *LinkList;

创建一个指定大小的双向链表

//创建一个指定大小的双向链表
void CreateList(LinkList* L, int n) {
	if (n < 1) {
		printf("输出有误\n");
		return;
	}
	printf("请输入 %d 个数据:", n);
	//创建头结点
	*L = (LinkList)malloc(sizeof(LNode));
	if (!(*L)) {
		exit(0);
	}
	LinkList rear = *L;
	LinkList p = NULL;
	for (int i = 0; i < n; ++i) {
		p = (LinkList)malloc(sizeof(LNode));
		if (!p) {
			exit(0);
		}
		scanf("%d", &p->data);
		rear->next = p;
		p->prior = rear;
		rear = p;
	}
	rear->next = NULL;
}

求链表的长度

//求链表的长度
int Length(LinkList L) {
	int len = 0;
	while (L->next != NULL) {
		++len;
		L = L->next;
	}
	return len;
}

双向链表的插入操作

//双向链表的插入操作
void Insert(LinkList* L, int pos, int e) {
	//判断插入的位置是否合理
	if (pos < 1 || pos > Length(*L) + 1) {
		printf("插入位置不合理\n");
		return;
	}
	LinkList adjust = *L;
	int i = 0;
	//只许循环 pos - 1 次
	while (i++ < pos - 1) {
		adjust = adjust->next;
	}
	LinkList p = (LinkList)malloc(sizeof(LNode));
	if (!p) {
		exit(0);
	}
	p->data = e;
	//连接
	p->next = adjust->next;
	adjust->next->prior = p;
	adjust->next = p;
	p->prior = adjust;
}

双向链表的删除操作:与插入操作类似, 在此不再赘述
双向链表的遍历

//双向链表的遍历
void Traverse(LinkList L) {
	while (L->next) {
		printf("%d ", L->next->data);
		L = L->next;
	}
	printf("\n");
}

双向链表的销毁

//双向链表的销毁
void Destroy(LinkList* L) {
	LinkList adjust = *L;
	while (*L) {
		adjust = adjust->next;
		free(*L);
		*L = adjust;
	}
}

双向链表的倒序遍历

void Reverse(LinkList L) {
	LinkList adjust = L;
	while (adjust->next) {
		adjust = adjust->next;
	}
	while (adjust != L) {
		printf("%d ", adjust->data);
		adjust = adjust->prior;
	}
	printf("\n");
}

测试

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
//定义一个双向链表
typedef struct LNode {
	int data;
	struct LNode* next;
	struct LNode* prior;
}LNode, *LinkList;
//创建一个指定大小的双向链表
void CreateList(LinkList* L, int n) {
	if (n < 1) {
		printf("输出有误\n");
		return;
	}
	printf("请输入 %d 个数据:", n);
	//创建头结点
	*L = (LinkList)malloc(sizeof(LNode));
	if (!(*L)) {
		exit(0);
	}
	LinkList rear = *L;
	LinkList p = NULL;
	for (int i = 0; i < n; ++i) {
		p = (LinkList)malloc(sizeof(LNode));
		if (!p) {
			exit(0);
		}
		scanf("%d", &p->data);
		rear->next = p;
		p->prior = rear;
		rear = p;
	}
	rear->next = NULL;
}
//求链表的长度
int Length(LinkList L) {
	int len = 0;
	while (L->next != NULL) {
		++len;
		L = L->next;
	}
	return len;
}
//双向链表的插入操作
void Insert(LinkList* L, int pos, int e) {
	//判断插入的位置是否合理
	if (pos < 1 || pos > Length(*L) + 1) {
		printf("插入位置不合理\n");
		return;
	}
	LinkList adjust = *L;
	int i = 0;
	//只许循环 pos - 1 次
	while (i++ < pos - 1) {
		adjust = adjust->next;
	}
	LinkList p = (LinkList)malloc(sizeof(LNode));
	if (!p) {
		exit(0);
	}
	p->data = e;
	//连接
	p->next = adjust->next;
	adjust->next->prior = p;
	adjust->next = p;
	p->prior = adjust;
}
//双向链表的遍历
void Traverse(LinkList L) {
	while (L->next) {
		printf("%d ", L->next->data);
		L = L->next;
	}
	printf("\n");
}
//双向链表的销毁
void Destroy(LinkList* L) {
	LinkList adjust = *L;
	while (*L) {
		adjust = adjust->next;
		free(*L);
		*L = adjust;
	}
}
void Reverse(LinkList L) {
	LinkList adjust = L;
	while (adjust->next) {
		adjust = adjust->next;
	}
	while (adjust != L) {
		printf("%d ", adjust->data);
		adjust = adjust->prior;
	}
	printf("\n");
}
int main() {
	LinkList L1;
	CreateList(&L1, 5);
	Reverse(L1);
	//Traverse(L1);
	//Insert(&L1, 3, 100);
	//Traverse(L1);
	Destroy(&L1);
	if (!L1) {
		printf("OK\n");
	}
	system("pause");
	return 0;
}

效果图
双向链表的基本操作-C语言

希望该文章能对大家有所帮助
同时真诚接受大家宝贵评论和建议


推荐阅读
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • 主板IO用W83627THG,用VC如何取得CPU温度,系统温度,CPU风扇转速,VBat的电压. ... [详细]
  • 本文介绍如何利用栈数据结构在C++中判断字符串中的括号是否匹配。通过顺序栈和链栈两种方式实现,并详细解释了算法的核心思想和具体实现步骤。 ... [详细]
  • 本文详细介绍了在不同操作系统中查找和设置网卡的方法,涵盖了Windows系统的具体步骤,并提供了关于网卡位置、无线网络设置及常见问题的解答。 ... [详细]
  • 使用Nginx反向代理实现多域名端口映射
    本文介绍如何通过配置本地hosts文件和Nginx反向代理,实现多个虚拟域名的端口映射,使用户可以通过标准HTTP端口80访问不同后端服务。 ... [详细]
  • 历经三十年的开发,Mathematica 已成为技术计算领域的标杆,为全球的技术创新者、教育工作者、学生及其他用户提供了一个领先的计算平台。最新版本 Mathematica 12.3.1 增加了多项核心语言、数学计算、可视化和图形处理的新功能。 ... [详细]
  • 本文详细探讨了如何通过分析单个或多个线程在瓶颈情况下的表现,来了解处理器资源的消耗。无论是单进程还是多进程环境,监控关键指标如线程数量、占用时间及调度优先级等,有助于揭示潜在的性能问题。 ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
  • 本文详细介绍了C语言中的基本数据类型,包括整型、浮点型、字符型及其各自的子类型,并探讨了这些类型在不同编译环境下的表现。 ... [详细]
  • HDU 2871 内存管理问题(线段树优化)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871。本题涉及内存管理操作,包括重置、申请、释放和查询内存块。通过使用线段树进行高效管理和维护。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • 本文深入探讨了 Delphi 中类对象成员的核心概念,包括 System 单元的基础知识、TObject 类的定义及其方法、TClass 的作用以及对象的消息处理机制。文章不仅解释了这些概念的基本原理,还提供了丰富的补充和专业解答,帮助读者全面理解 Delphi 的面向对象编程。 ... [详细]
  • 深入浅出TensorFlow数据读写机制
    本文详细介绍TensorFlow中的数据读写操作,包括TFRecord文件的创建与读取,以及数据集(dataset)的相关概念和使用方法。 ... [详细]
author-avatar
欧拉阿拉
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有