C语言(指针)8

                  Hi~!这里是奋斗的小羊,很荣幸各位能阅读我的文章,诚请评论指点,关注+收藏,欢迎欢迎~~     

                                💥个人主页:小羊在奋斗

                                💥所属专栏:C语言   

        本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为同样是初学者的学友展示一些我的学习过程及心得。文笔、排版拙劣,望见谅。

                                1、qsort 使用举例

                                                1.1qsort 是什么?

                                                1.2使用 qsort 函数排序整型数据

                                                1.3使用 qsort 函数排序结构数据

                                2、qsort 函数的模拟实现

                                                本节内容较多,如有需要请收藏阅读。

1、qsort 使用举例

        1.1qsort 是什么?

        qsort 是C语言中的一个库函数,使用 qsort 库函数需要包含头文件 <stdlib.h>。这个函数是用来对任意数据类型的数据排序的。

        我们之前也写过一个排序函数:

//冒泡排序 — 升序
#include <stdio.h>void bubble_sort(int arr[], int m)
{int i = 0;for (i = 0; i < m - 1; i++){int j = 0;int flag = 1;for (j = 0; j < m - 1 - i; j++){if (arr[j] > arr[j + 1]){flag = 0;int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}if (1 == flag){break;}}
}int main()
{int arr[100] = { 0 };int n = 0;do{scanf("%d", &arr[n++]);} while (arr[n - 1] != -1);//以-1为结束标志bubble_sort(arr, --n);int i = 0;for (i = 0; i < n; i++){printf("%d ", arr[i]);}return 0;
}

        上面是我们之前写过的一个冒泡排序,它可以实现排序,但它排序的对象只能是整型,所以它的功能太单一。而 qsort 函数可以实现对任意类型的数据进行排序,它不仅可以完成上面我们写的冒泡排序的功能,还能对字符型、字符串型、实型、结构体类型等排序,我们只要需要提供一个比较函数就行。 

        我们先来了解一下 qsort 函数的用法:

以下图片均截自C 标准库头文件 - cppreference.com ,更多详细内容请跳转查看。

         上图为 qsort 函数的参数个数、参数类型、函数返回值类型及其功能的简单介绍。

         上图为 qsort 函数参数的详细介绍。其中最后一个参数是一种函数指针类型,我们需要自定义一个比较函数将地址传给这个函数指针变量,再通过这个指针调用函数,这个函数就是一个回调函数。

         上图为 qsort 函数的使用实例。

        为什么要有 qsort 函数呢?它能帮我们做什么?在回答这个问题之前,让我们的目光再回到上节我们写的冒泡排序中,先思考另一个问题,为什么我们写的冒泡排序只能排整形数据呢?

        原因就在上面的红色方框中。因为如果我们想排字符串的话,字符串不能用 > 号比较大小,应该用字符串比较函数 strcmp ,简单地修改后,我们发现其他的地方基本不需要再做修改。所以我们只需要改变上面红色方框中的代码,就可以实现对字符串排序了。

        也就是说,排序的基本框架不变,变的只是数据的比较部分,那我们把基本框架封装成一个函数,而用于数据的比较部分我们再写一个函数,这样的话我们想排序什么类型,只需要写一个相应类型的比较函数,再将这个函数传给事先就分装好的框架函数,不就实现了想排序什么类型的数据就排序什么类型的数据吗?

        很明显我们所说的将基本框架分装一个函数,就是我们要学习的 qsort 函数,而需要我们自己写的比较函数,它的地址就作为 qsort 函数的第四个参数。

        qsort 函数就像一个半自动的机器,想使用它必须要有人操作,而且这个人必须事先明确自己想要得到什么,需要给 qsort 函数传递一个什么东西它才能给出我们想要的结果。

        1.2使用 qsort 函数排序整型数据 

        通过上面的了解,接下来我们就来模仿 qsort 函数的使用示例写一个排序整型的小程序:

#include <stdio.h>
#include <stdlib.h>void cmp_int(const void* a, const void* b)
{if (*(int*)a > *(int*)b){return 1;}else if (*(int*)a < *(int*)b){return -1;}else{return 0;}
}void print(const void* pa, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", *((int *)pa + i));}
}void text()
{int arr[] = { 5,3,2,7,8,1,0,4,9,6 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_int);print(arr, sz);
}int main()
{text();return 0;
}

         上面的代码中有一些细节的地方,比如:

         指针变量a和b的类型都是 void * 类型,而我们在之前的文章中说过 void * 类型的指针是不能直接进行解引用的。由于上面的程序是排序整型数据,所以我们需要将 void * 类型的指针变量a和b强转为 int * 类型再解引用。 在 C语言(指针)2 中我们说过这么两段话:

        虽然void *类型的指针不能直接进行解引用操作,也不能 +- 整数的操作, 但是当我们不知道别人给我们传的地址是什么类型的时候,我们就可以放心地去用void *来接收,这就是它的作用。

        一般void *类型的指针是使用在函数参数的部分,用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果,使得一个函数来处理多种类型的数据。在后面的文章中会深入探讨。 

        相信我们现在已经明白了其中的含义。正是因为 void * 类型的特殊,qsort 函数才得以对任意数据类型的数据进行排序。 

        上面函数的功能只是打印出排序好的整型数据, 因此并不希望数据被改变,所以我们可以用 const 修饰指针变量,增强数据的健壮性,防止我们不小心通过指针间接地改变了数据。

        1.3使用 qsort 函数排序结构数据

        为了证明 qsort 函数确实可以对任意类型的数据排序,我们再来用 qsort 函数排序结构型数据:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct people
{char name[20];int age;
};void cmp_struct_name(const void* a, const void* b)
{return strcmp((*(struct people*)a).name, (*(struct people*)b).name);
}void print_struct(const struct people* p, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%s ", (*(p + i)).name);}
}void text1()//排序结构体数据类型的数据
{struct people p[] = { { "xiaoshuai", 25}, { "xiaomei", 24 }, { "xiaochou", 23 } };int sz = sizeof(p) / sizeof(p[0]);qsort(p, sz, sizeof(p[0]), cmp_struct_name);print_struct(p, sz);
}int main()
{text1();return 0;
}

        上面是结构体成员——名字的排序,其中也有几处细节需要注意:

 

        值得一说的是,strcmp 函数的返回值规则是:当第一个字符串大于第二个字符串时返回一个正数,小于时返回一个负数,相等时则返回0,这与 qsort 函数是一致的,所以这里没有使用 if—else 分支来判断,而是直接return了strcmp函数的返回值。

        同样的道理,我们上面写过的排序整型数据的这部分代码也是可以写成下面这样的,这样写更加简单高效:

        但是,这样写是有一点风险的,虽然这个风险微乎其微,但还是值得说一下。其实细心的朋友已经知道了,因为我们之前给出的截图中已经有两行大字明确说明了这种写法的风险,并且推荐了更加科学的写法。

        虽然第二种写法在现实中发生错误的概率很小很小,但我们不能因为如此就放肆地使用这种写法,最后养成一种坏习惯。作为一名技术人员应当时刻保持严谨、科学、负责任的工作态度,这样才能写出高质量且万无一失的代码。

        我们下面还要写一个结构体成员——年龄的排序,但是在写这个代码之前,我们先来补充一个关于结构体成员访问、之前欠下的一点内容。

        结构体成员访问有两种方法,一种是我们用过的 " . " 结构体成员访问操作符,还有一种就

是 “->” 结构体成员访问操作符。它们两个的使用方法是:

        下面就来用结构体成员访问操作符 “ -> ” 来实现结构体成员——年龄的排序:

#include <stdio.h>
#include <stdlib.h>struct people
{char name[20];int age;
};void cmp_struct_age(const void* a, const void* b)
{int arg1 = ((struct people*)a)->age;int arg2 = ((struct people*)b)->age;return (arg1 > arg2) - (arg1 < arg2);
}void print_struct(const struct people* p, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", (*(p + i)).age);}
}void text2()//排序结构体数据类型的数据
{struct people p[] = { { "xiaoshuai", 25}, { "xiaomei", 24 }, { "xiaochou", 23 } };int sz = sizeof(p) / sizeof(p[0]);qsort(p, sz, sizeof(p[0]), cmp_struct_age);print_struct(p, sz);
}int main()
{//text1();text2();return 0;
}

 

        而上面的方法就不需要对结构体指针变量a和b进行解引用操作了。 

        说到这里,我来对 qsort 函数做一个简单的总结:

        (1)qsort 函数是一个库函数,使用需要包含头文件 <stdlib.h>;

        (2)qsort 函数使用的排序算法为快速排序,并且默认排升序;

        (3)qsort 函数可以实现对任意数据类型的数据排序,但只是一个 “半成品” ,需要我们自己写一个某种数据类型的比较函数, 再通过函数指针调用;

        (4)qsort 函数能实现的关键就是 void * 类型,正是因为它能接收任意类型的指针而实现了泛型编程的效果。

        qsort 函数默认排升序,那能不能想办法让它排降序呢?其实实现起来很简单,比如下面的这个代码,我们只需要把a和b的值交换,就可以实现降序了。

2、qsort 函数的模拟实现

        我们是否可以将 bubble_sort 函数改造一下,让它就像 qsort 函数一样可以实现对任意数据类型的数据排序呢?其实是可以的。既然我们已经搞清楚了 qsort 函数的实现逻辑,那就可以仿照 qsort 函数来改造我们的冒泡排序,使它也能完成对任意类型的数据排序。

        首先我们可以将自己的意识分为两个,一个是小帅,另一个是小美。小帅现在需要写一个 bubble_sort 函数,这个函数可以实现对任意类型的数据排序,默认排升序。虽然小帅不知道小美要用他写的这个函数排什么类型的数据,但他可以定一个规则,告诉小美她想使用这个函数的话需要做些什么。

        现在我们将意识转换为小帅。我要创建一个可以对任意类型的数据排序的函数,起个名字叫bubble_sort ,函数不需要返回值。第一个参数需要接收小美传过来的数组首元素的地址,但我不知道这个元素是什么类型,所以只能定义为 void * 类型;有了数组首元素的地址,我还需要知道数组内元素的个数,所以第二个参数要接收数组内元素的个数;我还需要知道一个元素占多少个字节,因为我没法仅通过首元素的地址和元素的个数来找到其他的元素;最后还需要一个参数来接收小美传过来的比较函数的地址,这个比较函数需要小美自己写,并且这个比较函数的规则是当前一个元素大于后一个元素时返回一个正值,小于返回一个负值,等于则返回0。

        梳理清楚后我就可以写出下面函数的主体部分,用到的排序算法是冒泡排序: 

void bubble_sort(void *pa, size_t sz, size_t width, int (*cmp)(const void *a, const void *b))
{int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;int flag = 1;for (j = 0; j < sz - 1 - i; j++){//判断大小}if (1 == flag){break;}}
}

         接下来我需要调用小美写的比较函数并判断其返回值,当返回值大于0时我要交换这两个比较的值的位置。但是由于我并不知道小美要排什么类型的数据,所以我在调用小美的比较函数时怎样传参就是一个问题。

        我现在知道首元素的地址,还知道一个元素的大小宽度,那我想要访问其他元素的时候就可以先将这个元素强转为最小类型也就是 char * 类型的指针,再给这个元素加上n个元素的宽度就可以实现访问每个元素的地址了。那我就可以写出下面的代码:

void bubble_sort(void *pa, size_t sz, size_t width, int (*cmp)(const void *a, const void *b))
{int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;int flag = 1;for (j = 0; j < sz - 1 - i; j++){//判断大小if (cmp((char*)pa + j * width, (char*)pa + (j + 1) * width) > 0){//交换两个值的位置}}if (1 == flag){break;}}
}

        如果这个回调函数的返回值大于0,我就要交换这两个指针(地址)指向的数据的位置,那我再写一个交换函数来实现交换操作。想要交换就必须对指针进行解引用,解引用的前提又必须对 void * 类型的指针转换类型,但是在不知道类型的情况下很明显又是一个棘手的问题。

        虽然我不知道指针的类型,但我知道元素的大小,类似于上面指针访问的思想我可以一个字节一个字节的交换,因为无论是什么类型它的大小都大于或等于一个字节,那对于n个字节大小的元素我就交换n次,很明显这个n就是我们知道的元素的大小宽度。那我就可以写出下面的代码:

void swap(char* buf1, char* buf2, size_t width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}void bubble_sort(void *pa, size_t sz, size_t width, int (*cmp)(const void *a, const void *b))
{int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;int flag = 1;for (j = 0; j < sz - 1 - i; j++){//判断大小if (cmp((char*)pa + j * width, (char*)pa + (j + 1) * width) > 0){//交换两个值的位置flag = 0;swap((char*)pa + j * width, (char*)pa + (j + 1) * width, width);}}if (1 == flag){break;}}
}

        到这里,这个函数我已经基本写好了,最后再写一个打印函数就完成了。 

        现在我们将意识转换为小美。我现在知道了小帅写的 bubble_sort 函数的规则,首先我需要准备好我想排序的一组数据到数组中,再调用小帅写的 bubble_sort 函数将数组首元素的地址、数组元素个数、元素大小宽度、自定义的比较函数地址等作为参数,最后调用打印函数即可。那我需要写的代码就是下面这些:

int cmp_int(const void* a, const void* b)
{int arg1 = *(int*)a;int arg2 = *(int*)b;return (arg1 > arg2) - (arg1 < arg2);
}int main()
{int arr[] = { 5,2,7,4,9,1,0,3,8,6 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print_int(arr, sz);
}

        到此,我们就完成了冒泡排序的改造,实现了一个类似于 qsort 函数的 bubble_sort 函数。为了区分函数的编写者和使用者,我们可以将 bubble_sort 函数的实现放在另一个文件中,在别人需要使用这个函数时只需要包含相应的头文件即可。

        另外,上面只是以整型类型的数据为例进行排序,最后我们再使用各种类型的数据对我们写的 bubble_sort 函数进行测试。

        sort.c

#define  _CRT_SECURE_NO_WARNINGS#include "sort.h"void swap(char* buf1, char* buf2, size_t width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}
}void bubble_sort(void *pa, size_t sz, size_t width, int (*cmp)(const void *a, const void *b))
{int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;int flag = 1;for (j = 0; j < sz - 1 - i; j++){//判断大小if (cmp((char*)pa + j * width, (char*)pa + (j + 1) * width) > 0){//交换两个值的位置flag = 0;swap((char*)pa + j * width, (char*)pa + (j + 1) * width, width);}}if (1 == flag){break;}}
}void print_int(int* pa, int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", *(pa + i));}
}

         sort.h

#pragma once#include <stdio.h>//排序
void bubble_sort(void* pa, size_t sz, size_t width, int (*cmp)(const void* a, const void* b));
//打印
void print_int(int* pa, int sz);

         main.c

#define  _CRT_SECURE_NO_WARNINGS#include "sort.h"int cmp_int(const void* a, const void* b)
{int arg1 = *(int*)a;int arg2 = *(int*)b;return (arg1 > arg2) - (arg1 < arg2);
}void text1()
{int arr[] = { 5,2,7,4,9,1,0,3,8,6 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print_int(arr, sz);
}int cmp_struct_name(const void* a, const void* b)
{return strcmp((*(struct people*)a).name, (*(struct people*)b).name);
}void text2()
{struct people p[] = { { "xiaoshuai", 25, 75.5 }, { "xiaomei", 24, 54.3 }, { "xiaochou", 23, 67.8 } };int sz = sizeof(p) / sizeof(p[0]);bubble_sort(p, sz, sizeof(p[0]), cmp_struct_name);int i = 0;for (i = 0; i < sz; i++){printf("%s ", (*(p + i)).name);}
}int cmp_struct_weight(const void* a, const void* b)
{double arg1 = (*(struct people*)a).weight;double arg2 = (*(struct people*)b).weight;return (arg1 > arg2) - (arg1 < arg2);
}void text3()
{struct people p[] = { { "xiaoshuai", 25, 75.5 }, { "xiaomei", 24, 54.3 }, { "xiaochou", 23, 67.8 } };int sz = sizeof(p) / sizeof(p[0]);bubble_sort(p, sz, sizeof(p[0]), cmp_struct_weight);int i = 0;for (i = 0; i < sz; i++){printf("%lf ", (*(p + i)).weight);}
}int cmp_struct_age(const void* a, const void* b)
{int arg1 = (*(struct people*)a).age;int arg2 = (*(struct people*)b).age;return (arg1 > arg2) - (arg1 < arg2);
}void text4()
{struct people p[] = { { "xiaoshuai", 25, 75.5 }, { "xiaomei", 24, 54.3 }, { "xiaochou", 23, 67.8 } };int sz = sizeof(p) / sizeof(p[0]);bubble_sort(p, sz, sizeof(p[0]), cmp_struct_age);int i = 0;for (i = 0; i < sz; i++){printf("%d ", (*(p + i)).age);}
}int main()
{//text1();/*text2();*//*text3();*//*text4();*/return 0;
}

        通过实验,我们改造的 bubble_sort 函数确实可以对任意类型的数据排序,并且排升序和降序都是可行的。 

         如果觉得我的文章还不错,请点赞、收藏 + 关注支持一下,我会持续更新更好的文章。

                                              点击跳转下一节 —> C语言(指针)9

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

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

相关文章

BUUCTF-misc23

[GUET-CTF2019]zips1 1.打开附件 是一个加密的压缩包 2.暴力破解压缩包 得到压缩包密码 3.010Editor 解密之后又得到一个加密的压缩包 发现不是解密文件 用010Editor打开是伪加密&#xff0c;将09 00 给为 00 00 4.Python 用Python运行文件里的部分内容&#xff0c;发现密…

高精度可编程直流电源功能

在电子产品开发和测试中&#xff0c;高精度可编程直流电源是一种非常重要的工具。它不仅能够提供稳定可靠的电源供应&#xff0c;还能够精确地控制输出电压和电流,满足各种复杂的测试需求。下面我们就来详细了解一下高精度可编程直流电源的功能特点。 1. 输出精度高 高精度可…

基于深度学习OCR文本识别

第一步&#xff1a;概要 基于深度学习OCR文本识别分为两个模块&#xff1a;DBNet和CRNN。 DBNet是基于分割的文本检测算法&#xff0c;算法将可微分二值化模块(Differentiable Binarization)引入了分割模型&#xff0c;使得模型能够通过自适应的阈值图进行二值化&#xff0c;并…

php发送短信功能(创蓝短信)

一、以下是创蓝发送短信的功能&#xff0c;可以直接执行&#xff1a; <?php$phone 12312312312;$msg 测试短信功能;echo 发送手机号&#xff1a;.$phone.<br/>;echo 发送内容&#xff1a;.$msg.<br/>;$send sendMessage($phone, $msg);var_dump($send);…

HQL面试题练习 —— 品牌营销活动天数

题目来源&#xff1a;小红书 目录 1 题目2 建表语句3 题解 1 题目 有营销活动记录表&#xff0c;记录了每个品牌每次营销活动的开始日期和营销活动的结束日期&#xff0c;现需要统计出每个品牌的总营销天数。 注意&#xff1a; 1:苹果第一行数据的营销结束日期比第二行数据的营…

sam代码简析

Segment Anything&#xff1a;建立了迄今为止最大的分割数据集&#xff0c;在1100万张图像上有超过1亿个掩码&#xff0c;模型的设计和训练是灵活的&#xff0c;其重要的特点是Zero-shot(零样本迁移性)转移到新的图像分布和任务&#xff0c;一个图像分割新的任务、模型和数据集…

记录centos中操作(查找、结束、批量)进程以及crontab定时写法的知识

环境&#xff1a;vps&#xff0c;centos7&#xff0c;python3。 近期写了个python程序&#xff0c;用青龙面板在centos上运行。程序中有while无限循环&#xff0c;但是我在青龙中设置了定时任务&#xff08;每隔半小时运行一次&#xff09;&#xff0c;于是造成了进程中有多个…

Java进阶16 单元测试XML注解

Java进阶16 一、单元测试 单元测试就是针对最小的功能单元编写测试代码&#xff0c;Java程序最小的功能单元是方法&#xff0c;因此&#xff0c;单原测试就是针对Java方法的测试&#xff0c;进而检查方法的正确性。简单理解就是测试代码的工具。 1、Junit 1.1 Junit引入 目…

全面了解CC攻击和防范策略

前言 “ CC攻击的原理就是攻击者控制某些主机不停地发大量数据包给对方服务器造成服务器资源耗尽&#xff0c;一直到宕机崩溃。” 什么是CC攻击&#xff1f; CC攻击前身是一个名为Fatboy的攻击程序&#xff0c;而之所以后来人们会称之为CC&#xff0c;也叫HTTP-FLOOD&#xff…

程序语言基础知识

文章目录 1.程序设计语言2. 程序设计语言的特点和分类3. 编译程序&#xff08;编译器&#xff09;的工作原理4. 程序语言的数据成分4.1 数据成分4.2 运算成分4.3 控制成分4.4 传输成分 1.程序设计语言 低级语言&#xff1a;机器语言和汇编语言。 机器语言&#xff1a;二进制代…

Java面向对象-常用类 (包装类)

常用类 – 包装类 基本数据类型的包装类 理解&#xff1a;包装类是8种基本数据类型对应的类 出现原因&#xff1a;Java是一种纯面向对象语言&#xff0c;但是java中有8种基本数据类型&#xff0c;破坏了java为纯面向对象的特征。为了承诺在java中一切皆对象&#xff0c;java…

c/c++ 判断质数(素数)

目录 一.常规方法 二.进阶方法 三.代码示例&#xff08;运用进阶方法&#xff09; 质数是整数且仅能被自身和1整除 一.常规方法 所以我们根据质数的这个定义便可用以下思路判断&#xff1a;设需要检测的数为x。y为除1和自己的除数 逐步检测x是否可被y整除&#xff0c;如x…

MySQL之架构设计与历史(一)

架构设计与历史 概述 和其他数据库系统相比&#xff0c;MySQL有点与众不同&#xff0c;它的架构可以在多种不同场景中应用并发挥好的作用&#xff0c;但同时也会带来一点选择上的困难。MySQL并不完美&#xff0c;却足够灵活&#xff0c;能够适应高要求的环境&#xff0c;例如…

Android 逆向学习【1】——版本/体系结构/代码学习

#Android 历史版本 参考链接&#xff1a;一篇文章让你了解Android各个版本的历程 - 知乎 (zhihu.com) 三个部分&#xff1a;api等级、版本号、代号&#xff08;这三个东西都是指的同一个系统&#xff09; API等级&#xff1a;在APP开发的时候写在清单列表里面的 版本号&…

Vitis HLS 学习笔记--控制驱动TLP - Dataflow视图

目录 1. 简介 2. 功能特性 2.1 Dataflow Viewer 的功能 2.2 Dataflow 和 Pipeline 的区别 3. 具体演示 4. 总结 1. 简介 Dataflow视图&#xff0c;即数据流查看器。 DATAFLOW优化属于一种动态优化过程&#xff0c;其完整性依赖于与RTL协同仿真的完成。因此&#xff0c;…

力扣第206题-反转链表

反转链表的效果示意图 要改变链表结构时&#xff0c;通常加入一个创建的临时头结点会更容易操作 时间复杂度&#xff1a;遍历2遍&#xff0c;2n 空间复杂度&#xff1a;额外创建一个栈&#xff0c;n (空间创建一个数组长度最大为5000&#xff0c;你说这个数组是栈也可以&…

【C++】详解多态

目录 初识多态 多态的条件 接口继承和实现继承 override 和 final 多态原理 继承与虚函数表 析构函数与多态 抽象类 本篇内容关联知识的链接 【C】详解C的继承-CSDN博客 【C】详解C的模板-CSDN博客 【C】C的内存管理-CSDN博客 初识多态 父类被不同子类继承后&#…

报名开启!2024 开源之夏丨Serverless Devs 课题已上线!

Serverless 是近年来云计算领域热门话题&#xff0c;凭借极致弹性、按量付费、降本提效等众多优势受到很多人的追捧&#xff0c;各云厂商也在不断地布局 Serverless 领域。 Serverless Devs 是一个由阿里巴巴发起的 Serverless 领域的开源项目&#xff0c;其目的是要和开发者们…

leetcode以及牛客网单链表相关的题、移除链表元素、链表的中间节点、合并两个有序链表、反转链表、链表分割、倒数第k个节点等的介绍

文章目录 前言一、移除链表元素二、链表的中间节点三、合并两个有序链表四、反转链表五、链表分割六、倒数第k个节点总结 前言 leetcode以及牛客网单链表相关的题、移除链表元素、链表的中间节点、合并两个有序链表、反转链表、链表分割、倒数第k个节点等的介绍 一、移除链表元…

扫盲:如何提升医学图像分割性能-to do list

导读&#xff1a;本文主要讨论了如何改进图像分割项目中的分割性能&#xff0c;包括一般性和具体性的问题解决方案&#xff0c;以及如何通过调整模型参数、改善数据集质量、优化模型架构、调整超参数、增加训练时长、改善图像分辨率和后处理技术等方法来提高分割效果。 图像分…