【C语言】——指针六:冒泡排序与qsort函数的实现

【C语言】——指针六:冒泡排序与qsort函数

一、冒泡排序

1.1、冒泡排序的原理

  
  在实践过程中,我们难免会碰到要给一组数据排序的情况。如果我们掌握一些排序的算法,效率就会高很多。排序的方法有方法有很多,如:希尔排序,快速排序,堆排序……,今天,我们讲的排序方法就是——冒泡排序
  
  冒泡排序的原理是什么呢?
  
  他的核心就是相邻两元素两两比较
  
这里,我们以大小为 10 的数组从小到大排序为例,详细讲解冒泡排序的原理:

  • 首先,我们将首元素与数组第二个元素相比较,若首元素,则两两换位,否则不进行任何操作。
      
  • 接着,我们将第二个元素第三个元素相比较,若第二个元素比第三个元素,则两数交换,否则不变。
      
  • 接下来,依次往后,第三与第四,第四与第五……不断按顺序进行两两比较,符合条件,则两两换位,直到将位置最后两个元素比较完.
      
  • 10 元素的数组要比较 10 - 1= 9 组。若前一个元素,则交换两数位置,否则无事发生(若是从大到小排序,则反之) 这样,一趟冒泡排序就完成啦。
      
      

在这里插入图片描述

  不难发现,一趟冒泡排序后,最大的那个元素排到了最后面,即完成第一个数的排序
  

  
  接下来则进行第二趟排序,与第一趟基本一样,不同的是,因为最后一个元素已经排好了,因此最后一个元素不用比较少比较一组
  
  在这里插入图片描述
  
  可以看到,第二大的数也排好了。
  

  
  以此类推,不断进行下一冒泡排序,每一趟排序都能让未排序的数中,最大的那个数归位,
  
  同时每次冒泡排序较之上一趟少比较一组,直到某一趟排序没有进行任何比较,排序结束
  
  在这里插入图片描述

  

  冒泡排序的过程就像气泡在水中不断上升的,较大(或较小)的元素不断像气泡一样浮到数组的顶端,因此该排序叫冒泡排序。

  
  

1.2、用代码实现冒泡排序

  
  好啦,现在我们知道了冒泡排序的原理,便可以上手进行代码实践了,试试将一个无序数组从小到大排序吧
  
参考代码:

#include<stdio.h>

int* bubble(int* arr, int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	return arr;
}

int main()
{
	int arr[] = { 6,4,1,2,9,3,7,8,10,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble(arr, sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
	printf("\n");
	return 0;
}

  上面代码基本实现了冒泡排序的功能,但有点缺陷
  
  大家不妨想一想,如果给的数据较为有序,可能只进行一两趟排序即可完成,可上面的代码一定要进行完整的冒泡排序,是不是太过繁琐
  
  这时,我们可以在每一次排序后进行判断,如果该次排序完后已经完成目标,则退出排序。
  
  在代码的实现中,我们可以设变量flag,当其为 1 表示排序完成,当一趟排序进行交换元素的操作,则将 f l a g flag flag 置为 0,程序继续运行。若一趟循环结束后, f l a g flag flag 还是 1 ,则表示排序已完成。
  
参考代码:

int* bubble(int* arr, int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int flag = 1;//假设这一趟已经有序了
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
				flag = 0;
			}
		}
		if (1 == flag)
		{
			break;
		}
	}
	return arr;
}

  
  

二、qsort函数

2.1、qsort函数的定义

  
  下面,我们学习一个新的函数: q s o r t qsort qsort 函数1
  
   q s o r t qsort qsort 函数的功能是对 任意类型 的数据进行排序,它是怎么做到的呢?
  
  首先,让我们一起来看看他的定义:

在这里插入图片描述

图片来源:cplusplus.com
  
  
参数讲解:
  
(1) v o i d ∗ b a s e void* base voidbase

这里是引用
  
  翻译:指向数组中要排序的第一个对象的指针,转换为 v o i d void void
  
  第一个参数 b a s e base base 其实就是传递待排序数组的首元素地址,它的类型是 v o i d void void * .为什么是 v o i d void void* 呢?因为 q s o r t qsort qsort 函数要排序的是==任意类型的数据,它事先并不知道你要传递给它的数据类型==,因此这里用 v o i d void void* 指针,以便能接受所有类型的数据
  

  
(2) s i z e size size_ t t t n u m num num

在这里插入图片描述
  
  翻译:基数指向的数组中元素的个数 s i z e size size_ t t t 是一个无符号整型。
  
   第二个参数 n u m num num 其实就是待排序数组的元素个数,因为元素个数肯定是正数,所以这里用 s i z e size size_ t t t 类型。
  

  

(3) s i z e size size_ t t t s i z e size size

在这里插入图片描述
  
  翻译:数组中每个元素的字节大小 s i z e size size_ t t t 是一个无符号整型。
  
  第三个参数 s i z e size size 指的是待排序数组中每个元素的大小,单位是字节。
  

  
(4) i n t int int ( * c o m p a r compar compar) ( c o n s t const const v o i d void void * ,  c o n s t const const v o i d void void )

  介绍之前,我们先来观察第四个元素 c o m p a r compar compar 的类型: i n t int int ( * c o m p a r compar compar) ( c o n s t const const v o i d void void * ,  c o n s t const const v o i d void void )。 没错,它是一个函数指针,也就是说我们要给它传递一个函数地址
  
  这是个怎样的函数呢?有什么要求呢?我们一起来看看。
  

在这里插入图片描述
  
  先来看看函数的参数类型: ( c o n s t (const (const v o i d ∗ p 1 void* p1 voidp1,   c o n s t const const v o i d ∗ p 2 ) void* p2) voidp2),它有两个参数,均为 c o n s t const const v o i d void void* 类型,返回类型是 i n t int int
  
  接着是这个函数的具体功能:它的功能是实现两个元素的比较

  • p1 < p2,返回 < 0 的数,
  • 相等,返回 0
  • p1 > p2,返回 > 0 的数。
      


  为什么要有这个参数呢,我们这里可以回顾一下上面的冒泡排序:

  在这里插入图片描述
  


  在内层循环中,该冒泡排序通过两两数相比较来决定是否换位,以实现最终排序,而arr[j] > arr[j + 1]是整型的比较方式。
  
  但是 q s o r t qsort qsort 函数需要实现的是任意类型的排序,而每一种类型的比较方式是不同的,一种类型一种写法。
  
   q s o r t qsort qsort 函数事先并不知道使用者要求用什么类型来排,怎么办呢?
  
   q s o r t qsort qsort 函数便让函数使用者自己写一个待排序类型的比较函数,然后将该函数地址传给 q s o r t qsort qsort q s o r t qsort qsort 内部再不断调用该函数进行比较,以达到排序的目的。

  同时,该函数仅仅是为了对两个数进行比较,并不会对两个数进行修改,因此前面加上 c o n s t const const 来修饰。
  

2.2、 qosrt函数的使用

  
  了解了 q s o r t qsort qsort 函数后,让我们一起练习它的使用吧。
  

(1)比较函数的写法

  
  我们已经知道要使用 q o s r t qosrt qosrt 函数,需传递一个比较函数的地址的,那这个比较函数怎么写呢?接下来,让我们试着来写一写这个比较函数吧。

在这里插入图片描述

  • 它的两个形参均为 c o n s t const const v o i d void void* 类型

  • 而返回类型为 i n t int int
       p1 > p2 返回 > 0 的数。
       p1 = p2 返回 0。
       p1 > p2 返回 < 0 的数。

下面我们来举几个例子吧
  
整型比较:

int cmp_int(const void* p1, const void* p2)
{
	return(*(int*)p1 - *(int*)p2);
}

注:运算前,要进行强制类型转换,因为 v o i d void void * 类型并不能进行解引用和 +- 整数的运算,应强制类型转换成要比较数据的类型,再进行相关运算。
  
结构体数据比较(按字符串比较):

typedef struct stu 
{
	char name[20];
	int age;
}stu;

int cmp_stu_name(const void* p1, const void* p2)
{
	return strcmp(((stu*)p1)->name,((stu*)p2)->name);
}

注:有关 t y p e d e f typedef typedef 关键字的用法详情请看【C语言】——指针四:字符指针与函数指针变量。
注: s t r c m p strcmp strcmp 函数是专门用来比较字符串大小的函数,在之后的学习中我们会进一步认识他。
  

(2)使用 q s o r t qsort qsort 函数

  
下面,一起来尝试使用 q s o r t qsort qsort 函数来排序吧
  
整型数组排序:

#include<stdio.h>

int cmp_int(const void* p1, const void* p2)
{
	return(*(int*)p1 - *(int*)p2);
}
int main()
{
	int arr[] = { 6,4,1,2,9,3,7,8,10,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
	printf("\n");
	
	return 0;
}

  
运行结果:
在这里插入图片描述
  
结构体排序(按字符串):

#include<stdio.h>

int cmp_stu_name(const void* p1, const void* p2)
{
	return strcmp(((stu*)p1)->name,((stu*)p2)->name);
}


int main()
{
	stu s[] = {{"zhangsan",19},{"lisi",18},{"wangwu",20}};
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(&s, sz, sizeof(s[0]), cmp_stu_name);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d\n", s[i].name, s[i].age);
	}
	return 0;
}

  
运行结果:
在这里插入图片描述
  

2.3、用冒泡排序模拟实现 q s o r t qsort qsort 函数

  
  了解了冒泡排序和 q s o r t qsort qsort 函数,接下来,我们来实现用冒泡排序来模拟实现 q s o r t qsort qsort 函数。

(1)函数声明

  
  首先,一个函数声明最重要的就是函数名参数类型返回类型。既然是模仿,我们就要模仿的像,因此,这部分我们可以直接照着官方的函数声明来。
  

void my_qsort(void* base, size_t num, size_t size, int(*compar)(const void*, const void*))

  

(2)函数基本骨架

  
  我们是用冒泡排序来实现 q s o r t qsort qsort 函数,那么我们就可以以上面冒泡排序排整型数组的代码为基础,想想哪些可以保留,那些应该去除。
  

int* bubble(int* arr, int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	return arr;
}

  
  既然是用冒泡排序实现 q s o r t qsort qsort 函数,那么有关冒泡排序核心思想的代码应该保留下来,而具体的实现方法,如:前后量元素比较大小、交换两元素,因为每种类型的具体实现方式不同,应该被替换掉。
  
  这样,我们函数的大体骨干就出来啦:

void my_qsort(void* base, size_t num, size_t size, int(*compar)(const void*, const void*))
{
	int i = 0;
	for (i = 0; i < num - 1; i++)
	{
		int flag = 1;
		int j = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
			if (/*比较两个元素的大小*/)
			{
				//交换两个元素
				//···
				
				flag = 0;
			}
		}
		if (1 == flag)
		{
			break;
		}
	}
}

  

(3)比较两个元素的大小

  
  比较两个元素的大小的方法前面已经介绍了,既然每一种类型的比较方式不同,那么 q s o r t qsort qsort 就让使用者自己写一个比较函数传进来。
  
  这里,我们来讲讲如何在 q s o r t qsort qsort 函数中使用比较函数

在这里插入图片描述

  通过比较函数的声明我们知道,它需要我们传递要比较的两个元素的地址,那这两个元素的地址怎么找呢?
  
  在《【C语言】—— 指针一 : 初识指针(上)》中,我们了解到,一种类型的变量,不论该类型大小是几个字节,进行取地址操作时,取出的是它所有字节中地址最小的字节的地址,即该元素的地址是其地址最小字节的地址那么我们只要想办法将数据中各个元素地址最小的字节的地址就好了
  
  开始时,我们传入的 b a s e base base 的地址是指向首元素的最低字节的地址,为 v o i d void void * 类型,怎么让他指向第二个元素呢?

  • 首先, v o i d void void * 类型指针不能进行 ± 整数的运算,我们先进行强制类型转换,因为 c h a r char char * 一次访问权限只有一个字节,所以将其转换成 c h a r char char * 指针,以方便后面的运算。
  • 那么转换成 c h a r char char* 后,又该跳过几个字节呢?别忘了,我们还有一个参数没用到: s i z e size size该元素类型大小为几个字节,我们指针就跳过多少个字节,这样就能指向下一个元素啦,即 c h a r char char*) b a s e base base + s i z e size size

  现在找第二个元素没问题了,那么想要找到第 j j j 个元素怎么办呢?找第 j j j 个元素,即将指针从起始位置跳过 j ∗ s i z e j * size jsize 个字节,即 ( ( c h a r ((char ((char * ) b a s e + j base + j base+j * s i z e ) size) size)

我们以整型数组为例:

在这里插入图片描述

  这样,我们就可以将需要比较的元素地址准确传给比较函数啦。
  
这里截取一小段:

for (j = 0; j < num - 1 - i; j++)
	{
		//比较两个元素的大小
		if (compar((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
		{
			//交换两个元素
			//···
				
			flag = 0;
		}
	}

  

(4)交换两个元素

  
  交换元素部分的代码我们可以直接像交换两个整型数据一样写吗?答案肯定是不可以的,原因还是一样,每一种类型都是不一样的。
  
  那么该怎么交换呢?我们可以 一个字节一个字节地逐一交换
  

在这里插入图片描述

  
  我们可以单独封装一个交换函数

void swap(char* p1, char* p2, size_t size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char temp = *(p1 + i);
		*(p1 + i) = *(p2 + i);
		*(p2 + i) = temp;
	}
}
  • p 1 p1 p1 p 2 p2 p2 为两个要交换元素的地址, s i z e size size 为需要交换的字节数。
  • 在传址时,两元素的传址方法与比较函数的传址方法相同,即 ( ( c h a r ((char ((char * ) b a s e + j base + j base+j * s i z e ) size) size)
  • 因为在传址时,传的已经是 c h a r char char* 类型的指针了,这里函数形参直接用 c h a r char char * 就行,不需要 v o i d void void * 再进行强制类型转换
      
      
(5)完整代码

  
  下面是冒泡排序模拟实现 q s o r t qsort qsort 函数的完整代码(以排序整型数组为例):

#include<stdio.h>

int cmp_int(const void* p1, const void* p2)
{
	return(*(int*)p1 - *(int*)p2);
}


void swap(char* p1, char* p2, size_t size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char temp = *(p1 + i);
		*(p1 + i) = *(p2 + i);
		*(p2 + i) = temp;
	}
}


void my_qsort(void* base, size_t num, size_t size, int(*compar)(const void*, const void*))
{
	int i = 0;
	for (i = 0; i < num - 1; i++)
	{
		int flag = 1;
		int j = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
			if (compar(((char*)base + j * size), ((char*)base + (j + 1) * size)) > 0)
			{	
				swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
				flag = 0;
			}
		}
		if (1 == flag)
		{
			break;
		}
	}
}


int main()
{
	int arr[] = { 6,4,1,2,9,3,7,8,10,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
	printf("\n");
	return 0;
}

  
  
  
  
  好啦,本期关于冒泡排序与 q s o r t qsort qsort函数就介绍到这里啦,希望本期博客能对你有所帮助,同时,如果有错误的地方请多多指正,让我们在C语言的学习路上一起进步!
  
  
  
  


  1. q s o r t qsort qsort 函数底层是使用快速排序来实现的,本文将以冒泡排序来模拟实现冒泡函数。 ↩︎

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

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

相关文章

Linux 常用命令(1)

&#x1f607;作者介绍&#xff1a;一个有梦想、有理想、有目标的&#xff0c;且渴望能够学有所成的追梦人。 &#x1f386;学习格言&#xff1a;不读书的人,思想就会停止。——狄德罗 ⛪️个人主页&#xff1a;进入博主主页 &#x1f5fc;专栏系列&#xff1a;Linux 随笔集合 …

NetCore3.1 Controller中直接返回JObject对象抛出异常解决方案

问题描述 在NetCore 3.1的Web项目中&#xff0c;Controller有一个方法直接返回JObject对象时&#xff0c;抛出了异常 S y s t e m . N o t S u p p o r t e d E x c e p t i o n : T h e c o l l e c t i o n t y p e ′ N e w t o n s o f t . J s o n . L i n q . J O b j …

2024/3/29 IOday2

所有人&#xff0c;今日作业&#xff1a;用fwrite 和 fseek功能&#xff0c;将一张bmp格式的图片更改成 德国国旗 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, const char *argv[]) {FILE* fpfopen("./rising_free…

<QT基础(4)>QLabel使用笔记

Label 前面的文章里面把QLabel批量引入ScrollArea作为预览窗口&#xff0c;这篇把图像填充到QLable的PixelMap展示指定图像。 参数设置 设置QLabel的大小格式 QWidget* widget new QWidget; widget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); widget->…

千川素材投放效果如何追踪:精准识别爆款、潜力、首发、优质素材

在数字营销和广告领域&#xff0c;素材投放的效果直接关乎广告的成功与否。为了在竞争激烈的市场中脱颖而出&#xff0c;广告主和广告从业者需要密切关注素材投放效果&#xff0c;并及时识别出不同类型的素材&#xff0c;如爆款、潜力、首发和优质素材。本文将详细探讨如何进行…

慧天【HTWATER】:水文水动力模型的革命性工具,城市内涝的精准解决方案

城市内涝水文水动力模型介绍 在城市排水防涝规划过程中&#xff0c;水文水动力耦合模型已经成为一种不可或缺的分析工具。在模型建立、城市内涝风险评估、排水系统性能诊断以及海绵城市规划等方面&#xff0c;内涝耦合模型提供了相应的模拟及分析工具&#xff1a; 1.1丰富的数…

Docker安装xxl-job并整合到SpringBoot项目

1. 创建数据库 执行如下SQL语句创建相关表 CREATE database if NOT EXISTS xxl_job default character set utf8mb4 collate utf8mb4_general_ci; use xxl_job;SET NAMES utf8mb4; CREATE TABLE xxl_job_info (id int(11) NOT NULL AUTO_INCREMENT,job_group int(11) NOT NUL…

分享几个以前画过的pcb,确实能看到进步

本文来自看海原创视频教程&#xff1a;《运放秘籍》运算放大器基础精讲及应用第一部*开天 微信公众号&#xff1a;工程师看海 【淘宝】https://m.tb.cn/h.5PAjLi7?tkvmMLW43KO7q CZ3457 「运放秘籍_运算放大器Multisim仿真视频教程第一部开天_工程师看海」 点击链接直接打开 …

【多线程系列】你先说说synchronized的实现原理

面试官&#xff1a;听说你精通多线程&#xff0c;那我就考考你吧 面试官&#xff1a;不用慌尽管说&#xff0c;错了也没关系&#x1f60a;。。。 以贴近现实的【面试官面试】形式来分享技术&#xff0c;本期是《多线程系列》&#xff0c;感兴趣就关注我吧❤️ 面试官&#xff1…

SpringBoot Redis的使用

官方文档&#xff1a; 官方文档&#xff1a;Spring Data Redis :: Spring Data Redis 和jedis一样&#xff0c;SpringBoot Redis 也可以让我在Java代码中使用redis&#xff0c;同样也是通过引入maven依赖的形式。 加速访问github: 使用steam可以免费加速访问github Spring…

第十四届蓝桥杯JavaA组省赛真题 - 特殊日期

解题思路&#xff1a; 暴力秒了 public class Main {public static void main(String[] args) {int cnt 0;for (int i 1900; i < 9999; i) {for (int j 1; j < 12; j) {for (int k 1; k < days(i, j); k) {if (sum(i) sum(j) sum(k)) cnt;}}}System.out.print…

【Flink】Flink 处理函数之基本处理函数(一)

1. 处理函数介绍 流处理API&#xff0c;无论是基本的转换、聚合、还是复杂的窗口操作&#xff0c;都是基于DataStream进行转换的&#xff0c;所以统称为DataStreamAPI&#xff0c;这是Flink编程的核心。 但其实Flink为了更强大的表现力和易用性&#xff0c;Flink本身提供了多…

Matlab与数学计算

原文地址&#xff1a;Matlab与数学计算 - Pleasure的博客 下面是正文内容&#xff1a; 前言 这是一篇笔记。主要用于介绍MatLab的作用以及其作为数学工具的使用方法。 目的是总结学校课件复习自用&#xff0c;但是不可能像相关的书籍那么系统全面&#xff0c;力求简单明了。都…

书生·浦语大模型全链路开源体系-第1课

书生浦语大模型全链路开源体系-第1课 书生浦语大模型全链路开源体系-第1课相关资源课程笔记技术报告笔记 书生浦语大模型全链路开源体系-第1课 为了推动大模型在更多行业落地应用&#xff0c;让开发人员更高效地学习大模型的开发与应用&#xff0c;上海人工智能实验室重磅推出书…

SD-WAN与边缘计算的结合:开启网络性能

随着数字化转型的加速和云计算技术的发展&#xff0c;企业对网络性能和可靠性的需求越来越高。SD-WAN&#xff08;软件定义广域网&#xff09;和边缘计算作为两项重要的技术趋势&#xff0c;在提高网络性能和效率方面发挥着至关重要的作用。本文将探讨SD-WAN与边缘计算的结合如…

linux使用GDB调试段错误

前因&#xff1a;由于在做线程邮箱项目的过程中&#xff0c;遇到了段错误&#xff0c;情况如下&#xff1a; 代码量达到了500多行&#xff0c;使用打印难以实现&#xff0c;试着用GDB调试段错误。 调试过程&#xff1a; 1、使用gcc ./a.out -g 使用加-g来生成调试文件core …

三菱Q系列PLC以太网TCP通讯FB块源码

三菱Q系列PLC的tcp通讯&#xff0c;客户端和服务器两个变量好用的FB块&#xff0c;调用块就可以实现通讯连接&#xff0c;不需要自己写程序&#xff0c;简单配置引脚就可以。该块还集成了断网&#xff0c;连接错误&#xff0c;发送接收数据错误报警等功能。具体功能见下面介绍.…

【linux】基础IO |文件操作符

需要掌握&#xff1a;操作文件&#xff0c;本质&#xff1a;进程操作文件。进程和文件的关系 向文件中写入&#xff0c;本质上向硬件中写入->用户没有权利直接写入->操作系统是硬件的管理者&#xff0c;我们可以通过操作系统往硬件写入->操作系统必须提供系统调用&…

JavaScript邂逅

文章目录 Javascript内容邂逅JavaScript前端的三大核心计算机语言认识编程语言常见的编程语言编程语言的发展历史–机器语言阶段一: 机器语言 编程语言的发展历史–汇编语言阶段二:汇编语言 汇编语言的发展历史–高级语言阶段三:高级语言 机器语言和高级语言 认识JavaScriptJav…

大数据做「AI大模型」数据清洗调优基础篇

关于本文 近期一直在协助做AI大模型数据清洗调优的工作&#xff0c;主要就是使用大数据计算引擎Spark做一些原始数据的清洗工作&#xff0c;整体数据量大约6PB-8PB之间&#xff0c;那么对于整个大数据量的处理性能将是一个重大的挑战&#xff0c;关于具体的调优参数配置项暂时不…