【数据结构与算法】:堆排序和选择排序

news2024/11/25 16:31:01

1. 堆排序

堆排序是一种比较复杂的排序算法,因为它的流程比较多,理解起来不会像冒泡排序和选择排序那样直观。

1.1 堆的结构
要理解堆排序,首先要理解堆。堆的逻辑结构是一棵完全二叉树,物理结构是一个数组。 (如果不知道什么是二叉树,请前往我的主页查看)所以堆是一个用数组表示的完全二叉树。如图:
在这里插入图片描述

1.2 堆的左右子树与下标的关系

现在的需求是要对数组元素进行排序,所以事实上我们还是通过数组的下标来操纵数组的元素。但是我们已经把数组想象成一棵完全二叉树了,怎么通过二叉树的左右子树来确定数组下标呢?有如下性质:

  1. leftchild = parent * 2 + 1
  2. rightchild = parent * 2 + 2
  3. parent = (child - 1) /2child 是左孩子或右孩子
  4. 堆的右子树 = 左子树 + 1

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7b8d8d56960041629f715eaf16124b62.png

1.3 大堆和小堆的概念

  • 大(顶)堆是指所有父亲节点的值都大于等于孩子节点的值。大堆的堆顶是数组元素的最大值
  • 小(顶)堆是指所有父亲节点的值都小于等于孩子节点的值。小堆的堆顶是数组元素的最小值

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d1e27a901f584536bf9ccbdab885862c.png

堆排序主要分三步:
(1)构建堆
(2)调整堆
(3)堆排序

首先需要明确一点,构建堆是在数组基础上构建的换句话说就是将数组抽象成一个二叉堆,而不是凭空构建。

1.1排序思想

1.首先将待排序的数组构造一个大根堆,此时,整个数组的最大值就是堆结构的顶端。
2.将堆结构内顶端的数与堆的最后一个叶节点所在的数交换,此时,末尾的数为最大值,把它不看作堆里面的了,剩余待排序的个数为n - 1
3.将剩余的n - 1个数再构造成大根堆,再将堆顶的数与n - 1位置的数交换,如此反复执行,最后就能得到有序数组了

注意:排升序建大根堆,排降序建小根堆。(默认排升序)

原因:由于堆排序的本质是选数排序,是通过堆来选数的。如果排升序时建小堆,最小的数在堆顶已经被选出来了。那么在剩下的数中再去选数,但是这时剩下的数的父子结构关系都乱了,需要重新建堆才能选出下一个数,建堆的时间复杂度是0(N),这样堆排序就没有效率优势了。

  • 如何构造大堆

想要建大堆,首先要理解向下调整算法前提是左右子树都是大堆,否则无法使用该算法(如果要建小堆,则使用向下调整算法的前提是左右子树都是小堆)。

算法思路:
从根节点开始,选出左右孩子中大的那一个,跟父亲比较,如果比父亲大就和父亲交换位置,然后再继续向下调,调到叶节点就终止

举一个简单的例子解释:
在这里插入图片描述

向下调整算法代码实现如下:

注意:第一个if的判断条件中child + 1 < sz 是为了避免左子树存在,而右子树不存在的情况,即计算右子树的下标时数组越界了


void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

//sz是数组元素个数
void AdjustDown(int* arr, int sz, int root)
{
	int parent = root;
	int child = parent * 2 + 1;//默认孩子是左孩子

	while (child <sz)
	{
		//选出左右孩子中较小的那一个
		if (child + 1 < sz && arr[child + 1] > arr[child])
		{
			child += 1;
		}
		if ( arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

但是我们知道一个任意的数组要满足这个前提是几乎不可能的,那么给定一个无序的序列,该如何利用向下调整算法构建成大堆呢

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fimgblog.csdnimg.cn%2Fdirect%2Ff30892cf7e694bc7b83e0ceb633ff093.png&pos_id=img-QHNSTLpS-1712537662852

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ab42586bcbdf4619aea79712b94e028e.png

首先我们任意给定一个无序的数组,将其看做一个堆结构,一个没有规则的二叉树,将序列里的值按照从上往下,从左到右依次填充到二叉树中。

![![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/cf9b819bb9d84fe598424cbdde03518e.png](https://img-blog.csdnimg.cn/direct/bd29ffbde1f64d5bae6b5699b5019323.png

再经过分析,叶子节点不需要调,因为叶子节点没有左右子树,可以当成大堆。所以应该倒着从最后一个非叶子的子树开始调。 那么最后一个非叶子节点的下标如何计算呢?由上文可知,已知一个孩子的下标,计算其父亲的下标,用 parent = (child - 1) /2即可。如上图,9的下标是4,其父亲6的下标为(4 - 1) / 2 = 1符合。

我们找到了最后一个非叶子节点,即元素值为6的节点,比较它的左右节点中最大的一个的值,是否比他大,如果大就交换位置
在这里5小于6,而9大于6,则交换6和9的位置;
![![![![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/8e312a353c9440ab97dfcad6b9ea990f.png](https://img-blog.csdnimg.cn/direct/b3dbea45957044099882c5d8d450589c.png](https://img-blog.csdnimg.cn/direct/dc9da81f04524c15adf9c7be8e582c77.png](https://img-blog.csdnimg.cn/direct/4cddded9d25947fb9e033b29b88d2380.png

找到下一个非叶子节点4,用它和它的左右子节点进行比较,4大于3,而4小于9,交换4和9位置;

![![![![![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/05d07a38f0c041da8cd39f5749e02d9f.png](https://img-blog.csdnimg.cn/direct/1e9a2d3c835a44c0a39a0ada530bb67e.png](https://img-blog.csdnimg.cn/direct/4e54919fe8cf41b98e194561adc78b75.png](https://img-blog.csdnimg.cn/direct/90be6d87e5914f628ecdfdbd6f0d54a7.png](https://img-blog.csdnimg.cn/direct/ec6a93164ba94ecab4116dea5b1cd17f.png

此时发现4小于5和6这两个子节点,我们需要进行调整,左右节点5和6中,6大于5且6大于父节点4,因此交换4和6的位置;

![![![![![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/79250501036045fe8098c5f772f8d45e.png](https://img-blog.csdnimg.cn/direct/8a2b25d834a649cba8f3e2c638042a82.png](https://img-blog.csdnimg.cn/direct/35fd0e8347ee41999a2935620a7b986e.png](https://img-blog.csdnimg.cn/direct/1cfa3f7fabbc42559e8b7be672088a9f.png](https://img-blog.csdnimg.cn/direct/46cc04ce83864e74ac09deeae7b7d4b3.png

此时我们就构造出来一个大根堆。代码实现如下:

注意:for循环中的sz - 1是指数组最后一个元素的下标,即最后一个叶子的位置(sz - 1 - 1) / 2是指最后一个非叶子节点的位置

void HeapSort(int* arr, int sz)
{
	//建堆

	//但是,如果我们要排升序,就要建大堆
	for (int i = (sz - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, sz, i);//建好了大堆
	}
}

通过上述操作建好了大堆,接下来进行排序

首先将顶点元素9与末尾元素4交换位置,此时末尾数字为最大值。排除已经确定的最大元素,将剩下元素重新构建大根堆。
第一次交换重构如图:
![![![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ab40c52232ac411fbce6bfa91cd27af7.png](https://img-blog.csdnimg.cn/direct/d4abc5f6fe914182ad1e196b0ea5a2dc.png](https://img-blog.csdnimg.cn/direct/f61699b41c2749a7b264470692a2579b.png

此时元素9已经有序,末尾元素则为4(每调整一次,调整后的尾部元素在下次调整重构时都不能动)。
第二次交换重构如图:

![![![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ad777bf274cb4e8f93ad8ce5ee657992.png](https://img-blog.csdnimg.cn/direct/fc48ceb896c542148b3d80593c3a6109.png](https://img-blog.csdnimg.cn/direct/7b82cf7dc86447ccb901241fca961074.png

最终排序结果:
![![![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/58b6d443391c44308405685214acaba1.png](https://img-blog.csdnimg.cn/direct/d935b4cbddf24bce84bdff6b006698e0.png](https://img-blog.csdnimg.cn/direct/77288401207d4a6f8b146dc7febfd1b5.png

排序代码实现如下:

void HeapSort(int* arr, int sz)
{
	//建堆

	//但是,如果我们要排升序,就要建大堆
	for (int i = (sz - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, sz, i);//建好了大堆
	}

	int end = sz - 1;
	while (end > 0)
	{
		//把第一个最大的和最后一个交换,把它不看作堆里的
		Swap(&arr[0], &arr[end]);
		
		//再把前n-1个向下调整成升序,再选出次大的数
		AdjustDown(arr, end, 0);//end是需要调整的个数,0是根参数,
		                        //用的是数组第一个元素的下标
		end--;
	}
}

由此,我们可以归纳出堆排序算法的步骤:

1.把无序数组构建成二叉堆。

2.循环删除堆顶元素,移到集合尾部,调节堆产生新的堆顶。

当我们删除一个最大堆的堆顶(并不是完全删除,而是替换到最后面),经过自我调节,第二大的元素就会被交换上来,成为最大堆的新堆顶。

正如上图所示,当我们删除值为9的堆顶节点,经过调节,值为6的新节点就会顶替上来;当我们删除值为6的堆顶节点,经过调节,值为5的新节点就会顶替上来…

由于二叉堆的这个特性,我们每一次删除旧堆顶,调整后的新堆顶都是大小仅次于旧堆顶的节点。那么我们只要反复删除堆顶,反复调节二叉堆,所得到的集合就成为了一个有序集合。

1.4 堆排序的全过程完整代码实现如下:


void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

//sz是数组元素个数
void AdjustDown(int* arr, int sz, int root)
{
	int parent = root;
	int child = parent * 2 + 1;//默认孩子是左孩子

	while (child <sz)
	{
		//选出左右孩子中较大的那一个
		if (child + 1 < sz && arr[child + 1] > arr[child])
		{
			child += 1;
		}
		if ( arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int* arr, int sz)
{
	//建堆

	//但是,如果我们要排升序,就要建大堆
	for (int i = (sz - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, sz, i);//建好了大堆
	}

	int end = sz - 1;
	while (end > 0)
	{
		//把第一个最大的和最后一个交换,把它不看作堆里的
		Swap(&arr[0], &arr[end]);
		
		//再把前n-1个向下调整成升序,再选出次大的数
		AdjustDown(arr, end, 0);//end是需要调整的个数,0是根参数,
		                        //用的是数组第一个元素的下标
		end--;
	}
}

排序结果是:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/3cbb2bb1cd5b44e89cf8f904694f78d5.png

1.5堆排序的时间复杂度:0(N*logN),是不稳定的排序。

2. 选择排序

选择排序是所有排序算法中最简单的,最容易理解的,同时也是效率极差的排序,几乎不用。

2.1 排序思想:

遍历一个无序数组,一次选出最大值和最小值,再把这两个值分别放到最前和最后的位置;重复这个操作,选出次大值,次小值,分别放到数组的第二个位置和倒数第二个位置……

图解如下:(默认排升序)

begin ,end,maxi,mini存放的都是下标让begin指向第一个元素,end指向最后一个元素通过遍历数组,在begin和end区间内找到最大值8,下标maxi = 2,最小值-1,下标mini = 3

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/86defaa277ef4ce0adc4743ee9d4db67.png

再让最大值和最小值分别与end,begin位置上的数交换,这样最小的就排在最前面,最大的就排在最后面了,再begin++,end–,在新区间内找到最大值和最小值

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d66abd19a0454d00bb67c197ca8b29c9.png

再次交换后,就得到了有序数组。

在这里插入图片描述

2.2 代码的实现如下:


void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void SelectSort(int* arr, int sz)
{
	int begin = 0;
	int end = sz - 1;

	while (begin < end)
	{
		int maxi = begin;
		int mini = end;

		//循环找出当前数中的最大数和最小数
		for (int i = begin; i <= end; i++)
		{
			if (arr[i] > arr[maxi])
			{
				maxi = i;
			}
			if (arr[i] < arr[mini])
			{
				mini = i;
			}
		}
		
		//让最大值和最小值分别与end,begin位置上的数交换
		Swap(&arr[begin], &arr[mini]);
		Swap(&arr[end], &arr[maxi]);
		
		begin++;
		end--;
	}
}

2.3 代码的优化:

但是上述代码有Bug!如果begin和maxi位置上的数重叠,交换时就会发生混乱!图解如下:

maxi和end位置上的数交换后,把最小值换走了,此时最大值放在了最小值的位置上,如果begin再和mini位置上的数交换,排序就会出错!
在这里插入图片描述
代码优化如下:

void SelectSort(int* arr, int sz)
{
	int begin = 0;
	int end = sz - 1;

	while (begin < end)
	{
		int maxi = begin;
		int mini = end;

		//循环找出当前数中的最大数和最小数
		for (int i = begin; i <= end; i++)
		{
			if (arr[i] > arr[maxi])
			{
				maxi = i;
			}
			if (arr[i] < arr[mini])
			{
				mini = i;
			}
		}
		Swap(&arr[begin], &arr[mini]);

		//如果begin和maxi位置上的数重叠,就要修正一下maxi的位置
		if (begin == maxi)
		{
			maxi = mini;
		}
		Swap(&arr[end], &arr[maxi]);
		begin++;
		end--;
	}
}

排序结果如图:
在这里插入图片描述

2.4 时间复杂度和稳定性

由于两个循环执行的次数大致都是N次(N为数组元素的个数),所以选择排序的时间复杂度为0(N*N),就算是最好的情况下,数组有序,时间复杂度也是0(N * N),选择排序是不稳定的排序

3. 堆排序和选择排序的性能比较

clock() 函数是 <time.h> 头文件中的一个函数,用来返回程序启动到函数调用时之间的CPU时钟周期数。这个值通常用来帮助衡量程序或程序的某个部分的性能

我们可以用这个函数进一步对比两种排序占用的CPU时间

代码实现为:

// 测试排序的性能对比
void TestOP()
{
	srand(time(0));
	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();
		a3[i] = a1[i];
		a4[i] = a1[i];
	}
	
	int begin3 = clock();
	SelectSort(a3, N);
	int end3 = clock();

	int begin4 = clock();
	HeapSort(a4, N);
	int end4 = clock();

	printf("SelectSort:%d\n", end3 - begin3);
	printf("HeapSort:%d\n", end4 - begin4);
	
	free(a3);
	free(a4);
  
}

int main()
{
   TestOP();
   
   return 0;
}

这里随机生成十万个随机数,分别用希尔排序和直接插入排序来进行排序,测试两种算法的执行时间:

在这里插入图片描述

由执行结果可知,堆排序的效率远远高于选择排序。选择排序真的很差!

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

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

相关文章

中间件漏洞攻防学习总结

前言 面试常问的一些中间件&#xff0c;学习总结一下。以下环境分别使用vulhub和vulfocus复现。 Apache apache 文件上传 (CVE-2017-15715) 描述: Apache(音译为阿帕奇)是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上&#xff0c;由于其跨…

C++ stl容器vector的认识与简单使用

目录 前言&#xff1a; 本篇文档图片引用自&#xff1a;https://cplusplus.com/reference/vector/vector/ 1.vector的结构 2.迭代器类型 3.构造函数 4.迭代器 反向迭代器遍历 const迭代器 5.容量 maxsize shrink_to_fit reverse resize 6.修改 insert和erase 7.…

【随笔】Git 高级篇 -- 相对引用1 main^(十二)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

2023 年网络安全热点技术发展态势

文章目录 前言一、人工智能信息技术迎来井喷式发展期二、零信任网络安全架构即将投入实际部署三、美国全面推动军政业务向云环境迁移四、专用太空软硬件与独立卫星网络并行发展五、量子信息技术与网络安全领域加速融合前言 在 2023 年取得进展的信息技术不在少数。从网络安全的…

【opencv】示例-distrans.cpp 距离变换

stuff.jpg #include <opencv2/core/utility.hpp> // 包含OpenCV中的核心功能支持库 #include "opencv2/imgproc.hpp" // 包含OpenCV中的图像处理库 #include "opencv2/imgcodecs.hpp" // 包含OpenCV中的图像编解码库 #include "open…

微信小程序picker设置了系统年度,打开选择年份从1年开始显示

背景&#xff1a;开发微信小程序时&#xff0c;使用了picker组件&#xff0c;设置值为当前系统时间年份&#xff0c;可以正常回显年份。但是打开面板选择年份的时候&#xff0c;默认从一年开始显示的。如下图所示。 原因&#xff1a;因为绑定的年份字段为Number类型。 解决方案…

App Inventor 2 怎么判断两个颜色是否相等?

问&#xff1a;为什么这里不能判断这个背景颜色呢&#xff1f; 答&#xff1a;背景颜色不是 bool 型&#xff0c;不能直接插入判断积木。 本帖隐藏的内容 要使用 等于&#xff08;推荐数学块.等于&#xff0c;当然文本块.等于也可以&#xff09; 来判断才行。 经检验&…

java错误记录

文章目录 javaslf4j中log不存在 maven编译出现Non-resolvable import POM: Failure to find类找不到jdk版本不对 java slf4j中log不存在 解决方法&#xff1a;再idea中安装lombok插件。 离线下载地址 https://github.com/mplushnikov/lombok-intellij-plugin/releases&#x…

爬虫 selenium

爬虫 selenium 【一】介绍 【1】说明 Selenium是一款广泛应用于Web应用程序测试的自动化测试框架 它可以模拟用户再浏览器上的行为对Web应用进行自动化测试 主要作用&#xff1a; 浏览器控制&#xff1a;启动、切换、关闭不同浏览器元素定位于操作&#xff1a;通过CSS选择器…

突破编程_前端_SVG(概述)

1 什么是 SVG SVG&#xff0c;全称可缩放矢量图形&#xff08;Scalable Vector Graphics&#xff09;&#xff0c;是一种基于 XML&#xff08;可扩展标记语言&#xff09;的矢量图像格式。这种图像格式的主要特点是它描述的是矢量图形&#xff0c;而不是基于像素的位图图像。因…

计数排序解读

当我们提及排序算法时&#xff0c;通常会想到冒泡排序、选择排序、插入排序、归并排序和快速排序等经典算法。然而&#xff0c;今天我们要探讨的是一种非比较型整数排序算法——计数排序。计数排序在某些特定场景下表现出色&#xff0c;具有线性的时间复杂度。下面我们将深度剖…

如何看待现在的前端?必备技能和方向?

​ 目录 1. 技术生态丰富 2. 用户体验为中心 3. 跨平台和移动优先 4. 性能和安全性 5. 前端工程化和自动化 6. 服务端渲染和静态站点生成 7. 人工智能和机器学习的融合 总结 发展方向&#xff1a; 必备技能&#xff1a; 当前前端开发领域正在经历快速的发展和变革。…

Three飞线动画(运动轨迹)

效果图 1.初始化场景 onMounted(() > {line() })let index 0; //取索引值的点的位置 let num 20; //从曲线上获取的数量 let points1, newLine1, bufferGeometry1; let points2, newLine2, bufferGeometry2;function line() {} 2.场景中加入一条三维曲线 function line…

Flody算法求解多源最短路问题

Flody算法求解多源最短路问题 蓝桥公园 #include <bits/stdc.h> using namespace std; #define int long long const int N409; int n,m,q,d[N][N]; signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m>>q;memset(d,0x3f,sizeof…

Linux网卡与IP地址:通往网络世界的通行证

在探索Linux网卡和IP地址的关系之前&#xff0c;我们得先理解Linux网卡是怎么工作的。想象一下&#xff0c;每台计算机都是一个世界&#x1f30e;&#xff0c;而网卡就是连接这些世界的门户&#x1f6aa;。网卡的工作就是接收和发送数据包&#xff0c;就像邮差&#x1f4ec;递送…

在win10上虚拟一个LoongOS系统(类似虚拟机)作为开发环境

文章目录 1.安装1.1.下载这三个东西1.2.安装好qemu。1.3.创建一个启动脚本startup_mate.bat&#xff0c;然后把三部分东西放到一起1.4.然后双击startup.bat就可以启动了。 2.文件的传输2.1.使能虚拟机系统的ssh2.2.连接ssh 3.Qt相关安装Qt安装opencv 1.安装 注意&#xff0c;一…

揭秘操作系统:核心功能与Linux系统解析

1.引言 在先前探讨中&#xff0c;我们了解到计算机主机内部的硬件资源需要一种高效管控手段&#xff0c;由此催生了操作系统的诞生。操作系统&#xff08;Operating System&#xff0c;简称OS&#xff09;&#xff0c;是计算机生态系统中不可或缺的核心组件&#xff0c;以其复杂…

高颜值高性能的开源免费自托管照片和视频备份方案:Immich

Immich&#xff1a;安全存储您的珍贵记忆&#xff0c;高颜值且高性能的自托管照片与视频备份解决方案&#xff0c;让您随时随地无忧回顾美好时光。- 精选真开源&#xff0c;释放新价值。 概览 在数字化时代&#xff0c;我们的照片和视频越来越多&#xff0c;如何安全、有效地备…

DSP笔记12-PWM基础知识及EPWM

PWM pulse width modulation 脉冲宽度调制&#xff0c;宽度可调节的方波脉冲&#xff0c;驱动开关器件&#xff0c; 参数&#xff1a; 1.频率f 1kHz&#xff0c;2kHz开关损耗 2.周期T 3.幅值&#xff0c;高低电平之间电压 gpio输出3.3V&#xff0c;转换成5V高电平输出 4.占…

Vue项目中,使用高级表格vxe-table中的【vxe-grid】动态列之动态插槽

1、首先项目当中得安装了vxe-table // 没有安装的话&#xff0c;可以使用一下命令安装 npm install vxe-table 或 yarn add vxe-table使用示例&#xff1a; import Vue from vue import VXETable from vxe-table import vxe-table/lib/style.cssVue.use(VXETable)2、动态列中动…