数据结构--双链表,循环链表,静态链表代码(王道书上代码手敲!!!)c++

news2024/11/16 5:58:10

目录

1.带头结点的双链表的初始化,判断链表是否为空,前插,后插,按位序插,删除后继节点,按位查找,按之查找,清空链表,销毁链表,遍历打印列表操作

2. 循环单链表初始化,判空,判断是否为尾节点

3.循环双链表初始化,判空,判断是否为尾节点,插入,删除后继元素,打印链表内容操作

4.静态链表的初始化,查找空节点,按位查找,按位插入,按位删除,遍历打印操作


注意!!!以下代码是在c++环境中写的c代码,用了c++代码的&

1.带头结点的双链表的初始化,判断链表是否为空,前插,后插,按位序插,删除后继节点,按位查找,按之查找,清空链表,销毁链表,遍历打印列表操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//带头结点的双链表
//定义结构体
typedef struct DNode {
	int data;
	struct  DNode* prior, * next;
}DNode,*DLinklist;

//添加函数原型的声明
bool InitDLinkList(DLinklist& L);
bool Empty(DLinklist L);
bool InsertNextDNode(DNode* p, DNode* s);
bool  InsertPriorDNode(DNode* p, DNode* s);
bool InsertDNode(DLinklist& L, int i, DNode* s);
void PrintDList(DNode* L);
bool DeleteNextDNode(DNode* p);
DNode* GetElem(DLinklist L, int i);
DNode* LocateElem(DLinklist L, int e);
void ClearDList(DLinklist& L);
void DestroyDList(DLinklist& L);

//初始化双链表
bool InitDLinkList(DLinklist &L) {
	L = (DNode*)malloc(sizeof(DNode));		//申请了一片空间做为头节点,并且头指针L指向这个节点
	if (L == NULL) {
		printf("内存分配失败");
		return false;
	}
	L->prior = NULL;							//头结点的前向指针永远指向NULL
	L->next = NULL;								//头结点的下一个节点暂时还没有节点
	return true;
}

//判断链表是否为空
bool Empty(DLinklist L) {
	if (L->next == NULL)
		return true;
	else
		return false;
}

//后插操作,在p节点后插入s节点
bool InsertNextDNode(DNode *p,DNode *s) {
	if (p == NULL || s == NULL)		//非法参数
		return false;
	s->next=p->next;
	if(p->next!=NULL)	//如果p不是最后一个节点
		p->next->prior = s;
	s->prior = p;
	p->next = s;
	return true;
}

//双链表的前插操作,在p节点前插入节点s
bool  InsertPriorDNode(DNode *p,DNode *s) {
	if (p == NULL || s == NULL)				//非法参数
		return false;
	DNode* q = p->prior;	//找到p的前一个结点,在他后面进行后插
	InsertNextDNode(q, s);
	return true;
}

//实现按位序插入,实现逻辑,找到当前位序的前一个节点,在其后进行后插
bool InsertDNode(DLinklist &L, int i, DNode* s) {
	DNode *p= GetElem(L, (i - 1));
	//进行后插
	InsertNextDNode(p, s);
	return true;
}

// 打印双链表
void PrintDList(DNode* L) {
	DNode* p = L->next;		// 跳过头节点
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
}

//删除p节点后的后继节点
bool DeleteNextDNode(DNode* p) {
	if (p == NULL || p->next == NULL)
		return false;
	DNode* q = p->next;
	p->next = q->next;
	if (q->next != NULL)
		q->next->prior = p;
	free(q);
	return true;
}

//按位查询双链表,查询第i个位置的节点,并返回该节点
DNode* GetElem(DLinklist L,int i) {
	DNode* p = L;
	int j = 0;
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	if (p == NULL) // 如果p为空,说明i值过大
		return NULL;
	return p;
}

//按值查找
DNode* LocateElem(DLinklist L,int e) {
	DNode* p = L->next;			//聪第一个结点开始遍历,因为头结点的数据为NULL,无意义。
	while (p != NULL && p->data!=e) {
		p = p->next;
	}
	return p;
}

//清空双链表
void ClearDList(DLinklist &L) {
	while (L->next != NULL) {
		DeleteNextDNode(L);
	}
}

//销毁双链表
void DestroyDList(DLinklist &L) {
	ClearDList(L);
	free(L);		//释放头结点
	L = NULL;		//头指针指向NULL,使其链表结构彻底销毁
}

int main() {
	DLinklist L;
	InitDLinkList(L);
	
	//检查双链表是否为空
	printf("当前双链表是否为空:%s\n",Empty(L)?"是":"否");

	// 验证后插操作
	DNode* node1 = (DNode*)malloc(sizeof(DNode));
	node1->data = 1;
	InsertNextDNode(L, node1);
	printf("后插节点1后双链表的内容:\n");
	PrintDList(L);

	// 验证按位序插入操作
	DNode* node2 = (DNode*)malloc(sizeof(DNode));
	node2->data = 2;
	InsertDNode(L, 2, node2);
	printf("按位序插入节点2后双链表的内容:\n");
	PrintDList(L);

	// 验证前插操作
	DNode* node3 = (DNode*)malloc(sizeof(DNode));
	node3->data = 3;
	InsertPriorDNode(node2, node3);
	printf("前插节点3后双链表的内容:\n");
	PrintDList(L);

	// 验证按值查找操作
	int value = 2;
	DNode* result = LocateElem(L, value);
	if (result != NULL) {
		printf("找到值为%d的节点地址为:%d\n", value,result);
	}
	else {
		printf("未找到值为%d的节点\n", value);
	}

	// 清空双链表
	ClearDList(L);
	printf("清空双链表后:\n");
	PrintDList(L);

	// 销毁双链表
	DestroyDList(L);
	if (L == NULL) {
		printf("双链表已销毁\n");
	}
	else {
		printf("双链表销毁失败\n");
	}

	return 0;
}

结果:

2. 循环单链表初始化,判空,判断是否为尾节点

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//循环单链表
//定义单链表结构体
typedef struct LNode {
	int data;
	struct LNode* next;
}LNode,*LinkList;

//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool IsTail(LinkList L, LNode* p);

//链表初始化
bool InitList(LinkList &L) {
	//关于链表初始化是否需要将data设置为空的说法,回答如下:
	//主要是确保链表存在并且指针正确设置。
	//即头结点已经被分配内存并且 next 指针指向自己(循环链表)或 NULL(普通链表)。不需要设置data域为空
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL)
		return false;
	L->next = L;
	return true;
}

//链表判空操作,判断链表是否为空
bool Empty(LinkList L) {
	if (L->next == L)
		return true;
	else
		return false;
}

//判断节点p是否为尾节点
bool IsTail(LinkList L,LNode *p) {
	if (p->next == L)
		return true;
	else
		return false;
}

int  main() {
	LinkList L;	//定义一个单链表
	InitList(L);
	
	//判空操作验证
	printf("该循环链表是否为空:%s\n", Empty(L) ? "是" : "否");

	//是否为尾节点验证
	LNode *p= (LNode*)malloc(sizeof(LNode));
	L->next = p;
	p->next = L;
	printf("该节点是否为尾节点:%s\n", IsTail(L,p) ? "是" : "否");

	return 0;
}

结果:

3.循环双链表初始化,判空,判断是否为尾节点,插入,删除后继元素,打印链表内容操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//循环双链表
//定义单链表结构体
typedef struct LNode {
	int data;
	struct LNode *next,*prior;
}DNode, *DLinkList;

//函数原型的声明
bool InitDLinkList(DLinkList& L);
bool Empty(DLinkList L);
bool IsTail(DLinkList L, DNode* p);
bool InsertNextDNode(DNode* p, DNode* s);
bool DeleteDNode(LNode* p);
void PrintList(DLinkList L);

//初始化双链表
bool InitDLinkList(DLinkList &L) {
	L = (DNode*)malloc(sizeof(DNode));
	if (L == NULL)
		return false;
	L->next = L;
	L->prior = L;
	return true;
}

//判空操作
bool Empty(DLinkList L) {
	if (L->next == L)
		return true;
	else
		return false;
}

//判断节点p是否为尾节点
bool IsTail(DLinkList L, DNode *p) {
	if (p->next == L)
		return true;
	else
		return false;
}

//插入节点,在p节点后插入s节点
bool InsertNextDNode(DNode* p, DNode* s) {
	if (p == NULL || s == NULL) {
		return false;  // 如果 p 或 s 为空,则插入失败
	}
	p->next->prior = s;
	s->next=p->next;
	p->next = s;
	s->prior = p;
	return true;
}

//删除p节点的后继节点q
bool DeleteDNode(LNode *p) {
	if (p == NULL || p->next == NULL)
		return false;
	DNode* q = p->next;
	p->next = q->next;
	q->next->prior = p;
	free(q);
	return true;
}

// 打印链表内容
void PrintList(DLinkList L) {
	DNode* p = L->next;
	while (p != L) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

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

	// 判空操作验证
	printf("该循环双链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入节点测试
	DNode* node1 = (DNode*)malloc(sizeof(DNode));
	node1->data = 1;
	InsertNextDNode(L, node1);

	DNode* node2 = (DNode*)malloc(sizeof(DNode));
	node2->data = 2;
	InsertNextDNode(node1, node2);

	DNode* node3 = (DNode*)malloc(sizeof(DNode));
	node3->data = 3;
	InsertNextDNode(node2, node3);

	// 打印链表内容验证插入操作
	printf("链表内容: ");
	PrintList(L);

	// 是否为尾节点验证
	printf("node3 是否为尾节点:%s\n", IsTail(L, node3) ? "是" : "否");

	// 删除节点测试
	DeleteDNode(node1); // 删除 node1 的后继节点 node2

	// 打印链表内容验证删除操作
	printf("删除 node2 后链表内容: ");
	PrintList(L);

	// 释放内存
	free(node1);
	free(node3);
	free(L);

	return 0;
}

结果:

4.静态链表的初始化,查找空节点,按位查找,按位插入,按位删除,遍历打印操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
#define MaxSize 10

// 静态链表定义
typedef struct {
    int data;       // 存储数据元素
    int next;       // 下一个元素的数组下标
} SLinkList[MaxSize];

//函数原型声明
bool InitSList(SLinkList& s);
int FindFreeNode(SLinkList s);
int FindLocate(SLinkList s, int i);
bool Insert(SLinkList& s, int i, int e);
int DeleteSNode(SLinkList& s, int i);
void PrintList(SLinkList s);

// 初始化链表
bool InitSList(SLinkList& s) {
    if (s == NULL)
        return false;
    s[0].next = -1;  // 头节点,next指向-1表示空链表
    for (int i = 1; i < MaxSize; i++) {
        s[i].next = -2;  // -2表示空闲节点
    }
    return true;
}

// 找到第一个空闲的元素,并返回它的下标
int FindFreeNode(SLinkList s) {
    for (int i = 0; i < MaxSize; i++) {
        if (s[i].next == -2) {
            return i;
        }
    }
    return -1;  // 没有空闲节点
}

// 找到位序为i的元素,并返回它的下标
int FindLocate(SLinkList s, int i) {
    int pos = 0;  // 指向头节点
    for (int j = 0; j < i && pos != -1; j++) {
        pos = s[pos].next;
    }
    return pos;
}

// 按位插入,在位序为i的位置插入值为e的节点
bool Insert(SLinkList& s, int i, int e) {
    if (i < 1 || i > MaxSize - 1) return false;  // 插入位置无效

    int prev = FindLocate(s, i - 1);  // 找到位序i-1的位置
    if (prev == -1) return false;  // 插入位置无效

    int freeNode = FindFreeNode(s);  // 找到一个空闲节点
    if (freeNode == -1) return false;  // 没有空闲节点

    s[freeNode].data = e;
    s[freeNode].next = s[prev].next;
    s[prev].next = freeNode;

    return true;
}

// 删除位序为i的节点,并返回删除节点的值
int DeleteSNode(SLinkList& s, int i) {
    if (i < 1 || i >= MaxSize) return -1;  // 删除位置无效

    int prev = FindLocate(s, i - 1);  // 找到位序i-1的位置
    if (prev == -1 || s[prev].next == -1) return -1;  // 删除位置无效

    int delNode = s[prev].next;  // 要删除的节点
    int e = s[delNode].data;  // 获取删除节点的数据
    s[prev].next = s[delNode].next;  // 跳过要删除的节点
    s[delNode].next = -2;  // 将删除的节点标记为空闲节点

    return e;
}

// 打印链表中的元素
void PrintList(SLinkList s) {
    int pos = s[0].next;  // 从头节点的下一个节点开始
    while (pos != -1) {
        printf("%d -> ", s[pos].data);
        pos = s[pos].next;
    }
    printf("NULL\n");
}

int main() {
    SLinkList s;
    if (InitSList(s)) {
        Insert(s, 1, 10);
        Insert(s, 2, 20);
        Insert(s, 1, 5);
        printf("初始链表: ");
        PrintList(s);

        int deletedValue = DeleteSNode(s, 2);
        printf("删除位序为2的节点后: ");
        PrintList(s);
        printf("删除的值: %d\n", deletedValue);
    }
    else {
        printf("链表初始化失败\n");
    }

    return 0;
}

 结果:

 结束~


有收获的宝宝留个赞赞再走吧~ 

不胜感激~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux目录结构和重要文件

1. 目录介绍 操作Linux命令行&#xff0c;最基本的对象就是目录和文件&#xff0c;因为Linux中一切事物都是基于文件的&#xff0c;而目录就是文件的文件夹&#xff0c;所以接下来对一些基础且核心的文件目录管理命令进行说明。 1.1 目录结构 Linux系统目录结构是一个有层次…

达梦数据库的系统视图v$dict_cache

达梦数据库的系统视图v$dict_cache 达梦数据库系统视图V$DICT_CACHE主要用于监控和管理字典缓存的状态。字典缓存是数据库系统中用于存储元数据信息&#xff08;如表结构、索引信息等&#xff09;的缓存区域&#xff0c;它对于提高数据库查询性能至关重要。通过查询V$DICT_CAC…

Python 报错 SyntaxError: EOL while scanning string literal

Python 报错 SyntaxError: EOL while scanning string literal 在编程领域&#xff0c;尤其是使用Python这类解释型语言时&#xff0c;SyntaxError: EOL while scanning string literal 是一种常见的错误。这种错误通常发生在Python解释器尝试解析代码时&#xff0c;遇到了意外…

L-H、BytePlus 和 INOVAI在东京成功举办Web3 AI未来峰会

7月30日&#xff0c;L-H (Legendary Humanity)、字节跳动旗下BytePlus 和日本知名Web3孵化器 INOVAI 在东京联合举办Web3&AI未来峰会&#xff0c;水滴资本等行业重磅机构共同参与此次峰会&#xff0c;探讨AI与 Web3的融合性未来。 在此次峰会上&#xff0c;L-H (Legendary…

区块链软硬件协同,做产业数字化转型的“安全官” |《超话区块链》直播预告

今年的两会政府工作报告提出&#xff1a;“产业的数字化&#xff08;行业数字化转型&#xff09;是发展新质生产力的核心&#xff0c;是推动产业升级实现高质量发展的关键。”全面推进产业数字化&#xff0c;需要技术创新与产业应用深入协同&#xff1b;立足可持续发展的长远目…

动态面板数据实证模型及 Stata 具体操作步骤

目录 一、文献综述 二、理论原理 三、实证模型 四、稳健性检验 五、程序代码及解释 六、代码运行结果 一、文献综述 在经济学和社会科学的广袤领域中&#xff0c;动态面板数据模型逐渐成为研究者们探索复杂现象和关系的有力工具。众多杰出学者凭借这一模型在多个研究方向上…

30.x86游戏实战-遍历背包数组

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

弧形导轨的多样化驱动方式!

弧形导轨由导轨、导向滑块、传动机构等部分组成&#xff0c;是一种可以实现直线、圆弧、任意曲线运动的导向装置&#xff0c;广泛应用在机械设备中。弧形导轨的驱动方式具有多样性和灵活性&#xff0c;可以根据不同的应用场景和需求进行选择。 1、滚轮驱动&#xff1a;在弧形导…

全球汽车凸轮轴市场规模预测:未来六年CAGR为2.3%

随着汽车行业的持续发展和消费者对发动机性能的需求增加&#xff0c;汽车凸轮轴作为发动机核心部件之一&#xff0c;正逐渐受到市场的广泛关注。本文旨在通过深度分析汽车凸轮轴行业的各个维度&#xff0c;揭示行业发展趋势和潜在机会。 【市场趋势的演变】 1. 市场规模与增长…

VisualStudio 类设计器 组件的使用

总目录 前言 当我们需要快速熟悉一个新接手的软件系统框架及业务逻辑代码时&#xff0c;如果埋头一个个去捋顺&#xff0c;估计等你捋顺了&#xff0c;项目也结束了&#xff1b;应对这种情况最好方法就是先通过UML图去了解代码的宏观架构&#xff0c;然后有针对性的突破。VS中…

搭建Go语言gRPC微服务开发环境详细教程

文档&#xff1a;https://grpc.io/docs/languages/go/quickstart/ 下载protobuffer&#xff1a;https://github.com/protocolbuffers/protobuf/releases/tag/v27.2 解压到C:/dev目录&#xff1a; 将目录添加到环境变量&#xff1a; 打开终端进行测试&#xff1a; proto…

vite打包文件配置到IIS出现页面、图片加载不出来的问题

问题描述&#xff1a; 用vitevue3开发的项目&#xff0c;打包后放在服务器上&#xff0c;然后配置了IIS&#xff0c;用链接访问后出现白页面。 解决方案&#xff1a; 修改vite.config.js文件中的base路径&#xff1a;/改为./ 解决方案&#xff1a; 1.查看页面报错原因&…

雅致表达:看体育比赛 ,少不了的语文知识。

文章目录 引言捷报囊括当务之急问鼎凯旋折桂捞金曾几何时差强人意居功至伟一发不可收拾首当其冲不孚众望望其项背炙手可热美轮美奂摄氏度引言 随着巴黎奥运会各项赛事的展开,看到激动人心比赛画面的你,看到喜欢的选手圆梦的你,总会有冲动把喜悦分享出去,适当的用词为表达加…

MySQL笔记5——视图、存储过程和触发器

视图 创建视图 视图是从一个或几个基本表&#xff08;或视图&#xff09;导出的表。它与基本表不同&#xff0c;是一个虚表。 CREATE VIEW view_name as select…… 说明&#xff1a; view_name自己定义的视图名as后面是这个视图所用到的查询结果 视图的操作 视图的查询…

nodejs项目

一、基于域名配置server 1. 一个配置文件一般只有一个 http 模块 2. 一个 http 模块可以有多个 server 模块 3. 一个 server 模块就是一套 web 项目 4. 一个 server 模块中可以有多个 location 5. location 就是项目中的 url 路由 # 第一步 mkdir /zhangmin # 第…

GMII, SGMII 以太网接口

前言&#xff1a; &#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留…

(最全最小白易懂版)Yolov8新手教程-配置环境、数据集处理、目标检测、结果分析处理(图像指标、可视化结果)、报错分析等全过程学习记录

目录 一、安装环境&#xff08;配置yolo、demo测试&#xff09; 二、数据集准备&#xff08;格式学习&#xff09; 三、训练数据集 1.划分数据集 2.训练数据集 2.1常规训练 2.2微调 3.各种报错记录 3.1AttributeError 3.2TypeError 3.3Error while loading conda en…

贪心问题集

常见问题分类&#xff1a; 1&#xff09;区间问题 2&#xff09;Huffman 3&#xff09;排序不等式 4&#xff09;绝对值不等式 5&#xff09;推公式 一、区间问题 板子&#xff1a; ①区间选点问题 #include <iostream> #include <algorithm> using namespace std;…

【算法 01】快速排序算法与分治思想

深入理解快速排序与分治思想 在算法的世界里&#xff0c;快速排序以其高效的性能著称&#xff0c;它巧妙地运用了分治策略&#xff08;Divide and Conquer&#xff09;&#xff0c;将复杂的排序问题逐步分解为更小的子问题&#xff0c;直至问题变得足够简单&#xff0c;从而轻…

永劫无间:游戏模式操作,云手机游戏辅助教程!

在《永劫无间》中&#xff0c;快速比赛模式和无间模式是提升实力和展示技巧的重要途径。以下是详细的攻略建议&#xff0c;帮助玩家在游戏中取得更好的成绩。 快速比赛模式 快速比赛模式与排位赛的玩法内容一致&#xff0c;但对局结果不会影响你的段位积分和英雄积分&#xff…