当前位置: 首页 > news >正文

DS:八大排序之堆排序、冒泡排序、快速排序

                                                 创作不易,友友们给个三连吧!! 

一、堆排序

堆排序已经在博主关于堆的实现过程中详细的讲过了,大家可以直接去看,很详细,这边不介绍了

DS:二叉树的顺序结构及堆的实现-CSDN博客

直接上代码:

void AdjustDown(int* a, int n, int parent)//升序要建大堆
{int child = parent * 2 + 1;//假设左孩子比右孩子大while (child < n){//如果假设错误,就认错if (child + 1 < n && a[child] < a[child + 1])child++;//如果孩子大于父亲,交换if (a[child] > a[parent]){Swap(&a[child], &a[parent]);//交换完后,让原来的孩子变成父亲,然后再去找新的孩子parent = child;child = parent * 2 + 1;}elsebreak;}
}void HeapSort(int* a, int n)
{//向下调整建堆for (int i = (n - 1 - 1) / 2; i >= 0; i--)AdjustDown(a, n, i);//大堆,向下调整int end = n - 1;while (end >= 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);end--;}
}

建堆的时间复杂度是o(N),排序的时间复杂度是(N*logN)所以堆排序的总时间复杂度是N*logN

二、冒泡排序

2.1 思想

基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

2.2 冒泡排序的实现

方法:从前往后,逐一比较相邻元素,前面的大于或小于后面的则进行交换,每一轮将当前轮最大或最小的元素冒泡到当前论的最后。重复上述过程最后就是有序的。

该排序比较简单,不画图了,不懂得可以看看博主之前写的文章有介绍:

C语言:深入理解指针(2)-CSDN博客

代码实现:

void BubbleSort(int* a, int n)
{for (int i = 0; i < n - 1; i++)//每一趟拍好一个,最后排完n-1个,最后一个数就没必要比了{for (int j = 0; j < n - i - 1; j++)//第一趟需要比较的n-1次,第二次需要比较n-2次……//所以结束条件跟着i变化{if (a[j] > a[j + 1])Swap(&a[j], &a[j + 1]);}}
}

2.3 冒泡排序的改进

如果比较的过程中,比到中间的时候就有序了,但是我们并不知道,这个时候一直到后面进行的比较都是无效的,所以为了优化这个情况,我们设置一个标志,如果一趟排序中没有发生交换,说明后面都有序了,这个时候就停止冒泡排序!!

void BubbleSort(int* a, int n)
{for (int i = 0; i < n - 1; i++)//每一趟拍好一个,最后排完n-1个,最后一个数就没必要比了{int flag = 1;//假设有序for (int j = 0; j < n - i - 1; j++)//第一趟需要比较的n-1次,第二次需要比较n-2次……//所以结束条件跟着i变化{if (a[j] > a[j + 1]){Swap(&a[j], &a[j + 1]);flag = 0;//如果没有发生交换,说明不符合有序}}if (flag == 1)break;}
}

2.4 复杂度分析

时间复杂度:O(N^2)

空间复杂度:O(1)

三、快速排序

3.1 思想

         快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法

其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

       根据区间按照基准值划分的过程,有最早的hoare版本,包括后来深入研究之后的挖坑法、前后指针法、快排法、非递归法……以下博主会用图文的方式和大家一起学习不同方法的实现!!并在这个过程中理解为什么说这中排序方法是二叉树结构。

3.2 hoare快排实现

hoare大佬最初的思想是:

1、在数组中选取一个key值,一般是选择第一个元素或者最后一个元素(我们主要这边主要研究第一个元素做key值)

2、设置两个指针,一个指针right先从往右往左找比key小的值,找到之后,另一个指针left再从左往右走找比key大的值,然后都找到后就交换两边的值,重复上述过程,最后当两个指针相遇的时候,再将相遇点的值与key点的值交换,此时key的左边都是比key小的值,key的右边都是比key大的值,这样就完成了一次选基准值的排序。

3、完成一次找基准值的排序后,使数组有序的问题通过基准值key转化成使key左边和右边都有序的问题,也就是这个key为基准,再分割成两块区间,再分别用上述方法找各自区间的key值,继续重复之前的步骤(递归),直到区间不能被分割,此时的数组就实现了有序。

以上的说法可能大家还不太能理解,我们通过画图来理解hoare大佬的思想。

我们通过上图可以理解为什么说快速排序是一种二叉树结构的排序!!这个过程和二叉树的前序遍历非常相似。既然我们知道了hoare大佬具体想怎么干,我们就明白了这个快排是用递归去实现的,当然现在问题的关键就是我们如果进行基准排序去找到key值对应的位置,下面我们来分析一趟基准排序的过程

       以上就是完成一次基准排序的过程,大家会发现此时恰好key的左边是比key小的,key的右边都是比key大的,其实这并不是巧合,我们后面会分析,这边我们先实现一下一次基准排序的代码!

基准排序代码实现:

int PartSort1(int* a, int left, int right)//hoare基准排序
{int keyi = left;while (left < right){//右先找比key大的while (left < right&&a[right] >= a[keyi])right--;//左找比key小的while (left < right && a[left] <= a[keyi])left++;//找到后,就交换Swap(&a[left], &a[right]);}//此时相遇了,把相遇的位置和keyi的位置交换Swap(&a[left], &a[keyi]);return left;
}

根据上述的一次基准排序的实现,我们来通过递归实现整体快排的代码:

void QuickSort(int* a, int left, int right)
{if (left >= right)return;int keyi = PartSort1(a, left, right);//根据基准值去分割区间,继续进行基准排序QuickSort(a, left, keyi - 1);QuickSort(a, keyi+1,right);
}

思考以下问题:

1、怎么判断递归的结束条件呢??

2、hoare大佬是怎么确定每次相遇的时候,相遇点的位置的值一定比key的值小呢??

3、left可以从第二个位置开始走吗?

通过上述的分析,相信大家对hoare大佬的思想已经理解了!!

3.3 挖坑法快排实现

         hoare大佬的思想真的是超凡脱俗,非常厉害,但是也有很多不容易理解的地方,后面就有人进行了改进,发明了挖坑版本的快排,虽然名字叫挖坑,但是比hoare会好理解很多,下面我们来进行挖坑版本的分析!

发明挖坑版本大佬的思想是:

1、先把keyi对应的值记住,然后在这个位置挖坑,right找大,找到了就停下来,将停下来的位置的值去填坑,然后right的位置变成新坑,left找小,找到后就把对应的值填坑,然后left成为新坑,以此类推下去,直到left和right相遇,将之前记住keyi的值填入坑内,这个时候就完成了一次基准排序。

2、除了基准排序的方法和hoare大佬不同,其余地方都是一样的,也是用递归去解决。

 通过这个方法,我们来实现对应的基准排序算法

int PartSort2(int* a, int left, int right)//挖坑基准排序
{int key = a[left];//记住key的值int hole = left;//开始挖坑while (left < right){//右先找比key大的while (left < right && a[right] >= key)right--;//找到后,填坑,然后挖新坑a[hole] = a[right];hole = right;//左找比key小的while (left < right && a[left] <= key)left++;//找到后,填坑,然后挖新坑a[hole] = a[left];hole = left;}//此时相遇了,把key值放在坑里a[hole] = key;return hole;
}

整体实现:

void QuickSort(int* a, int left, int right)
{if (left >= right)return;int keyi = PartSort2(a, left, right);//根据基准值去分割区间,继续进行基准排序QuickSort(a, left, keyi - 1);QuickSort(a, keyi+1,right);
}

我们发现挖坑和填坑的思想特别好理解!!然后接下去就是前后指针版本快排 !!

3.4 前后指针法快排实现

发明前后指针版本大佬的思想是:

1、设置前指针prev,指向首元素,后指针cur指向第二个元素,如果cur开始找小,如果没找到小,就一直往前走,如果找到小的了,就先停下来,然后prev往前走一步,在和cur交换值,然后cur接着走……重复上述步骤,最后cur走出数组返回后,循环终止!此时prev指向的位置和keyi的位置交换。

 

下面我们来实现前后指针快排的基准排序

int PartSort3(int* a, int left, int right) //前后指针基准排序
{int prev = left;int cur = left + 1;int keyi = left;while (cur <= right)//cur走出数组循环停止{//cur一直在走,如果遇到比keyi小的,就停下来等perv走一步后交换,再接着走if (a[cur] < a[keyi]){++prev;Swap(&a[prev], &a[cur]);}cur++;}//cur出去后,prev的值和keyi交换Swap(&a[keyi], &a[prev]);return prev;
}

 因为prev和cur指向一个位置的时候,其实没有交换的必要,所以可以将上面代码的优化一下

int PartSort3(int* a, int left, int right) //前后指针基准排序
{int prev = left;int cur = left + 1;int keyi = left;while (cur <= right)//cur走出数组循环停止{//cur一直在走,如果遇到比keyi小的,就停下来等perv走一步后交换,再接着走if (a[cur] < a[keyi]&&++prev!=cur)Swap(&a[prev], &a[cur]);cur++;}//cur出去后,prev的值和keyi交换Swap(&a[keyi], &a[prev]);return prev;
}

整体快排的实现:

void QuickSort(int* a, int left, int right)
{if (left >= right)return;int keyi = PartSort3(a, left, right);//根据基准值去分割区间,继续进行基准排序QuickSort(a, left, keyi - 1);QuickSort(a, keyi+1,right);
}

3.5 快排的复杂度分析

时间复杂度:O(logN*N)

 如果使用了三数取中的优化方法(后面会介绍),那么快排就不可能出现O(N^2)的情况,所以最后时间复杂度是O(logN*N)

空间复杂度:O(logN)

         因为递归是要开销栈帧的,空间可以重复利用而时间不可重复利用。所以这里至多递归到他的深度即h = logN,所以他的空间复杂度是O(logN)

3.6 快排的优化

快排优化的过程源于这道OJ题

力扣:排序数组

看到这题,你可能会很开心:这不就是一个排序吗?我把最厉害的快排用上肯定能过的!!

结果是这样的——

为什么呢??因为力扣的测试用例设置了一个有序的数组来针对快排(复杂度分析过原因了),本质上就是因为有序的时候前面的keyi太小了!!所以我们设置一个改进方法——三数取中,解决有序的情况

3.6.1 三数取中——针对有序

int GetMidIndex(int* a, int left, int right)
{int mid = (left + right) / 2;if (a[left] < a[mid]){if (a[mid] < a[right])return mid;else if (a[right] < a[left])return left;elsereturn right;}else//a[left] >a[mid]{if (a[mid] > a[right])return mid;else if (a[right] > a[left])return left;elsereturn right;}
}

封装后,我们前面三种方法的基准值排序都要加上以下代码,这样就可以确保keyi的值是中间值了

int mid = GetMidIndex(a, left, right);
Swap(&a[mid], &a[left]);

你可能觉得这样子应该能过了 ,那我们再测试一下——

结果你发现,又被针对了,有序的情况解决了,又面临着有大量重复数据的排序问题,我们来分析一下:

你会发现,重复其实跟有序的情况是一样的,每次right指针都会走到keyi的位置,这样子时间复杂度也变成O(N^2)了。所以为了解决重复的问题,我们有了三路划分的方法—— 

3.6.2 三路划分——针对重复

因为每次递归需要返回两个边界才行,所以没办法单独封装一个partsort函数 

代码实现: 

void QuickSort2(int* a, int left, int right)
{if (left >= right)return;int mid = GetMidIndex(a, left, right);Swap(&a[mid], &a[left]);int phead = left;int pcur = left + 1;int ptail = right;int key = a[left];while (pcur <= ptail){if (a[pcur] < key){Swap(&a[pcur], &a[phead]);pcur++;phead++;}else if (a[pcur] > key){Swap(&a[pcur], &a[ptail]);ptail--;}elsepcur++;}QuickSort2(a, left, phead - 1);QuickSort2(a, ptail+1,right);
}

结果我们发现,还是过不了,那究竟是哪里出问题了呢?? 

因为里面有一组测试用例针对了三数取中,也就是他把偏大和偏小的数都安排在恰好的位置,所以我们为了针对这种情况,将三数取中的其中一个数改成随机数,接下来我们对三数取中再优化

3.6.3 三数取中再优化

将三数取中的其中一个数的下标变成随机下标:

同时要记得在主函数加上时间种子

int GetMidIndex2(int* a, int left, int right)
{int mid = left + (rand() % (right - left));if (a[left] < a[mid]){if (a[mid] < a[right])return mid;else if (a[right] < a[left])return left;elsereturn right;}else//a[left] >a[mid]{if (a[mid] > a[right])return mid;else if (a[right] > a[left])return left;elsereturn right;}
}
void QuickSort2(int* a, int left, int right)
{if (left >= right)return;int mid = GetMidIndex2(a, left, right);Swap(&a[mid], &a[left]);int phead = left;int pcur = left + 1;int ptail = right;int key = a[left];while (pcur <= ptail){if (a[pcur] < key){Swap(&a[pcur], &a[phead]);pcur++;phead++;}else if (a[pcur] > key){Swap(&a[pcur], &a[ptail]);ptail--;}elsepcur++;}QuickSort2(a, left, phead - 1);QuickSort2(a, ptail+1,right);
}

终于过了!!要重点理解快排的优化思想!! 

3.7 非递归法快排实现

3.7.1 栈实现

我们发现无论是hoare、挖坑还是前后指针,本质区别就是基准排序方法不同,但最后还是用递归去解决的,递归虽好但是有些时候如果数据太大的话还是有可能造成栈空间不够的情况,因此我们应该研究一下如果非递归实现!!——利用栈!

利用栈实现非递归快排的大佬的思想是:

利用栈来存储基准排序需要处理的区间,每次从栈拿出需要处理的区间,再将分割的区间放进栈中,利用栈后进先出的特点,每次都会先处理左边的区间再处理右边的区间,模拟了递归的过程。

我们画个图来理解吧!!(类似二叉树的前序遍历)

 非递归快排代码实现:

需要包含栈的相关代码

void QuickSortNonR1(int* a, int left, int right)
{Stack st;StackInit(&st);//把区间压进去,一定要先压右区间!!StackPush(&st, right);StackPush(&st, left);while (!StackEmpty(&st)){//将数据弹出来进行进准计算int left = StackTop(&st);StackPop(&st);int right= StackTop(&st);StackPop(&st);//进行基准计算int keyi = PartSort3(a, left, right);//分割区间(left keyi-1)keyi(keyi+1,right)//如果对应的区间还能分割,就继续压,要注意要先压后面在压前面if (keyi + 1 < right){StackPush(&st, right);StackPush(&st, keyi+1);}if (keyi - 1 > left){StackPush(&st, keyi-1);StackPush(&st,left);}}//会一直到栈为空,此时就拍好序了!!StackDestory(&st);
}

3.7.2 队列实现

使用队列也是可以的!!就有点类似二叉树的层序遍历

代码实现:

 需要包含队列的一些文件

void QuickSortNonR2(int* a, int left, int right)
{Queue q;QueueInit(&q);QueuePush(&q, left);QueuePush(&q, right);while (!QueueEmpty(&q)){int left = QueueFront(&q);QueuePop(&q);int right = QueueFront(&q);QueuePop(&q);int keyi = PartSort3(a, left, right);if (keyi - 1 > left){QueuePush(&q, left);QueuePush(&q, keyi-1);}if (keyi + 1 <right){QueuePush(&q, keyi +1);QueuePush(&q, right);}}QueueDestory(&q);
}

 

相关文章:

DS:八大排序之堆排序、冒泡排序、快速排序

创作不易&#xff0c;友友们给个三连吧&#xff01;&#xff01; 一、堆排序 堆排序已经在博主关于堆的实现过程中详细的讲过了&#xff0c;大家可以直接去看&#xff0c;很详细,这边不介绍了 DS&#xff1a;二叉树的顺序结构及堆的实现-CSDN博客 直接上代码&#xff1a; …...

Sora:继ChatGPT之后,OpenAI的又一力作

关于Sora的报道&#xff0c;相信很多圈内朋友都已经看到了来自各大媒体铺天盖地的宣传了&#xff0c;这次&#xff0c;对于Sora的宣传&#xff0c;绝不比当初ChatGPT的宣传弱。自OpenAI发布了GPT4之后&#xff0c;就已经有很多视频生成模型了&#xff0c;不过这些模型要么生成的…...

阅读笔记(BMSB 2018)Video Stitching Based on Optical Flow

参考文献 Xie C, Zhang X, Yang H, et al. Video Stitching Based on Optical Flow[C]//2018 IEEE International Symposium on Broadband Multimedia Systems and Broadcasting (BMSB). IEEE, 2018: 1-5. 摘要 视频拼接在计算机视觉中仍然是一个具有挑战性的问题&#xff0…...

Ubuntu学习笔记-Ubuntu搭建禅道开源版及基本使用

文章目录 概述一、Ubuntu中安装1.1 复制下载安装包路径1.2 将安装包解压到ubuntu中1.3 启动服务1.4 设置开机自启动 二、禅道服务基本操作2.1 启动&#xff0c;停止&#xff0c;重启&#xff0c;查看服务状态2.2 开放端口2.3 访问和登录禅道 卜相机关 卜三命、相万生&#xff0…...

《苍穹外卖》知识梳理6-缓存商品,购物车功能

苍穹外卖实操笔记六—缓存商品&#xff0c;购物车功能 一.缓存菜品 可以使用redis进行缓存&#xff1b;另外&#xff0c;在实现缓存套餐时可以使用spring cache提高开发效率&#xff1b;   通过缓存数据&#xff0c;降低访问数据库的次数&#xff1b; 使用的缓存逻辑&#…...

[NSSCTF]-Web:[SWPUCTF 2021 新生赛]easy_sql解析

查看网页 有提示&#xff0c;参数是wllm&#xff0c;并且要我们输入点东西 所以&#xff0c;我们尝试以get方式传入 有回显&#xff0c;但似乎没啥用 从上图看应该是字符型漏洞&#xff0c;单引号字符注入 先查看字段数 /?wllm2order by 3-- 没回显 报错了&#xff0c;说明…...

vue3 codemirror yaml文件编辑器插件

需求&#xff1a;前端编写yaml配置文件 &#xff0c;检查yaml语法 提供语法高亮 。 默认内容从后端接口获取 显示在前端 &#xff0c; 前端在codemirror 插件中修改文件内容 &#xff0c;并提交修改 后端将提交的内容写入服务器配置文件中 。 codemirror 通过ref 后期编辑器…...

力扣经典题:环形链表的检测与返回

1.值得背的题 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode *detectCycle(struct ListNode *head) {struct ListNode*fasthead;struct ListNode*slowhead;while(fast!NULL&&fast->…...

【web | CTF】BUUCTF [BJDCTF2020]Easy MD5

天命&#xff1a;好像也挺实用的题目&#xff0c;也是比较经典吧 天命&#xff1a;把php的MD5漏洞都玩了一遍 第一关&#xff1a;MD5绕过 先声明一下&#xff1a;这题的MD5是php&#xff0c;不是mysql的MD5&#xff0c;把我搞迷糊了 一进来题目啥也没有&#xff0c;那么就要看…...

spring boot Mybatis Plus分页

文章目录 Mybatis Plus自带分页和PageHelper有什么区别&#xff1f;Mybatis Plus整合PageHelper分页 springboot自定义拦截器获取分页参数spring boot下配置mybatis-plus分页插件单表分页查询自定义sql分页查询PageHelper 参考 Mybatis Plus自带分页和PageHelper有什么区别&…...

elementui 中 el-date-picker 控制选择当前年之前或者之后的年份

文章目录 需求分析 需求 对 el-date-picker控件做出判断控制 分析 给 el-date-picker 组件添加 picker-options 属性&#xff0c;并绑定对应数据 pickerOptions html <el-form-item label"雨量年份&#xff1a;" prop"date"><el-date-picker …...

GlusterFS:开源分布式文件系统的深度解析与应用场景实践

引言 在当今大数据时代背景下&#xff0c;企业对存储系统的容量、性能和可靠性提出了前所未有的挑战。GlusterFS作为一款开源的、高度可扩展的分布式文件系统&#xff0c;以其独特的无中心元数据设计和灵活的卷管理机制&#xff0c;在众多场景中脱颖而出&#xff0c;为解决大规…...

第6个-滚动动画

Day 6 - Scroll Animation 1. 演示效果 2. 分析思路 布局 所有的内容进行水平垂直居中&#xff0c;可以使用**margin:0 auto;&#xff0c;也可以使用flex**布局&#xff1a; body {background-color: #efedd6;display: flex;flex-direction: column;justify-content: center…...

配置oracle连接管理器(cman)

Oracle Connection Manager是一个软件组件&#xff0c;可以在oracle客户端上指定安装这个组件&#xff0c;Oracle连接管理器代理发送给数据库服务器的请求&#xff0c;在连接管理器中&#xff0c;我们可以通过配置各种规则来控制会话访问。 简而言之&#xff0c;不同于专用连接…...

[N-142]基于springboot,vue停车场管理系统

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 项目采用前后端分离 前端技术&#xff1a;vueelementUI 服务端技术&#xff1a;springbootmybatis-plus 本项目分为普通用户和管理员…...

DAY53:动态规划(买股票的最佳时机)

Leetcode: 121 买卖股票的最佳时机 代码随想录 1、确定下标和含义 dp[i][0]表示当天持有股票所得的最多现金 do[i][1]表示当天不持有股票的最多现金 2、递推公式 &#xff08;1&#xff09;如果第i天持有股票即dp[i][0]&#xff0c; 那么可以由两个状态推出来 第i-1天就…...

快速实现用户认证:使用Python和Flask配合PyJWT生成与解密Token的教程及示例代码

生成token 与解密 token 和 拦截器 #学习交流 访问 # https://v.iiar.cnimport jwt import datetime from models import XUser from flask import request, jsonify from functools import wrapsSECRET_KEY XPay# 创建token def generate_token(user_id):try:payload {exp:…...

外汇110:外汇做空是什么意思?如何运作?一文读懂

外汇市场允许卖空&#xff0c;就像众多金融市场一样。但什么是卖空呢&#xff1f;如何外汇做空&#xff1f;在本文中&#xff0c;我们将讨论如何做空货币。什么是外汇做空&#xff1f; 外汇做空&#xff08;Short Selling&#xff09;是外汇市场上的一种投资方式。它指的是投资…...

【记录】个人博客或笔记中的数学符号设定

note 这里记录个人博客中常用的数学符号数学格式和对应含义 文章目录 note数与数组索引集合线性代数微积分概率和信息论数据与概率分布函数深度学习中的常用数学表达方式 数与数组 α 标量 α 向量 A 矩阵 A 张量 I n n 行 n 列单位矩阵 v w 单词 w 的分布式向量表示 …...

Redis Sentinel工作原理

Redis Sentinel是Redis的高可用性解决方案。它主要用来监控Redis master和slave服务器的运行状态&#xff0c;并在master宕机时自动进行故障转移&#xff0c;即从slave节点中选举出新的master节点&#xff0c;并让其余的slave节点指向新的master节点。 Redis Sentinel工作原理…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...