数据结构(C语言版)代码实现(五)——双向循环链表的部分实现

目录

参考材料与格式

线性表的有关知识

头文件

库、宏定义、数据类型声明

线性表的双向链表存储结构

构造空链表

销毁链表

链表长度

按位查找

插入元素

删除元素

打印链表

完整头文件DuLinkList.h

测试函数(主函数)

测试结果

收获


参考材料与格式

参考材料:数据结构(C语言版)严蔚敏 吴伟民编著。

线性表的有关知识

预习到这里,有点感觉概念有点多,线性表,顺序表,链表,单链表,双向链表,静态链表,动态链表,循环链表......有的链表只有头指针,有的链表头指针尾指针都有,有的只有尾指针,那么怎么区分这些概念呢?从头说起。

线性表是数据结构,数据结构是相互之间一种或多种特定关系的数据元素的集合。顺序表与链表都是物理结构,又称存储结构,存储结构包括数据元素的表示和关系的表示。存储结构是数据结构在计算机中的表示,举个例子,可以说,单链表是线性表在计算机中表示的一种方式。所以,2.2节的标题是线性表的顺序表示与实现,意思是,这一节讲用顺序表表示线性表(线性表的顺序表示),用类C代码实现顺序表。

这些概念有一个特点,都是成对出现。如顺序表与链表、单链表与双向链表、静态链表与动态链表、循环链表与非循环链表......这些概念每一对都有且只有一个,如本节实现的存储结构为双向 循环 动态 链表,只有头指针。

为什么说这么多呢?因为课本中虽然单独介绍循环链表(35页2.3.2节),但后面没跟上代码,我一想,静态链表也可以循环,单链表、双向链表也可以循环,所以还是先弄清楚概念,再怎么写文章也不迟。

头文件

库、宏定义、数据类型声明

#include <cstdio>
#include <cstdlib>
#include <cstring>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;//Status是函数的类型,其值是函数结果状态代码
typedef int ElemType;

线性表的双向链表存储结构

//-----线性表的双向链表存储结构-----
typedef struct DuLNode {
	ElemType data;
	struct DuLNode* prior;
	struct DuLNode* next;
}DuLNode,*DuLinkList;

构造空链表

Status InitList_DuL(DuLinkList& L) {
	//构造一个空的线性链表L
	L = (DuLinkList)malloc(sizeof(DuLNode));
	L->prior = L->next = L;
	return OK;
}

销毁链表

Status DestroyList_DuL(DuLinkList& L) {
	//销毁线性链表L,L不再存在
	DuLinkList p = L;
	while (L->next != L) {
		L->next->prior = L->prior;
		L->prior->next = L->next;
		L = L->next;
		free(p);
		p = L;
	}
	free(L);
	return OK;
}

链表长度

int ListLength_DuL(DuLinkList L) {//求链表长度
	DuLinkList p = L->next;
	int count = 0;
	while (p != L)
	{
		p = p->next;
		count++;
	}
	return count;
}//一定要在GetElem_DuL函数前面

代码写完调试时,报错,找不到标识符,下面是解决文章。

如何解决VC2019中:error C3861: “xxxx”: 找不到标识符_error c3861 pow 找不到标识符-CSDN博客

简单总结,因为我的GetElem_DuL函数调用了这个求链表长度的函数,如果Get这个函数在前面的话,Get函数内部的求链表长度函数没有定义,出现C3861问题。解决方法有二,一是像注释中写的将求链表长度的函数放在前面,二是将求链表长度的函数写函数声明。

按位查找

DuLinkList GetElem_DuL(DuLinkList L, int i) {
	//L为带头结点的单链表的头指针。
	//按位查找
	DuLinkList p = L;
	if (i >= 1 && i <= ListLength_DuL(L) + 1) {
		int m = i;
		while (m--) {
			p = p->next;
		}
	}
	else
		p = NULL;
	return p;
}

插入元素

//算法2.18 插入元素
Status ListInsert_DuL(DuLinkList& L, int i, ElemType e) {
	//在带头结点的双链循环线性表L中第i个位置之前插入元素e,即在p前面插入结点
	//i的合法值为1<=i<=表长+1。
	DuLinkList p, s;//曾试过变量p,s一边声明一边赋值,结果报错,不知道为什么。
	if (!(p = GetElem_DuL(L, i)))//在L中确定插入位置指针p
		return ERROR;//i等于表长加1时,p指向头结点;i大于表长加1时,p=NULL。
	if (!(s = (DuLinkList)malloc(sizeof(DuLNode))))
		return ERROR;
	s->data = e;
	s->prior = p->prior;p->prior->next = s;
	s->next = p;p->prior = s;
	return OK;
}

删除元素

//算法2.19 删除元素
Status ListDelete_DuL(DuLinkList& L, int i, ElemType& e) {
	//删除带头结点的双链循环线性表L的第i个元素,i的合法值为1<=i<=表长
	DuLinkList p;
	if (!(p = GetElem_DuL(L, i)))//在L中确定第i个元素的位置指针p
		return ERROR;//p=NULL,即第i个元素不存在
	e = p->data;
	p->prior->next = p->next;
	p->next->prior = p->prior;
	free(p);
	return OK;
}

打印链表

void PrintList_DuL(DuLinkList L) {//打印链表
	DuLinkList p = L->next;
	while (p != L) {//注意与单链表的有区别,单链表是p!=NULL
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

完整头文件DuLinkList.h

#pragma once
#include <cstdio>
#include <cstdlib>
#include <cstring>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;//Status是函数的类型,其值是函数结果状态代码
typedef int ElemType;

//-----线性表的双向链表存储结构-----
typedef struct DuLNode {
	ElemType data;
	struct DuLNode* prior;
	struct DuLNode* next;
}DuLNode,*DuLinkList;

Status InitList_DuL(DuLinkList& L) {
	//构造一个空的线性链表L
	L = (DuLinkList)malloc(sizeof(DuLNode));
	L->prior = L->next = L;
	return OK;
}

Status DestroyList_DuL(DuLinkList& L) {
	//销毁线性链表L,L不再存在
	DuLinkList p = L;
	while (L->next != L) {
		L->next->prior = L->prior;
		L->prior->next = L->next;
		L = L->next;
		free(p);
		p = L;
	}
	free(L);
	return OK;
}

int ListLength_DuL(DuLinkList L) {//求链表长度
	DuLinkList p = L->next;
	int count = 0;
	while (p != L)
	{
		p = p->next;
		count++;
	}
	return count;
}//一定要在GetElem_DuL函数前面

DuLinkList GetElem_DuL(DuLinkList L, int i) {
	//L为带头结点的单链表的头指针。
	//按位查找
	DuLinkList p = L;
	if (i >= 1 && i <= ListLength_DuL(L) + 1) {
		int m = i;
		while (m--) {
			p = p->next;
		}
	}
	else
		p = NULL;
	return p;
}

//算法2.18 插入元素
Status ListInsert_DuL(DuLinkList& L, int i, ElemType e) {
	//在带头结点的双链循环线性表L中第i个位置之前插入元素e,即在p前面插入结点
	//i的合法值为1<=i<=表长+1。
	DuLinkList p, s;//曾试过变量p,s一边声明一边赋值,结果报错,不知道为什么。
	if (!(p = GetElem_DuL(L, i)))//在L中确定插入位置指针p
		return ERROR;//i等于表长加1时,p指向头结点;i大于表长加1时,p=NULL。
	if (!(s = (DuLinkList)malloc(sizeof(DuLNode))))
		return ERROR;
	s->data = e;
	s->prior = p->prior;p->prior->next = s;
	s->next = p;p->prior = s;
	return OK;
}

//算法2.19 删除元素
Status ListDelete_DuL(DuLinkList& L, int i, ElemType& e) {
	//删除带头结点的双链循环线性表L的第i个元素,i的合法值为1<=i<=表长
	DuLinkList p;
	if (!(p = GetElem_DuL(L, i)))//在L中确定第i个元素的位置指针p
		return ERROR;//p=NULL,即第i个元素不存在
	e = p->data;
	p->prior->next = p->next;
	p->next->prior = p->prior;
	free(p);
	return OK;
}

void PrintList_DuL(DuLinkList L) {//打印链表
	DuLinkList p = L->next;
	while (p != L) {//注意与单链表的有区别,单链表是p!=NULL
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

测试函数(主函数)

#include "DuLinkList.h"

int main()
{
	DuLinkList L;
	Status i;
	ElemType e;
	i = InitList_DuL(L);
	if (!i)
		printf("构造成功!\n");
	else
		printf("构造失败!\n");
	i = ListInsert_DuL(L, 0, 13);
	if (!i)
		printf("插入失败。\n");
	else
		printf("插入的元素为13。\n");
	for (int j = 5;j <= 10;j++) {
		i = ListInsert_DuL(L, 1, j);
		if (!i)
			printf("插入失败。\n");
		else
			printf("插入的元素为%d。\n",j);
	}
	i = ListInsert_DuL(L, 7, 13);
	if (!i)
		printf("插入失败。\n");
	else
		printf("插入的元素为13。\n");
	i = ListInsert_DuL(L, 9, 13);
	if (!i)
		printf("插入失败。\n");
	else
		printf("插入的元素为13。\n");
	PrintList_DuL(L);
	i = ListDelete_DuL(L, 7, e);
	if (!i)
		printf("删除失败\n");
	else
		printf("删除的元素为%d。\n", e);
	i = ListDelete_DuL(L, 3, e);
	if (!i)
		printf("删除失败\n");
	else
		printf("删除的元素为%d。\n", e);
	PrintList_DuL(L);
	DestroyList_DuL(L);
	return 0;
}

测试结果

收获

1、弄清了本章一些概念的联系。

2、解决了找不到标识符的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/355009.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电磁兼容(EMC):产品如何做到可靠的防静电设计

工业产品所应用的电磁环境之恶劣。要想产品在如此恶劣的电磁环境下正常工作&#xff0c;需要具备强大的抗干扰能力方能胜任。其中以静电干扰最为常见且棘手。本文将手把手教你如何将工业产品做到可靠的防静电设计。 1 了解静电 你想要打倒对手&#xff0c;必须先深入地了解他…

Redis 学习笔记 2:Java 客户端

Redis 学习笔记 2&#xff1a;Java 客户端 常见的 Redis Java 客户端有三种&#xff1a; Jedis&#xff0c;优点是API 风格与 Redis 命令命名保持一致&#xff0c;容易上手&#xff0c;缺点是连接实例是线程不安全的&#xff0c;多线程场景需要用线程池来管理连接。Redisson&…

预训练语言模型transformer

预训练语言模型的学习方法有三类&#xff1a;自编码&#xff08;auto-encode, AE)、自回归&#xff08;auto regressive, AR&#xff09;&#xff0c;Encoder-Decoder结构。 决定PTM模型表现的真正原因主要有以下几点&#xff1a; 更高质量、更多数量的预训练数据增加模型容量…

双非本科准备秋招(8.2)——JVM1

第一天系统学习JVM&#xff01;今天学了JVM是什么&#xff0c;学习JVM的作用&#xff0c;运行时的数据区域&#xff08;重点&#xff09;&#xff0c;内存溢出。明天学GC。 运行时数据区域 整体认识 JDK1.7 JDK1.8 先写一下每个线程私有的三个数据区&#xff0c;分别是程序计…

Docker—入门及Centos7安装

1、Docker入门 1.1、Docker是什么&#xff1f; Docker是基于Go语言实现的云开源项目。 Docker的主要目标是“Build&#xff0c;Ship&#xff0c;and Run Any App,Anywhere”&#xff0c;也就是通过对应组件的封装、分发、部署、运行等生命周期的管理&#xff0c;使用户的APP&…

模板笔记 ST表 区间选数k

本题链接&#xff1a;用户登录 题目&#xff1a; 样例&#xff1a; 输入 5 3 1 1 2 2 3 1 2 3 3 1 5 输出 4 6 思路&#xff1a; . 根据题意&#xff0c;给出数组&#xff0c;以及多个区间&#xff0c;问这些区间中&#xff0c;最小值之和 和 最大值之和&#xff0c;…

CHS_02.2.3.2_1+进程互斥的软件实现方法

CHS_02.2.3.2_1进程互斥的软件实现方法 知识总览如果没有注意进程互斥&#xff1f;单标志法双标志先检查法双标志后检查法Peterson 算法 知识回顾 在这个小节中 我们会学习进程互斥的几种软件实现方法 知识总览 那我们会学习单标志法 双标志 先检查 双标志后检查和Peterson算法…

前端工程化基础(三):Webpack基础

Webpack和打包过程 学习webpack主要是为了了解目前前端开发的整体流程&#xff0c;实际开发中&#xff0c;我们并不需要去手动配置&#xff0c;因为框架的脚手架都已经帮助我们完成了配置 内置模块path 该模块在Webpack中会经常使用 从路径中获取信息 const path require(&qu…

前端Vue v-for 的使用

目录 ​编辑 简介 使用方式 基本使用 v-for"(item, index)中item和index作用 示例 迭代对象 示例 结果 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入…

【Linux】第三十八站:信号处理

文章目录 一、信号处理二、再谈进程地址空间三、内核如何实现信号的捕捉四、sigaction 一、信号处理 我们知道&#xff0c;信号保存以后&#xff0c;会在合适的时候进行处理这个信号。 那么信号是如何被处理的&#xff1f;什么时候进行处理呢&#xff1f; 当我们的进程从内核…

精通Python第13篇—数据之光:Pyecharts旭日图的魔法舞台

文章目录 引言准备工作绘制基本旭日图调整颜色和样式添加交互功能定制标签和标签格式嵌套层级数据高级样式与自定义进阶主题&#xff1a;动态旭日图数据源扩展&#xff1a;外部JSON文件总结 引言 数据可视化在现代编程中扮演着重要的角色&#xff0c;而Pyecharts是Python中一个…

【深度学习每日小知识】Bias 偏差

计算机视觉是人工智能的一个分支&#xff0c;它使机器能够解释和分析视觉信息。然而&#xff0c;与任何人造技术一样&#xff0c;计算机视觉系统很容易受到训练数据产生的偏差的影响。计算机视觉中的偏见可能会导致不公平和歧视性的结果&#xff0c;从而使社会不平等长期存在。…

Python进阶(1) | 使用VScode写单元测试

Python进阶(1) | 单元测试 2024.01.28 VSCode: 1.85.1 Linux(ubuntu 22.04) 文章目录 Python进阶(1) | 单元测试1. 目的2. Python Profile3. 单元测试框架3.1 什么是单元测试3.2 选一个单元测试框架3.3 编写 Python 单元测试代码3.4 在 VSCode 里发现单元测试3.5 再写一个单元…

问题:github上不了,但是其他网页可以正常打开

问题&#xff1a; github上不了&#xff0c;但是其他网页可以正常打开&#xff0c;试了关闭防火墙&#xff0c;dns刷新&#xff0c;都没用后&#xff0c;参考以下文章成功打开Github 1.Github无法访问解决方法 2.github访问不了&#xff1f;详细解决方法 解决办法&#xff1a…

用Python编写的简单双人对战五子棋游戏

本文是使用python创建的一个基于tkinter库的GUI界面&#xff0c;用于实现五子棋游戏。编辑器使用的是spyder&#xff0c;该工具。既方便做数据分析&#xff0c;又可以做小工具开发&#xff0c; 首先&#xff0c;导入tkinter库&#xff1a;import tkinter as tk&#xff0c;这…

leetcode刷题日志-146LRU缓存

思路&#xff1a;使用hashmap储存key&#xff0c;vaule&#xff0c;使用双向链表以快速查到尾结点&#xff08;待逐出的节点&#xff09;&#xff0c;链表的题一定要在纸上画一下&#xff0c;不然连着连着就不知道连在哪里去了 class LRUCache {public class ListNode {int ke…

Java基础常见面试题总结(下)

常见的Exception有哪些&#xff1f; 常见的RuntimeException&#xff1a; ClassCastException //类型转换异常IndexOutOfBoundsException //数组越界异常NullPointerException //空指针ArrayStoreException //数组存储异常NumberFormatException //数字格式化异常ArithmeticE…

【Mac】windows PC用户转用Mac 配置笔记

win转mac使用的一些配置笔记&#xff1b;感觉mac在UI上还是略胜一筹&#xff0c;再配合在win上的操作习惯就体验更好了&#xff0c;对日常办公需求的本人足以。 优化设置 主要 操作优化 AltTab&#xff1a; win 习惯查看全部活动的alt键&#xff0c;对比cmdtab多了可以预览&…

前端——JavaScript

目录 文章目录 前言 一. JavaScript基础 1.JavaScript基本结构 2. JavaScript 执行过程 3. JavaScript 引入方式 二. JavaScript 语法 1.数据类型 2.变量 2.1 var 关键字定义变量 2.2 let 关键字定义变量 2.3 var 与 let 的区别 3.字符串 3.1定义字符串 3.2 字…

Px4学习:进入控制台的方法

运行命令 ls /dev/tty* 会列出所有端口 然后连接飞控通过USB数据线连接到电脑&#xff0c;再运行一次&#xff0c;就可以找到 笔者的是ttyACM0&#xff0c;下面会用到 px4源码 1.13.3 进入控制台 进入PX4源码文件夹&#xff0c;用终端打开&#xff0c;运行命令 ./Tools/mav…
最新文章