C——单链表

一.前言

我们在前面已经了解了链表中的双向链表,而我们在介绍链表分类的时候就说过常用的链表只有两种——双向带头循环链表和单向不带头不循环链表。下来我来介绍另一种常用的链表——单向不带头不循环链表也叫做单链表。不清楚链表分类的以及不了解双向链表的可以看我之前的博客C——双向链表-CSDN博客。

二.单链表的结构

我们已经了解了单链表的全称叫做单向不带头不循环链表,我们怎么理解这链表前面的修饰词呢?其实,单链表就像是一节节连接起来的火车车厢一样。但是这节车厢只可以向后走,并且火车的车头和车尾是不能连接在一起的。

我们照着这张图再来分析单链表的结构:单向的意思就是只能沿着D->A->C->E->Z->X->W这个方向走,那不带头的意思就是没有头节点即哨兵位,我们在讲双向链表的时候提到了哨兵位,他只是一个没有有效数据的头节点。不循环的意思我们也可以对照这双向链表来看,双向链表的尾节点可以找到头节点,头节点也可以找到尾节点,这就是循环;而单链表的尾节点指向的不是头节点而是NULL,头节点也不能找到尾节点。

那么单链表的节点到底是什么样的呢?

 我们再来与双向链表的节点进行对比一下:

 单链表节点只有两个成员,分别是数据和指向下一个节点的指针,而双向链表的节点有三个成员,分别是数据,指向前一个节点的指针和指向下一个节点的指针。

综上所述:单链表是一个只能指向下一个节点的链表,而且没有头节点,并且是不循环的。 

三.实现单链表

与双向链表的实现相似,实现单链表也需要很多的函数及头文件,所以我们将所有的函数声明和头文件都放到singlelist.h中,函数的实现都放入singlelist.c中。

3.1单链表节点的结构

//链表节点
struct SingleList
{int val;struct SingleList* next;
};

我们这样写虽然可以完成链表的基本结构,但是难道我们链表只能存储整形嘛?如果我们创建了很多个整型节点,但是有一天我们想利用链表存储字符型或者浮点型数据,那么我们就得一个一个的去修改,费时费力;还有就是这个节点的名称很长,在后面的代码中会重复出现,也很浪费时间。所以我们可以利用typedef关键词,对节点重命名,以及对int重命名。

//节点数据类型
typedef int SingleListdatatype;//链表节点
typedef struct SingleListNode
{SingleListdatatype val;struct SingleListNode* next;
}SLNode;

这样我们在多次使用该类型的时候就不需要再写那么长一串了,以后再修改储存的数据类型的时候也就不用一个一个节点的修改了,只需将定义的节点数据类型中的数据类型修改即可。

3.2单链表节点的创建

 我们在创建节点的时候实际上就是创建一个结构体变量,我们可以利用动态内存管理为我们的每一个节点动态开辟一块内存空间。

//节点的创建
SLNode* BuyNode(SingleListdatatype x)
{SLNode* node = (SLNode*)malloc(sizeof(SLNode));if (node == NULL){perror("malloc");exit(-1);}node->val = x;node->next = NULL;return node;
}

 我们来测试一下节点创建函数是否正确:

我们利用此测试代码来调试发现,我们创建了4个节点,通过调试也确实观察到了这四个节点,并且它们储蓄的数据就是我们传的数据,指向下一个节点的指针也是NULL。与我们想要实现的结果相同。 

那我们现在将这四个节点连接起来:

void test1()
{SLNode* plist = NULL;SLNode* plist1 = BuyNode(1);SLNode* plist2 = BuyNode(2);SLNode* plist3 = BuyNode(3);SLNode* plist4 = BuyNode(4);plist1->next = plist2;plist2->next = plist3;plist3->next = plist4;
}int main()
{test1();return 0;
}

我们再来调试一下: 

我们看到将所有节点连接起来之后,我们就可以利用第一个节点找到后面的节点。 

3.3链表的打印

//链表的打印
void SLNodePrint(SLNode* plist)
{while (plist)//plist != NULL{printf("%d->", plist->val);plist = plist->next;}printf("NULL\n");
}

 我们再来测试一下该函数:

也是没有出现问题,说明我们链表的打印已经完成了。 

3.4尾插

我们现在创建的节点需要我们手动将其连接起来,我们可以利用尾插方法,将新创建的节点直接连接到前一个节点上。 

//尾插
void SLNodepushback(SLNode** plist, SingleListdatatype x)
{assert(plist);SLNode* newnode = BuyNode(x);//新节点if (*plist == NULL){//空链表*plist = newnode;}else{//非空链表//遍历原链表,找到尾节点SLNode* pcur = *plist;while (pcur->next)//(*plist)->next != NULL{pcur = pcur->next;}pcur->next = newnode;}
}

我们测试下尾插方法:

我们尾插了四次,通过打印方法,将链表打印出来,说明我们的尾插方法也没有问题。但是有些人可能会有疑问:为什么这里传的是二级指针 而不传一级指针?

因为我们是通过一个结构体类型的指针来维护我们的链表,而我们传一级指针的话相当于值传递,而对于值传递来说,形参改变是不影响实参的。简单来说,就说你在函数内部将形参节点的next指针改变了,但是却不影响实参的值。达不到我们的目的。所以要想形参的改变影响实参的话,我们就得地址传递,就得传一级指针的地址,也就是二级指针

3.5头插 

头插从名字就可以听出来是把一个新节点插到链表的头部,我们利用图来分析如何进行头插:

//头插
void SLpushfront(SLNode** plist, SingleListdatatype x)
{assert(plist);SLNode* newnode = BuyNode(x);newnode->next = *plist;*plist = newnode;
}

我们测试头插方法:

根据打印结果来看,头插的方法也没有任何问题。 

3.6尾删

尾删就是删除链表中的尾节点,那么前提就是该链表不能为空,如果都是空链表了,怎么执行删除操作呢?我们画图来分析一下:

//尾删
void SLpopback(SLNode** plist)
{assert(plist && *plist);//*plist != NULL防止链表为空SLNode* pcur = *plist;//记录倒数第二个节点SLNode* del = *plist;//记录尾节点while (del->next){pcur = del;del = del->next;}pcur->next = NULL;free(del);del = NULL;
}

我们测试之后发现出了错误,这是为什么呢?

我们进行四次尾删,最后一次删除会将1删除掉,此时应该只打印NULL,这里打印了随机值。这是为什么呢? 

//尾删
void SLpopback(SLNode** plist)
{assert(plist && *plist);//*plist != NULL防止链表为空if (!((*plist)->next))//(*plist)->next == NULL{//链表只有一个节点free(*plist);*plist = NULL;}else{//链表有多个节点SLNode* pcur = *plist;//记录倒数第二个节点SLNode* del = *plist;//记录尾节点while (del->next){pcur = del;del = del->next;}pcur->next = NULL;free(del);del = NULL;}
}

我们现在再来测试一下修改后的尾删代码: 

我们看到,现在就没有问题了。

3.7头删

我们实现了尾删,现在来实现头删。头删的前提与尾删的前提相同:链表不能为空。头删实际上就是删除链表中的第一个节点,我们画图分析如何实现头删:

//头删
void SLpopfront(SLNode** plist)
{assert(plist && *plist);//链表不能为空SLNode* next = (*plist)->next;free(*plist);*plist = next;
}

我们来测试头删方法:

没有问题~ 

那如果我们多删一次呢?

我们看到,第五次删除的时候这时候已经是空链表了,我们再看提示的错误信息,说是断言出错了,这就说明了链表为空了。 

3.8查找数据

查找数据非常简单,我们只需要遍历链表,将要查找的数据与链表中的数据进行对比,如果找到了则返回该数据对应节点的地址;如果没找到则返回NULL。

//查找
SLNode* SLFind(SLNode* plist, SingleListdatatype x)
{assert(plist);SLNode* pcur = plist;while (pcur){if (pcur->val == x){return pcur;}pcur = pcur->next;}return NULL;
}

测试查找:

结果没毛病,老铁OK了! 

3.9在指定位置之前插入数据

我们要在指定位置的前面插入数据,所以我们必须得找到该指定位置,这就需要调用我们的查找方法了。我们来画图分析一下:

//在指定位置之前插入数据
void SLposfront(SLNode** plist, SLNode* pos, SingleListdatatype x)
{assert(plist && *plist);//链表不能为空,否则找不到指定位置if (pos == *plist){//pos节点就是第一个节点//调用头插方法SLpushfront(plist,x);}else{//pos节点不是第一个节点SLNode* newnode = BuyNode(x);SLNode* pcur = *plist;SLNode* prev = *plist;while (pcur){if (pcur->val == pos->val){break;}prev = pcur;pcur = pcur->next;}// prev newnode pcur/posprev->next = newnode;newnode->next = pcur;}
}

 我们测试该代码:

我们测试了三种位置的插入,无论是第一个节点之前还是中间节点之前或者是尾节点之前都没有问题。

3.10在指定位置之后插入数据

在指定位置之后插入数据与在指定位置之前插入数据有相同点但也有不同点,我们继续来画图分析:

//在指定位置之后插入数据
void SLposback(SLNode* pos, SingleListdatatype x)
{assert(pos);SLNode* newnode = BuyNode(x);//pos newnode pos->nextnewnode->next = pos->next;pos->next = newnode;
}

我们对其进行测试来看: 

3.11删除pos节点

我们现在来删除指定节点,前提肯定是链表不能为空。我们接着来画图分析:

//删除pos节点
void slpoppos(SLNode** plist, SLNode* pos)
{assert(plist && *plist);assert(pos);if (*plist == pos){//pos是头节点,调用头删方法SLpopfront(plist);}else{SLNode* prev = *plist;while (prev->next != pos){//找到pos的前一个节点prev = prev->next;}//prev pos pos->nextprev->next = pos->next;free(pos);pos = NULL;}
}

测试该代码: 老铁没毛病!

3.12删除pos节点之后的节点

删除pos节点之后的节点我们要改变指向的指针就只有一个了,那就是pos->next指针。要让它指向pos->next->next。我们画图分析:

//删除pos节点后一个节点
void slpopposback(SLNode* pos)
{assert(pos && pos->next);//pos->next != NULL避免pos是尾节点SLNode* Next = pos->next;pos->next = pos->next->next;free(Next);Next = NULL;
}

 测试代码:

那如果我们的pos节点就是尾节点程序会发生什么呢? 

我们看到,上面提醒我们断言出错,说明此时pos节点为尾节点。 

3.13销毁链表

//销毁链表
void DestorySL(SLNode** plist)
{assert(plist && *plist);SLNode* Next = (*plist)->next;while (Next){free(*plist);*plist = Next;Next = Next->next;}free(*plist);*plist = NULL;
}

 我们通过调试来判断我们的销毁方法:没有问题!

到这里,我们单链表的所有方法都已经完成了。下面附上完整代码:

四.完整代码

1.singlelist.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>//节点数据类型
typedef int SingleListdatatype;//链表节点
typedef struct SingleListNode
{SingleListdatatype val;struct SingleListNode* next;
}SLNode;//节点的创建
SLNode* BuyNode(SingleListdatatype x);//链表的打印
void SLNodePrint(SLNode* plist);//尾插
void SLNodepushback(SLNode** plist, SingleListdatatype x);//头插
void SLpushfront(SLNode** plist, SingleListdatatype x);//尾删
void SLpopback(SLNode** plist);//头删
void SLpopfront(SLNode** plist);//查找
SLNode* SLFind(SLNode* plist, SingleListdatatype x);//在指定位置之前插入数据
void SLposfront(SLNode** plist, SLNode* pos,SingleListdatatype x);//在指定位置之后插入数据
void SLposback(SLNode* pos, SingleListdatatype x);//删除pos节点
void slpoppos(SLNode** plist, SLNode* pos);//删除pos节点后一个节点
void slpopposback(SLNode* pos);//销毁链表
void DestorySL(SLNode** plist);

2.singlelist.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SingleList.h"//节点的创建
SLNode* BuyNode(SingleListdatatype x)
{SLNode* node = (SLNode*)malloc(sizeof(SLNode));if (node == NULL){perror("malloc");exit(-1);}node->val = x;node->next = NULL;return node;
}//链表的打印
void SLNodePrint(SLNode* plist)
{while (plist)//plist != NULL{printf("%d->", plist->val);plist = plist->next;}printf("NULL\n");
}//尾插
void SLNodepushback(SLNode** plist, SingleListdatatype x)
{assert(plist);SLNode* newnode = BuyNode(x);//新节点if (*plist == NULL){//空链表*plist = newnode;}else{//非空链表//遍历原链表,找到尾节点SLNode* pcur = *plist;while (pcur->next)//(*plist)->next != NULL{pcur = pcur->next;}pcur->next = newnode;}
}//头插
void SLpushfront(SLNode** plist, SingleListdatatype x)
{assert(plist);SLNode* newnode = BuyNode(x);newnode->next = *plist;*plist = newnode;
}//尾删
void SLpopback(SLNode** plist)
{assert(plist && *plist);//*plist != NULL防止链表为空if (!((*plist)->next))//(*plist)->next == NULL{//链表只有一个节点free(*plist);*plist = NULL;}else{//链表有多个节点SLNode* pcur = *plist;//记录倒数第二个节点SLNode* del = *plist;//记录尾节点while (del->next){pcur = del;del = del->next;}pcur->next = NULL;free(del);del = NULL;}
}//头删
void SLpopfront(SLNode** plist)
{assert(plist && *plist);//链表不能为空SLNode* next = (*plist)->next;free(*plist);*plist = next;
}//查找
SLNode* SLFind(SLNode* plist, SingleListdatatype x)
{assert(plist);SLNode* pcur = plist;while (pcur){if (pcur->val == x){return pcur;}pcur = pcur->next;}return NULL;
}//在指定位置之前插入数据
void SLposfront(SLNode** plist, SLNode* pos, SingleListdatatype x)
{assert(plist && *plist);//链表不能为空,否则找不到指定位置assert(pos);if (pos == *plist){//pos节点就是第一个节点//调用头插方法SLpushfront(plist,x);}else{//pos节点不是第一个节点SLNode* newnode = BuyNode(x);SLNode* pcur = *plist;SLNode* prev = *plist;while (pcur){if (pcur->val == pos->val){break;}prev = pcur;pcur = pcur->next;}// prev newnode pcur/posprev->next = newnode;newnode->next = pcur;}
}//在指定位置之后插入数据
void SLposback(SLNode* pos, SingleListdatatype x)
{assert(pos);SLNode* newnode = BuyNode(x);//pos newnode pos->nextnewnode->next = pos->next;pos->next = newnode;
}//删除pos节点
void slpoppos(SLNode** plist, SLNode* pos)
{assert(plist && *plist);assert(pos);if (*plist == pos){//pos是头节点,调用头删方法SLpopfront(plist);}else{SLNode* prev = *plist;while (prev->next != pos){//找到pos的前一个节点prev = prev->next;}//prev pos pos->nextprev->next = pos->next;free(pos);pos = NULL;}
}//删除pos节点后一个节点
void slpopposback(SLNode* pos)
{assert(pos && pos->next);//pos->next != NULL避免pos是尾节点SLNode* Next = pos->next;pos->next = pos->next->next;free(Next);Next = NULL;
}//销毁链表
void DestorySL(SLNode** plist)
{assert(plist && *plist);SLNode* Next = (*plist)->next;while (Next){free(*plist);*plist = Next;Next = Next->next;}free(*plist);*plist = NULL;
}

3.test.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include "SingleList.h"//void test1()
//{
//	SLNode* plist1 = BuyNode(1);
//	SLNode* plist2 = BuyNode(2);
//	SLNode* plist3 = BuyNode(3);
//	SLNode* plist4 = BuyNode(4);
//
//	plist1->next = plist2;
//	plist2->next = plist3;
//	plist3->next = plist4;
//
//	SLNodePrint(plist1);
//}void test2()
{SLNode* plist = NULL;//测试尾插SLNodepushback(&plist, 1);SLNodepushback(&plist, 2);SLNodepushback(&plist, 3);SLNodepushback(&plist, 4);SLNodePrint(plist);//测试销毁链表DestorySL(&plist);//测试删除pos节点的下一个节点//SLNode* find = SLFind(plist, 4);//slpopposback(find);//SLNodePrint(plist);//测试删除pos节点//SLNode* find = SLFind(plist, 4);//slpoppos(&plist,find);//SLNodePrint(plist);//测试在指定位置之后插入数据//SLNode* find = SLFind(plist, 1);//SLposback(find,66);//SLNodePrint(plist);//测试在指定位置之前插入数据//SLNode* find = SLFind(plist, 4);//SLposfront(&plist,find,100);//SLNodePrint(plist);//测试查找//SLNode* find = SLFind(plist,99);//if (find == NULL)//{//	printf("找不到!");//}//else//{//	printf("找到了!");//}//测试头删//SLpopfront(&plist);//SLNodePrint(plist);//2 3 4//SLpopfront(&plist);//SLNodePrint(plist);//3 4//SLpopfront(&plist);//SLNodePrint(plist);//4//SLpopfront(&plist);//SLNodePrint(plist);//NULL//SLpopfront(&plist);//SLNodePrint(plist);//测试尾删//SLpopback(&plist);//SLNodePrint(plist);//1 2 3//SLpopback(&plist);//SLNodePrint(plist);//1 2//SLpopback(&plist);//SLNodePrint(plist);//1//SLpopback(&plist);//SLNodePrint(plist);//NULL//测试头插//SLpushfront(&plist,100);//SLNodePrint(plist);//SLpushfront(&plist,99);//SLNodePrint(plist);
}int main()
{//test1();test2();return 0;
}

完!

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

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

相关文章

Prometheus-Operator:快速部署

1. 项目目标 &#xff08;1&#xff09;了解Prometheus-Operator的优势 &#xff08;2&#xff09;熟练掌握Prometheus-Operator部署 &#xff08;3&#xff09;操作Grafana对接Prometheus 2. 项目准备 2.1. 规划节点 主机名 主机IP 节点规划 Prometheus 主机IP Prom…

如何克服挑战?跨境电商平台开发中的关键挑战解析

在当今的数字化时代&#xff0c;跨境电商平台开发成为了许多企业所关注的焦点。然而&#xff0c;随之而来的是一系列挑战&#xff0c;需要克服才能确保项目成功推进。从法律合规、支付结算到物流运输&#xff0c;跨境电商平台开发中的挑战多而复杂。本文将针对跨境电商平台开发…

【Matlab】Matlab之美,抓紧来膜拜大神的创星之作(附2024Matlab教程+代码)

软件介绍 MATLAB是一款商业数学软件&#xff0c;用于算法开发、数据可视化、数据分析以及数值计算的高级技术计算语言和交互式环境&#xff0c;主要包括MATLAB和Simulink两大部分&#xff0c;可以进行矩阵运算、绘制函数和数据、实现算法、创建用户界面、连接其他编程语言的程序…

福派斯鸭肉梨狗粮,让狗狗告别泪痕困扰!值得一试吗?

亲爱的宠友们&#xff0c;你们是不是也为自家狗狗的泪痕问题头疼不已呢&#xff1f;&#x1f914;今天我就来给大家聊聊福派斯鸭肉梨去泪痕狗粮&#xff0c;看看这款狗粮究竟怎么样&#xff0c;去泪痕效果好不好&#xff0c;以及值不值得入手哦&#xff01; 首先&#xff0c;我…

【MySQL】SQL基本知识点DDL(1)

目录 1.SQL分类&#xff1a; 2.DDL-数据库操作 3.DDL-表操作-创建 4.DDL-表操作-查询 5.DDL-表操作-数据类型 6.DDL-表操作-修改 1.SQL分类&#xff1a; 2.DDL-数据库操作 3.DDL-表操作-创建 注意&#xff1a;里面的符号全部要切换为英文状态 4.DDL-表操作-查询 5.DDL…

如何内网穿透,远程访问内网设备

文章目录 0.前言1.准备工作2.内网穿透原理3.配置公网服务器的frp5.配置访问内网主机6.配置win10的远程桌面访问&#xff08;win11类似&#xff09;7.参考资料 0.前言 最近想研究一些新东西&#xff0c;公司的机器不敢乱搞&#xff0c;公司测试的服务器安装软件太多&#xff0c…

【送书福利第六期】Java开发的150多个坑,你踩过几个?(文末送书)

文章目录 做Java开发别掉坑里还不知道 程序员为什么会掉到坑里却不自知&#xff1f;第一是意识不到坑的存在。第二是有些 bug 或问题只在特定情况下暴露。第三是变化不明显的性能问题。 《Java开发坑点解析&#xff1a;从根因分析到最佳实践》Java 开发完美避坑指南结语 &#…

zblog中用户中心-邀请码注册插件的导出功能补充

自己加了一个导出未使用的邀请码功能&#xff0c;可惜我不是入驻作者&#xff0c;没有权限发布&#xff0c;之前被一条大河拒了&#xff0c;他说我抄他代码&#xff0c;不给我过审还冷嘲热讽&#xff0c;我一气之下&#xff0c;就没继续申请了&#xff0c;话说我是专业搞java开…

中国地图(2024版审图号地图)和地图变化说明

2024版shp格式审图号地图预览图&#xff1a; 新版中国地图的变化&#xff08;简述&#xff09; 国土面积的增加&#xff1a;新版中国地图显示&#xff0c;中国的国土面积从960万平方公里增加到1045万平方公里&#xff0c;增加了85万平方公里。 九段线变为十段线&#xff1a;…

RFID工业读写器在危化品储存管理的优势有哪些?

在化学品和危险品储存管理领域&#xff0c;传统的管理方式通常存在一些痛点和挑战&#xff1a;化学品和危险品的管理主要依赖于人工记录和监控&#xff0c;容易出现数据不准确、遗漏、混淆等问题&#xff0c;导致安全隐患和管理困难。化学品和危险品的存储和管理涉及到一系列安…

#04 构建您的第一个神经网络:PyTorch入门指南

文章目录 前言理论基础神经网络层的组成前向传播与反向传播 神经网络设计步骤1&#xff1a;准备数据集步骤2&#xff1a;构建模型步骤3&#xff1a;定义损失函数和优化器步骤4&#xff1a;训练模型步骤5&#xff1a;评估模型结论 前言 在过去的几天里&#xff0c;我们深入了解了…

InLine Chat功能优化对标Github Copilot,CodeGeeX带来更高效、更直观的编程体验!

VSCode中的CodeGeeX 插件上线InLine Chat功能后&#xff0c;收到不少用户的反馈&#xff0c;大家对行内交互编程这一功能非常感兴趣。近期我们针对这个功能再次进行了深度优化&#xff0c;今天详细介绍已经在VSCode插件v2.8.0版本上线的 CodeGeeX InLine Chat功能&#xff0c;以…

C++ 多态的相关问题

目录 1. 第一题 2. 第二题 3. inline 函数可以是虚函数吗 4. 静态成员函数可以是虚函数吗 5. 构造函数可以是虚函数吗 6. 析构函数可以是虚函数吗 7. 拷贝构造和赋值运算符重载可以是虚函数吗 8. 对象访问普通函数快还是访问虚函数快 9. 虚函数表是什么阶段生成的&…

SQL的命令

目录 创建用户 ​编辑 DDL数据库操作 查询 创建 使用 删除 创建数据库表 在表中修改字段 查询表 DML 添加数据 修改 删除 DQL 查询 创建用户 DDL数据库操作 查询 show databases; 创建 权限问题导致无法创建&#xff0c;连接root修改用户权限 CREATE DATABAS…

企业微信创建应用(一)

登录到企业微信后台管理(https://work.weixin.qq.com/)进入自建应用(应用管理-应用-创建应用) 3.查看参数AgentId和 Secret 4.企业微信查看效果

报表控件Stimulsoft指南:在 JavaScript 报告工具中使用节点计划

我们最近发布了一篇关于使用Quartz.NET 库自动执行报告任务的文章。继续这个主题&#xff0c;今天我们将深入探讨我们的报告如何与 Node Schedule 作业调度程序集成。 Stimulsoft Ultimate &#xff08;原Stimulsoft Reports.Ultimate&#xff09;是用于创建报表和仪表板的通用…

《C语言文件处理:从新手到高手的跃迁》

&#x1f4c3;博客主页&#xff1a; 小镇敲码人 &#x1f49a;代码仓库&#xff0c;欢迎访问 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3fd;留言 &#x1f60d;收藏 &#x1f30f; 任尔江湖满血骨&#xff0c;我自踏雪寻梅香。 万千浮云遮碧…

matlab-贪婪算法寻找最小覆盖

文章目录 一、最小结点集是什么二、贪婪算法实现查找最小结点集代码结果 一、最小结点集是什么 最小覆盖集&#xff08;也称为最小点覆盖集&#xff09;是图论中的一个重要概念&#xff0c;指的是一个节点子集&#xff0c;使得图中的每一条边都与这个子集中的至少一个节点关联…

一款助力工程项目管理智能化的神器——企智汇工程项目管理系统!

大家好&#xff0c;今天我要向大家介绍一款能够助力工程项目管理智能化的神器——企智汇工程项目管理系统。 在工程项目管理中&#xff0c;信息不对称、数据不共享、沟通不畅等问题一直困扰着管理者和工程师们。而企智汇正是为了解决这些问题而生的。 一、项目全过程可视化&a…

qt: undefined reference to `vtable for aaa‘

版本qt4.8.6&#xff0c;编译报错“main.cpp:(.text0x3b): undefined reference to vtable for aaa” 就一个main.cpp #include <QApplication> #include <QTimer> #include <QCursor> #include <QMouseEvent> #include <QDesktopWidget> #inc…