数据结构排序篇上

排序的概念及其运用

排序的概念

排序 :所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性 :假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次
序保持不变,即在原序列中, r[i]=r[j] ,且 r[i] r[j] 之前,而在排序后的序列中, r[i] 仍在 r[j] 之前,则称这种排
序算法是稳定的;否则称为不稳定的。
内部排序 :数据元素全部放在内存中的排序。
外部排序 :数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

排序的运用 

 

 常见的排序

 插入排序:直接插入排序

先写直接插入排序。

直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为 止,得到一个新的有序序列
实际中我们玩扑克牌时,就用了插入排序的思想

一下子写排序是不可取的,排序这个部分,先写单趟,后写整体。

就比如说,我有0~end个数据的下标,我想把该数组外的end+1下标的值插入到现有数据。end在哪里我不清楚,这里只是假设,这里单趟的核心思想就是把一个数往前面的有序区间插入。这里的0~end肯定是有序的。注意注意,这里的end是什么我们并不知道。

这里已经有一个有序区间了。然后我把后一个值往前面插入。

2比5小,所以5得往后挪动,但是一挪动就会覆盖2,所以得先把2存起来。将2保存在一个变量中。比5小挪动,end减减,比3小挪动,end减减,比1大,就放到1的后面。假如要插入的不是2了,而是0,那我还是比1小,1往后挪动,我end减减,然后把0插入在end的后面,所以结束条件为end=-1;

总结:无论哪一种情况,都是放在end的后面。

//单趟插入排序
void InsertSort(int* a, int n)
{int end=0;int tmp = a[end + 1];while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];--end;}else{break;}}//这里切记end要加1,否则会出问题,因为我们之前移动后,立马end减去1了。a[end + 1] = tmp;
}

上图是完成了一趟了

这个循环有两个出去的条件,一个是你比end对应的值大于或者等于就break跳出,还有end小于0就结束,就是所有的值都比你目标值大,就一直挪动,挪到end等于-1,就将目标值插入到end的后面。这就是一趟走的整体思路。

完成了一趟的数据后,我们就开始写次数来完善程序。

这里我们把end给为0,就想当然把0当成有序,然后继续来走。

所以给的end的其实位置就是0.所以在循环里,这里就给i。

end为0时,即第一个数据有序,end后的数据开始插入,以此类推。

end的结束位置在数组最后位置的前一个。即有n个数据,那么最后一个数据的下标为n-1,再往前就是n-2;

因为这里要经常打印数组,所以这里就写一个相应的函数。

void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}

分析时间复杂度

写代码时,要对其的思路逻辑清楚一点,否则会出现问题。

一定要学会单趟套整体。

这个直接插入排序的时间复杂度为多少?千万不要说两层循环n的平方。简单排序看层数是没问题的。但是排序这里看循环层数来判断n的平方是不对的。判断时间复杂度要看思想。

这个直接插入排序,逆序的时候,时间复杂度是最坏的。就是第一个数有序,第二个数插入一次,第三个数两次,就是等差数列。就是得全部挪动一遍。所以也就是1~n-1,也就是n的平方。

呃呃呃,虽然这个程序是n的平方,但是切记看思想来判断。

这是最坏情况,我们再看一下最好情况,即顺序。就是0(n),就是遍历了一遍。或者说接近有序,这个最好情况再顺序有序或者接近有序时成立。

为什么最好是0(n)呢?就是我给你一个数组,你是不知道他是是否有序的。你不知道他是否有序。没有排序可以做到0(1),最快的排序就是接近0(n)的。当然在一些比较局限的场景里可以做到0(n)。常见的排序n*log(n)就是最好的了。

交换排序:冒泡排序

体现素养的小细节:

写个冒泡,呜呜,遇到友人了。

BubbleSort.(命名要规范,否则面试出大问题)。

规范:代码里面不要有拼音,除非没有对应的单词。这个关乎面试官对你的代码素养。

冒泡排序 是一种交换思想,如果前一个大于后一个就交换,这样以来,一轮之后,最大的值就到最后了。然后再前一个根后一个交换,把次大的值换到倒数第二个位置了。

我们还按照先写单趟,再写整体。

这里先写一个交换函数,因为之后可以复用。

//单趟冒泡排序
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void BubbleSort(int* a, int n)
{for (int i = 1; i < n; i++){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);}}
}

代码比的是细节。要控制住细节。如果你觉得细节控制的不是太好,那一定是画图画少了。

这里for循环条件也可以给i为0,这样接得写i<n-1了,这样得控制尾部的结束条件了。当然,怎么写都是可以的。

我们这样写的就是一前一后进行交换。

到这里第一次记冒好了,第一次就确定了最大值,所以第二趟就冒到n-1就行了。当<1时,冒泡就结束。所以一共冒泡n-1次就行。

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void BubbleSort(int* a, int n)
{for (int j = 0; j < n - 1; j++){for (int i = 1; i < n; i++){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);}}}
}

 这里第一层次数循环是到n-2结束,第二层for循环进行每一次需要的趟数到小于n-(n-2)结束,即小于2就结束,也就是到1,我们分析就是到1就继续,正好0和1那里比较了,然后就结束,思路是这样的。

到这里,冒泡就写好了,但是其实还是可以优化的。

冒泡空间有可优化的空间,就是顺序可能或者基本有序,就不冒一趟没有发现数据交换,就不用再继续走了,这里给个标志。

void BubbleSort(int* a, int n)
{for (int j = 0; j < n - 1; j++){int exchange = 0;for (int i = 1; i < n; i++){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

冒泡排序的时间复杂度是n的平方。这个时候的最坏的情况不是说逆序了,逆序只是其中一种情况,不一定是逆序,很多情况都是n的平方。最好的顺序就是接近有序从而达到0(n)。

它和插入排序看起来没什么区别,但其实不一样。

冒泡排序的特性总结:
1. 冒泡排序是一种非常容易理解的排序
2. 时间复杂度: O(N^2)
3. 空间复杂度: O(1)
4. 稳定性:稳定

 对比直接插入排序和冒泡排序

// 测试排序的性能对比
void TestOP()
{srand(time(0));//开100000个空间const int N = 100000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);int* a6 = (int*)malloc(sizeof(int) * N);//每个数组放一样的数for (int i = 0; i < N; ++i){a1[i] = rand();a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];}//计算时间int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();BubbleSort(a2, N);int end2 = clock();/*int begin3 = clock();SelectSort(a3, N);int end3 = clock();int begin4 = clock();HeapSort(a4, N);int end4 = clock();int begin5 = clock();QuickSort(a5, 0, N - 1);int end5 = clock();int begin6 = clock();MergeSort(a6, N);int end6 = clock();*/printf("InsertSort:%d\n", end1 - begin1);printf("BubbleSort:%d\n", end2 - begin2);/*printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);*/free(a1);free(a2);/*free(a3);free(a4);free(a5);free(a6);*/
}
int main()
{/*int a[] = { 5,4,3,2,1 };BubbleSort(a, sizeof(a) / sizeof(a[0]));PrintArray(a, sizeof(a) / sizeof(a[0]));*/TestOP();return 0;
}

malloc个多个数组,产生一个随机值。然后将数组1赋值给别的数组,就是说这6个数组的值都是一样的。 

这里begin减去end就是排序所消耗的时间。

clock是电脑运行启动到调用这个函数是所消耗的毫秒数,所以两个clock之差就是中间的排序消耗掉的时间。

这里进行测试时,debug可能优化没有全开,测性能用release。

下图是realease的。

跑十万个值进行的比较。

所以明显的感觉到这两个不一样。不能单看时间复杂度来看这里的问题。

时间复杂度用来算他是属于哪一个量级的。这两个属于同一个档次的排序。同一个学校,是统一档次,但出来的不同同学有不同。

所以不能单一时间复杂度来评估。

选择排序:堆排序

堆排序 (Heapsort) 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是
通过堆来进行选择数据。 需要注意的是排升序要建大堆,排降序建小堆。

 

 

直接选择排序的特性总结:
1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度: O(N*logN)
3. 空间复杂度: O(1)
4. 稳定性:不稳定

 

void HeapSort(int* a, int n)
{//a数组直接建堆 0(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}//O(N*logN)int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);printf("%d ", a[end]);--end;}printf("%d", a[0]);
}
int main()
{int a[] = { 5,4,3,2,1 };HeapSort(a, sizeof(a) / sizeof(a[0]));//PrintArray(a, sizeof(a) / sizeof(a[0]));//TestOP();return 0;
}

 

排序和排序直接真的有差距啊。

插入和冒泡属于同一类,但效率差很多的重要的点在,插入具有很强的适应性。

冒泡不再冒的条件是很苛刻的,就是不能有任何一个交换,没有一个条件交换,就是已经有序了,这个条件是很难达成的。

插入的适应性在哪里呢?只要由一个靠后的数据比前面数据都小,那就挪动n次。但是这是非常极端的,一般来说这个数据可能在偏中间一点的位置,即只挪动了一半的数据就达到了目的。

 

这个堆冒泡是常态,但对于插入排序来说,他只要每个数据都要挪满时才会出现这种情况。但是对插入排序来说,他的中间或许可能会局部有序,他不需要;一直挪。随机的场景更多的是局部有序。

时间复杂度不在同一个量级就没有可比性,在同一个量级的也有差异。冒泡在随机数是都是比满。

插入排序:希尔排序

 

希尔觉得插入排序非常的不错,如果有序接近有序,插入有序就非常nb了。它要改革直接插入排序。如果能把数据接近有序,那就很快乐。

所以他分为两个步骤:

预排序 目标:接近有序;

他觉得你挪动的太慢了。它想让挪动的快一些。也就是分组插入排序。目标:大的更快换到后面的位置,小的数更快换到前面的位置。

就是以gap为间距来一一分组。

希尔排序法又称缩小增量法。希尔排序法的基本思想是: 先选定一个整数,把待排序文件中所有记录分成个
组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工
作。当到达 =1 时,所有记录在统一组内排好序

 

希尔排序的特性总结:
1. 希尔排序是对直接插入排序的优化。
2. gap > 1 时都是预排序,目的是让数组更接近于有序。当 gap == 1 时,数组已经接近有序的了,这样就 会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
3. 希尔排序的时间复杂度不好计算,因为 gap 的取值方法很多,导致很难去计算,因此在好些树中给出的 希尔排序的时间复杂度都不固定

 《数据结构(C语言版)--- 严蔚敏

 《数据结构-用面相对象方法与C++描述》--- 殷人昆

稳定性:不稳定

 

预排序和原数组相比: 

 

他有序了一点,但不是很多。

我们先写单趟。

我们接下来以下图这个数组为例开始排

 

//单次希尔排序
void ShellSort(int* a, int n)
{int gap = 3;int end=0;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;
}

比完5和2了,然后比5和3时,不是上述代码,写的,得先在上图再套一层才能写,这里先继续写。

这里跟插入排序很像,无非就是将加1换成了加gap。

刚才完成的只是把一个数往前插入,如果我们要排一组数据,那么该如何排。

 for(int i=0;i<n;i+=gap)

 上图这里再套一层循环。但是这里有问题,如果i等于在5的位置时(即进行了交换之后),再加上gap来进入循环,这个时候就越界了。

所以外层循环应该写为上图:

这个时候就帮助我们帮红色这一组就排完了,但是我们想排整体,该如何呢?间距为gap,就有gap组。gap是几就有几组。所以再次套一层循环。

//一个gap进行的希尔排序
void ShellSort(int* a, int n)
{int gap = 3;for (int i = 0; i < n-gap; i += gap){int end=i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}
}

所以外层循环应该写为上图:

这个时候就帮助我们帮红色这一组就排完了,但是我们想排整体,该如何呢?间距为gap,就有gap组。gap是几就有几组。所以再次套一层循环。

//完整的希尔排序
void ShellSort(int* a, int n)
{int gap = 3;for (int j = 0; j < gap; j++){for (int i = 0; i < n - gap; i += gap){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

总结一下:希尔排序分为预排序他的目的是分组插入排序

预排序的目标是:大的更快换到后面的位置,小的数更快换到前面的位置。

到这里,其实上图完整的希尔排序也可以简化为2层。

void ShellSort(int* a, int n)
{int gap = 3;/*for (int j = 0; j < gap; j++){for (int i = 0; i < n - gap; i += gap){*/for (int i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}/*	}}*/
}

希尔排序是初始的是什么呢,是一组排完排另一组。是排完红色,再排绿色,再排紫色。

一组一组排。

但是按照上图来说,先比较换了2和5,然后不一整组一整组比较,而是最外层的i++。这个方法是gap组数据,交替完成分组插入排序。

gap大于1就是预排,等于1就是快速排序。gap越大,数据跳的越快,大的更快到前面为止,小的更快到后面,但是越不接近有序。

gap越小,数据跳的越慢,但是越接近有序,gap==1就是插入后就是有序。

 

继续深入;

这里还有人怎么给呢?到这里就已经变为怎么给gap了。

 这样就能控制gap了,我第一次间距给上50,gap大不接近有序,没关系啊,我gap在缩小,我除以2最后一趟一定是1.

 

这里希尔排序每一组都在接近有序。

呜呜呜呜,开始这个排序让你爱答不理,最后让我高攀不起。呜呜呜呜!

 

有人觉得除3更好,但是除3不能保证最后余数为1.
代码能力是练出来的。需要消化的数据才是有含量的。

若有收获,就点个赞吧

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

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

相关文章

面向电力行业定制安全云工作站解决方案,麒麟信安出席2024年电力企业信创替代技术研讨会

日前&#xff0c;由中国电子企业协会主办的“2024年电力企业信创替代技术研讨会”在江苏南京正式召开。会议以国家推进实现自主可控、加快建设“数字中国”为大背景&#xff0c;聚焦电力企业紧抓“信创替代”机遇&#xff0c;通过安全可靠的软硬件迭代升级&#xff0c;实现企业…

android studio 网络请求okhttp3、okgo

一、在build.gradle文件里添加 implementation com.squareup.okhttp3:okhttp:4.9.0 implementation com.squareup.okhttp3:okhttp:3.12.0 implementation com.squareup.okio:okio:1.17.4 implementation com.lzy.net:okgo:3.0.4 implementation com.alibaba:fastjson:1.2.57 i…

ssm046人事管理信息系统+jsp

人事管理信息系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本人事管理信息系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

软考高级架构师:存储管理-页式存储真题解析

背景知识 题目 进程P有8个页面&#xff0c;页号分别为0&#xff5e;7&#xff0c;页面大小为4K &#xff0c;假设系统给进程P分配了4个存储块&#xff0c;进程P的页面变换表如下所示。表中状态位等于1和0分别表示页面在内存和不在内存。若进程P要访问的逻辑地址为十六进制 514…

QThread的学习

锁住该线程直到下面的情况之一出现&#xff1a; (1)和该线程连接的对象已经执行完成&#xff08;例如&#xff1a;当它从run()中返回时&#xff09; 如果该线程已经结束&#xff0c;该函数将返回true。 如果该线程还没有开始&#xff0c;它也返回true。 (2)time毫秒已经过去。如…

嵌入式面试的中的一些潜规则

潜规则1:面试的本质不是考试,而是告诉面试官你会做什么 经验不够的小伙伴特别容易犯的一个错误,不清楚面试官到底想问什么,其实整个面试中面试官并没有想难倒你的意思,只是想通过提问的方式来知道你会什么。 比如stm32单片机的启动过程是怎样的? 没入门的说从main函数…

Windows系统LibRadtran安装

Windows系统LibRadtran安装 1.简介1.1官网下载1.2依赖环境1.3 Cygwin64 介绍及安装 2.安装2.1安装依赖的环境2.2编译 3.可能遇到的错误3.1 错误13.2 错误2 4.使用教程 1.简介 LibRadtran&#xff08;Library for Radiative Transfer&#xff09;是一个用于计算太阳和热辐射在大…

单列模式1.0

单列模式 单例模式能保证某个类在程序中只存在唯⼀⼀份实例, ⽽不会创建出多个实例 1.饿汉模式 只要程序一启动就会立即创建出一个对象 class Signleton{private static Signleton instancenew Signleton();//防止在以后的代码中再创建对象&#xff0c;我们将构造方法private,…

【MIT6.S081】Lab3: page tables(详细解答版)

实验内容网址&#xff1a;https://xv6.dgs.zone/labs/requirements/lab3.html 本实验的代码分支&#xff1a;https://gitee.com/dragonlalala/xv6-labs-2020/tree/pgtbl2/ Print a page table 关键点&#xff1a;递归、三级页表 思路&#xff1a; 用上图来解释三级页表的原理最…

【windows 】taskkill命令

在Windows操作系统中&#xff0c;并没有直接称为“kill”的命令来终止进程&#xff0c;但是你可以使用“taskkill”命令或者通过任务管理器来实现类似的功能。 “taskkill”是一个强大的命令行工具&#xff0c;可以用来终止一个或多个任务或进程。以下是一些常用的“taskkill”…

智能电网将科技拓展至工厂之外的领域

【摘要/前言】 物联网已然颠覆我们日常生活的许多层面。在家居方面&#xff0c;家电变成连网设备&#xff0c;不仅让我们能控制灯光与上网购物&#xff0c;甚至在出门时提供安全功能。在工业领域&#xff0c;智能工厂改变产品制造的方式。工业物联网(IIoT)不仅让制造商更加敏捷…

Spring Boot 学习(5)——开发流程:快速入门

花了几天的时间&#xff0c;整出个 “hello spring boot”&#xff0c;并且把它从 2 搞到了 3。 纸上得来终觉浅&#xff01;自己实践出真知&#xff01;现在再回头来囫囵一遍&#xff0c;加深下印象。回想下从前自觉某一编程语言大都如此&#xff0c;先找到简单示例照着画一遍…

【vue3-pbstar-books】大学生前端期末作业(vue3、element-plus、ts、pinia、vite、json-server)

一、项目要求 二、项目介绍 vue3-pbstar-books是一个图书主题的pc端网站&#xff0c;该项目有首页、全部书籍页、书籍分类页、书籍详情页和关于页五个页面。该方案结合了 Vue3、Element-Plus、TypeScript、Pinia 和 Vite 等先进技术&#xff0c;实现高效的页面布局、状态管理和…

Spring之AOP的详细讲解

目录 一.SpringAOP是什么&#xff1f; 1.1理论知识点 1.2简单的AOP例子 二.SpringAOP的核心概念 2.1切点(Pointcut) 2.2通知&#xff08;Advice&#xff09; 2.3切⾯(Aspect) 2.4通知类型 2.5切⾯优先级 Order 2.6切点表达式 2.6.1 execution表达式 2.6.2annotati…

天地人和•大道不孤——卢禹舜中国画作品展在重庆美术馆隆重开幕

2024年4月12日&#xff0c;由中国国家画院、重庆市文化和旅游发展委员会主办&#xff0c;重庆美术馆&#xff08;重庆画院、重庆国画院&#xff09;、北京八荒锦绣美术馆、中国国际文化交流基金会卢禹舜艺术基金承办的“天地人和•大道不孤——卢禹舜中国画作品展”开幕式在重庆…

jmeter实验 模拟:从CSV数据到加密请求到解密返回数据再到跨越线程组访问解密后的数据

注意,本实验所说的加密只是模拟加密解密,您需要届时写自己的加解密算法或者引用含有加密算法的相关jar包才行. 思路: 线程组1: 1.从CSV文件读取原始数据 2.将读取到的数据用BeanShell预习处理器进行加密 3.HTTP提取器使用加密后的数据发起请求 4.使用BeanShell后置处理器…

底层文件操作的各种函数(二)------printf,fprintf,sprintf,scanf,fscanf,sscanf的对比以及文件缓冲区

偷得几日清闲&#xff0c;又因一瞬之间对蹉跎时间的愧疚&#xff0c;由此而来到CSDN这个高手云集和新手求学的平台来也写上那么一篇博客。虽然自己的博客那么久不温不热&#xff0c;但坚持写作&#xff0c;巩固自己就好。今天要讲的是续接上一篇文章的补充与继续吧。上期文章&a…

MQ:延迟队列

6.1场景&#xff1a; 1.定时发布文章 2.秒杀之后&#xff0c;给30分钟时间进行支付&#xff0c;如果30分钟后&#xff0c;没有支付&#xff0c;订单取消。 3.预约餐厅&#xff0c;提前半个小时发短信通知用户。 A -> 13:00 17:00 16:30 延迟时间&#xff1a; 7*30 * 60 *…

GB/T 28181标准中的错误码,国标28181中可能出现的SIP协议相关的错误码及其含义

目录 一、GB/T 28181标准介绍 &#xff08;一&#xff09;概述 &#xff08;二&#xff09;关键内容和特点 1. 系统架构&#xff1a; 2. 设备接入&#xff1a; 3. 网络通信&#xff1a; 4. 业务功能&#xff1a; 5. 安全保护&#xff1a; 6. 平台管理&#xff1a; &a…

【C语言】字符串函数和内存函数及其模拟实现

文章目录 前言 一、常见字符串库函数1.strlen函数2.长度不受限制的字符串函数2.1 strcpy2.2 strcat2.3 strcmp 3.长度受限制的字符串函数3.1 strncpy3.2 strncat3.3 strncmp 二、字符串查找函数strstrstrtok 三、strerror函数四、内存操作函数1.memcpy2.memmove3.memcmp 五、字…