11大排序的原理讲解和Python源码剖析

news2024/11/17 22:25:44

排序算法

【谁教你这么剪的 | 11大排序的原理讲解和Python源码剖析】 https://www.bilibili.com/video/BV1Zs4y1X7mN/?share_source=copy_web&vd_source=ed4a51d52f6e5c9a2cb7def6fa64ad6a

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。

时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

**空间复杂度:**是指算法在计算机内,执行时所需存储空间,它也是数据规模n的函数。

在这里插入图片描述
在这里插入图片描述

平均时,空复杂度【o(n^2),o(1)】

冒泡 Bubble Sort-o(n^2),o(1)

冒泡排序(Bubble Sort)是一种简单的排序算法。**它通过重复比较相邻元素,并将其中最大(或最小)的元素逐渐调换到正确的位置。**简单来说,就是把小的元素往前调或者把大的元素往后调。

为什么冒泡排序是一种稳定的排序算法?

  • 在冒泡排序中,当相邻的两个元素相等时,它们的位置不会交换,保持了它们在原始数组中的相对顺序。因此,冒泡排序是一种稳定的排序算法。

如果两个相等的元素相邻,冒泡排序只会比较元素大小不会交换。如果两个相等的元素没有相邻,即使通过前面的交换使它们相邻,由于它们相等,不会再发生交换,所以它们的顺序保持不变。因此,冒泡排序是一种稳定的排序算法。

#每次比较的元素数量会减少一对,直到没有需要交换的元素,排序完成。
def bubble_sort(lst):
    n = len(lst)
    for i in range(n-1,-1,-1):#1)从最后一个元素开始,依次比较相邻的两个元素。
        for j in range(0, i):
            #2)如果顺序错误(比如前一个元素 大于 后一个元素),则交换它们的位置。
            if lst[j] > lst[j+1]:
                lst[j], lst[j+1] = lst[j+1], lst[j]   
    return lst    

选择 Selection Sort-o(n^2),o(1)

![动画展示](https://i-blog.csdnimg.cn/direct/cb4c07259e324252ae8a4ad220d34c00.png

原理:**每一轮从待排序序列中选出最小的元素,将其放置在已排序序列的末尾。然后,再从剩余的未排序元素中寻找最小元素,放置在已排序序列的末尾。**重复这个过程,直到全部待排序的数据元素个数为零,即完成排序。

特点:

1)每一轮只进行一次交换,因此交换次数相对较少,但是比较次数较多

2)选择排序是一种不稳定的排序算法:例如,考虑以下序列:[5, 3, 5, 2]。在第一次选择最小元素时,会选择到索引为3的元素2,并将其与索引为0的元素5进行交换,得到序列[2, 3, 5, 5]。由于原序列中的两个5的相对顺序被改变,所以选择排序是不稳定的。

def selection_sort(lst):
    for i in range(len(lst) - 1): #遍历列表,i从第一个元素到倒数第二个元素
        min_index = i  #1)假设当前索引为i的元素为最小值
        for j in range(i + 1, len(lst)):  #2)遍历未排序部分的元素
            if lst[j] < lst[min_index]:  #3)如果找到比当前最小值更小的元素
                min_index = j  #4)更新最小值的索引
        lst[i], lst[min_index]=lst[min_index],lst[i]#4)最后,将当前最小值与未排序部分的第一个元素交换位置
    return lst  

插入 Insertion Sort -o(n^2),o(1)

动画展示:https://gitee.com/cjq1311485460/brush-question-notes/raw/master/4d409d3d864794158b9d00ed87970110.gif

它的原理是将待排序的数据 逐个插入到 已排序的数据序列中的适当位置,直到全部插入完毕。插入排序如同打扑克牌一样,每次将后面的牌插到前面已经排好序的牌中。

具体步骤如下:

  1. 假设第一个元素已经是有序的序列,将其视为已排序序列。
  2. 从第二个元素开始,将其与已排序序列中的元素逐个比较,找到合适的位置插入。
  3. 将待插入元素插入到已排序序列中的适当位置,使得插入后的序列仍然有序。
  4. 重复步骤2和步骤3,直到所有元素都插入到已排序序列中。

特点:

稳定排序,适用于小规模数据或基本有序的数据。

def insertion_sort(lst):
    n=len(lst)
    for i in range(1,n):  
        cur_num, pre_index = lst[i], i-1 #获取当前待插入的元素 和 其前一个元素的索引
        while pre_index>=0 and cur_num<=lst[pre_index]: #当 当前待插入的元素 不大于 前一个元素时,就进行插入操作
            lst[pre_index + 1] = lst[pre_index]  #1)将前一个元素 后移一位
            pre_index -= 1  #2)还原前一个元素的索引
        lst[pre_index + 1] = cur_num  #3)将 当前待插入的元素 插入到正确的位置
    return lst  

o(nlogn)

希尔排序 Shell Sort o(nlogn),o(1)

动画展示:https://gitee.com/cjq1311485460/brush-question-notes/raw/master/4f3d6ca502bddeb2b466cd2c2054be55.gif

希尔排序(Shell Sort)是插入排序的一种改进算法,通过使用不同的间隔序列来提高排序的效率。

希尔排序的关键在于选择合适的间隔序列,不同的间隔序列可能会影响排序的效率。常用的间隔序列有**希尔增量序列(gap = gap // 2)**和Hibbard增量序列(gap = 2^k - 1),可以根据具体情况选择合适的间隔序列。

具体步骤如下:

  1. 首先,确定初始的间隔(gap)值,可以将数据序列的长度除以2取整作为初始间隔值。
  2. 然后,使用间隔值 对 数据序列进行分组,每个分组包含 相隔间隔值个元素。
  3. 将每个分组内的元素 按照插入排序的方式进行排序。(粗略排序)
  4. 缩小间隔值,将当前间隔值除以2取整,得到新间隔值。(逐渐精排)
  5. 重复步骤2到步骤4,直到最后一个间隔值为1
  6. 最后,使用间隔值为1进行一次插入排序,完成最终的排序。

特点:

不稳定的排序

def shell_sort(lst):
    n = len(lst)  
    gap = n // 2  # 初始间隔值为列表长度的一半
    while gap > 0:  #当间隔值大于0时,进行排序
        for i in range(gap, n):  #遍历列表,从间隔值开始 到 最后一个元素
            cur_num=lst[i]
            #以间隔值为步长进行插入排序,如果当前元素小于前一个间隔的元素,则交换元素
            j=i
            while j>=gap and cur_num<lst[j - gap]:  
                    lst[j], lst[j - gap] = lst[j - gap], lst[j]  
        gap //= 2  # 缩小间隔值
    return lst  

【重要】归并 Merge Sort-o(nlogn),o(n)

动画展示:“https://gitee.com/cjq1311485460/brush-question-notes/raw/master/20181120110141.gif” alt=“img” style="

该算法使用分治法的思想,将一个未排序的序列 分割成 多个已排序的子序列,然后递归地将这些子序列合并成一个有序的序列。

具体步骤如下:

  1. 首先,将待排序的序列进行拆分,将序列分割成多个子序列,直到每个子序列只包含一个元素。
  2. 然后,递归地将这些子序列进行合并。在合并的过程中,不断比较两个子序列的元素,不断将较小的元素放入新的序列中,并将相应子序列的指针向后移动一位,重复这个过程直到其中一个子序列为空。然后将另一个非空的子序列中的剩余元素直接放入新的序列中。
  3. 重复步骤2和步骤3,直到所有的子序列都合并成一个有序的序列。

特点:

稳定的排序

# 定义合并函数:先两个两个排序归并,再四个四个排序归并,,,
def merge(nums, left, mid, right):
    tmp = []  # 合并后的结果序列
    i = left  # 左子序列的指针
    j = mid + 1  # 右子序列的指针
    while i <= mid and j <= right:
        if nums[i] <= nums[j]:  # 1.1)如果左子序列的元素小于等于右子序列的元素
            tmp.append(nums[i])  # 1.2)将左子序列的元素添加到结果序列中
            i += 1  # 1.3)左子序列指针向后移动一位
        else:
            tmp.append(nums[j])  # 1.4)否则,将右子序列的元素添加到结果序列中
            j += 1  # 1.5)右子序列指针向后移动一位

    # 2)将剩余的元素直接添加到结果序列中
    tmp.extend(nums[i:mid+1])
    tmp.extend(nums[j:right+1])
    
    #原地操作
    for i in range(left,right+1):
        nums[i]=tmp[i-left]
    return tmp


def merge_sort(nums, left, right):
    if left == right: return

    mid = left + (right - left) // 2
    merge_sort(nums, left, mid)  # 对左子序列进行递归排序
    merge_sort(nums, mid + 1, right)  # 对右子序列进行递归排序
    return merge(nums, left, mid, right)  # 合并左右子序列并返回结果序列


# nums=[1, 2, 2, 3, 5]
nums=[10,10, 9, 9, 8, 7,5,6,4,3,4,2]
print(merge_sort(nums,0,len(nums)-1))
print(nums[len(nums)-3])

【重要】快速 quick sort-o(nlogn),o(logn)

动画展示:<img src"https://gitee.com/cjq1311485460/brush-question-notes/raw/master/9a08519db9e53d08dc353299cfbe2147.gif" alt=“快速排序” style=“zoom:50%;” />

  • 为什么快速排序的最坏情况时间复杂度为O(n^2)?

    • 在最坏的情况下,选取的基准值是数组中的最大或最小元素,导致分区过程每次只能分出一个元素,这使得递归调用次数达到最大,时间复杂度为O(n^2)。
  • 为什么快速排序的平均时间复杂度为O(nlogn)?

    • 在平均情况下,基准值能够将数组均匀分割成两部分,使得递归调用的深度为O(logn),每层的分区操作需要O(n)时间,因此整体的时间复杂度为O(nlogn)。

第一种、快排递归流程:

(1) 从数列中挑出一个基准值

(2) 每次,将所有比基准值小的摆放在基准前面,所有比基准值大的摆在基准的后面(相同的数可以放到任一边)。【在这个分区退出之后,该基准就处于数列的中间位置】

(3) 最后,递归地 把"基准值前面的子数列" 和 “基准值后面的子数列” 进行排序。

第二种、快排非递归流程:

通过使用栈来模拟递归调用过程,可以将快速排序算法转化为循环实现,避免了递归调用的额外开销。这种方法可以提高快速排序的效率

步骤如下:

  1. 首先,将数组的起始位置 和 终止位置入栈。

  2. 然后,以栈是否为空为条件,开始进行循环。每次循环时,从栈中取出两个元素作为当前的区间,进行一次快速排序调用。

  3. 快速排序函数会返回一个分界点。根据这个分界点,将左侧的起点 和 终点、右侧的起点 和终点 进行判断。

  4. 如果左侧的起点小于终点,将左侧的起点 和 终点入栈,以便后续对该区间进行排序。

  5. 如果右侧的起点小于终点,将右侧的起点 和 终点入栈,以便后续对该区间进行排序。

  6. 继续循环,直到栈为空为止。

#[1]递归实现快速排序
# 划分函数,将列表划分为左右两个子序列,并返回划分点的位置
import random
def partition(nums, left, right):
    #优化点:将pivot的位置随机化
    # randpivot=random.randint(left,right)
    # nums[left],nums[randpivot]=nums[randpivot],nums[left]
    pivot=left # 再选择最左边的元素作为划分点的值

    #将区间内比nums[pivot]小的元素 都排在前面:
    #通过交换nums[i],nums[j]实现
    j = left+1
    for i in range(left+1,right+1):
        if nums[i]<=nums[pivot]:
            nums[i],nums[j]=nums[j],nums[i]
            j+=1
    nums[pivot],nums[j-1]=nums[j-1],nums[pivot] #将间隔nums[pivot]放中间位置,从而实现左小右大
    pivot=j-1
    return pivot

# 【1】递归实现快速排序
def QuickSort(nums: list, left: int, right: int) -> list:
    if left >= right: return
    p = partition(nums, left, right)  # 获取划分点的位置
    QuickSort(nums, left, p - 1)  # 对左子序列进行递归排序
    QuickSort(nums, p + 1, right)  # 对右子序列进行递归排序
    return nums

# nums=[1, 2, 2, 3, 5]
nums=[10,10, 9, 9, 8, 7,5,6,4,3,4,2]
print(QuickSort(nums,0,len(nums)-1))
print(nums[len(nums)-3])

    
# 【2】非递归实现快速排序(使用栈)
def QuickSort_No_Stack(nums: list, left: int, right: int) -> list:
    temp = [left, right]  # 使用栈来保存 待处理的子序列的左右边界
    
    while temp:
        j = temp.pop()  # 取出栈顶的右边界
        i = temp.pop()  # 取出栈顶的左边界
        index = partition(nums, i, j)  # 获取分界点的位置
        
        if i < index - 1:  # 如果左子序列存在元素,压入栈中
            temp.append(i)
            temp.append(index - 1)
        
        if j > index + 1:  # 如果右子序列存在元素,压入栈中
            temp.append(index + 1)
            temp.append(j)
    return nums

(一)快速排序的最好情况,时间复杂度O(nlogn),空间复杂度O(logn)

在理想的情况下,选取的分界点刚好就是这个区间的中位数。此时,就和归并排序基本一致了。

过程:

递归的第一层,n个数被划分为2个子区间,每个子区间的数字个数为n/2;

递归的第二层,n个数被划分为4个子区间,每个子区间的数字个数为n/4;

递归的第三层,n个数被划分为8个子区间,每个子区间的数字个数为n/8;

递归的第logn层,n个数被划分为n个子区间,每个子区间的数字个数为1;

与归并排序的区别

归并排序是从最后一层开始,进行merge操作,自底向上;而快速排序则从第一层开始,交换区间中 数字的位置,是自顶向下的。

与归并排序的相似点:

merge操作和快速排序的时间复杂度是一样的。对于每一个区间,交换处理的时候,都需要遍历区间中的每一个元素,每一层的时间复杂度都是O(n)。在理想的情况下,有logn层,所以快速排序最好的时间复杂度为O(nlogn)

快速排序的最坏情况,时间复杂度O(n^2),空间复杂度O(n)

在最坏的情况下,选取的分界点刚好就是这个区间的最大值或者最小值

过程:比如,需要对n个数排序,每一次进行交换处理的时候,选取的分界点刚好都是区间的最小值。这样的话,每次操作,都只能将最小值放到第一个位置,而剩下的元素,则没有任何变化

**结果:**这种方式,对于n个数来说,就需要操作n次,而每一次操作都需要遍历剩下的所有元素,完成交换,所以总时间复杂度为O(n^2)。

堆排序 Heap sort-o(nlogn),o(1)

【堆排序(heapsort)】 https://www.bilibili.com/video/BV1Eb41147dK/?share_source=copy_web&vd_source=ed4a51d52f6e5c9a2cb7def6fa64ad6a

堆排序的核心思想是通过建立一个初始堆来表示无序区,然后不断地将堆顶元素(即最值)输出,并将其与无序区的最后一个元素交换。这样,每次交换后,有序区的长度增加1,无序区的长度减少1,直到无序区为空,排序完成。

为什么堆排序的时间复杂度为O(NlogN)?

  • 堆排序首先构建一个堆,这个过程的时间复杂度为O(N)。然后,通过不断调整堆结构来排序,调整每个元素的时间复杂度为O(logN),因此总体时间复杂度为O(NlogN)。
#【写法1】调整堆,使得以i为根节点的子树满足堆的性质
def adjust_heap(lst, i, size):  # size:总节点数
    if i >= size: return

    left_index = 2 * i + 1  # 左子节点的索引
    right_index = 2 * i + 2  # 右子节点的索引

    largest_index = i  # 假设最大值的索引为根节点索引
    # 1)如果左子节点大于根节点,更新最大值的索引 为 左子节点的索引
    if left_index < size and lst[left_index] > lst[largest_index]:
        largest_index = left_index
        # 2)如果右子节点大于最大值,更新最大值的索引 为 右子节点的索引
    if right_index < size and lst[right_index] > lst[largest_index]:
        largest_index = right_index
        # 3)如果最大值的索引 不等于 根节点的索引,交换根节点和最大值
    # 4),并递归调整交换后的子树
    if largest_index != i:
        lst[largest_index], lst[i] = lst[i], lst[largest_index]
        adjust_heap(lst, largest_index, size)
        
# 【推荐:写法2】调整堆,使得以i为根节点的子树满足堆的性质
def adjust_heap(lst, i, size):  # size:总节点数
    dad = i
    son = dad * 2 + 1
    while son < size:  # 若子节点指标在范围内才做比较
        if son + 1 < size and lst[son] < lst[son + 1]:  # 先比较两个子节点大小,选择最大的
            son+=1  # 含递归过程中son的改变
        if lst[dad] > lst[son]:  # 如果父节点大于子节点代表调整完毕,直接跳出函数
            return
        else:  # 否则交换父子内容再继续子节点和孙节点比较
            lst[dad], lst[son] = lst[son], lst[dad]
            dad = son
            son = dad * 2 + 1

def HeapSort(lst):
    n = len(lst)
    # 1)初始化大顶堆:完全二叉树-上到下,左到右构建;父节点 一定大于 根节点
    # 实现: 建立初始堆,从最后一个 非叶子节点开始,依次向上调整 每个子树 使其满足堆的性质
    for i in range(n // 2, -1, -1):  # n//2:以一半的子树 作为堆化的根节点,再通过递归,就可构建出整个大顶堆
        adjust_heap(lst, i, n)
    # 2)在已构建大顶堆的基础上,做排序
    for i in range(n - 1, -1, -1):  # 从最后一个元素开始,依次将最大值 放到 末尾
        lst[0], lst[i] = lst[i], lst[0]  # 将根节点(即最大值)与 最后一个元素交换
        adjust_heap(lst, 0, i)  # 2)调整交换后的堆【即依次“除去”最后一个最大元素的堆】,从而堆顶依次为最大值
    return lst

# nums=[1, 2, 2, 3, 5]
nums=[10,10, 9, 9, 8, 7,5,6,4,3,4,2]
print(HeapSort(nums))
print(nums[len(nums)-3])

nums=[10,10, 9, 9, 8, 7,5,6,4,3,4,2]
print(HeapSort(nums))

【o(n+k)】

桶排序 bucket sort-o(k*o(选择的排序算法)),o(k),k为桶

桶排序的思想是将待排序列表划分为多个桶,然后对每个桶中的元素进行选择排序【不固定】,最后将排序后的元素按照桶的顺序依次放回原列表。桶排序适用于待排序列表中元素的分布比较均匀的情况。桶排序的时间复杂度取决于桶的数量和每个桶中元素的排序算法。在这段代码中,使用了冒泡排序对每个桶中的元素进行排序。

为什么桶排序对数据分布均匀的数据效果更好?

  • 桶排序将数据分到多个桶中,然后对每个桶内的数据进行选择排序。如果数据分布均匀,每个桶内的数据量相对均衡,排序效率较高。但如果数据分布不均匀,有些桶内可能会有大量数据,导致排序效率下降。

具体的算法步骤如下:

  1. 划分桶:确定桶的数量和范围。

  2. 数据入桶:将待排序的数据按照规则放入对应的桶中。

  3. 桶内排序:对每个桶中的数据进行排序,可以使用其他排序算法,如选择排序、插入排序、快速排序等。

  4. 数据合并:将每个桶中的数据按照顺序依次合并,得到最终的有序序列。

def selection_sort(lst):
    for i in range(len(lst) - 1): #遍历列表,i从第一个元素到倒数第二个元素
        min_index = i  #1)假设当前索引为i的元素为最小值
        for j in range(i + 1, len(lst)):  #2)遍历未排序部分的元素
            if lst[j] < lst[min_index]:  #3)如果找到比当前最小值更小的元素
                min_index = j  #4)更新最小值的索引
        lst[i], lst[min_index]=lst[min_index],lst[i]#4)最后,将当前最小值与未排序部分的第一个元素交换位置
    return lst  

def bucket_sort(lst):
    maxVal, minVal = max(lst), min(lst)
    bucketSize = 3 #自定义的值
    
    # 1)计算桶的数量=(待排序列表中的最大值和最小值 的差)// 桶的个数
    bucketCount = (maxVal - minVal) // bucketSize + 1
    # 2)创建桶
    buckets = [[] for i in range(bucketCount)] #[[]*bucketCount]:这些空列表是同一个对象的多个引用。修改其中一个空列表会影响到所有引用了这个空列表的地方
    # 3)将元素放入对应的桶中
    for num in lst:
        buckets[(num - minVal) // bucketSize].append(num)
    
    # 4)对每个桶中的元素进行排序(这里使用了选择排序)
    for bucket in buckets:
        selection_sort(bucket)
        
    # 5)将排序后的元素放回原列表
    lst.clear()# 清空原列表
    for bucket in buckets:
        lst.extend(bucket)
    return lst

计数排序 Counting Sort -o(n+k),o(k),k 是列表中最大值

计数排序的思想是通过统计每个元素出现的次数,然后根据元素的大小顺序将其放回原列表。它适用于待排序列表中元素的范围较小且已知的情况。计数排序的时间复杂度为O(n+k),其中n为待排序列表的长度,k为元素的范围。计数排序是一种稳定的排序算法,因为相同元素的相对顺序不会改变。

为什么计数排序适用于范围较小且已知的数据?

  • 计数排序需要创建一个计数数组,其大小等于待排序数据的范围。如果数据范围太大,计数数组会占用大量空间,因此计数排序适用于范围较小且已知的数据。

算法的步骤如下:

Counting Sort 算法步骤总结:

1.创建计数数组:

2.计算最大元素值 max(lst) 并创建一个长度为 max(lst) + 1 的计数数组 cnt,所有初始值为 0。

3.填充计数数组:

4.遍历待排序列表 lst,将每个元素的计数增加,即 cnt[val] += 1,记录每个元素出现的频率。

5.按顺序填充原数组:

6.遍历计数数组 cnt,根据每个值的计数,将元素按顺序放回原数组 lst,直到计数为 0。

结果:排序后的列表 lst 将按非递减顺序排列。

def counting_sort(lst):
    n = len(lst)
    cntlen = max(lst) + 1  # 1)根据最大元素值创建 计数数组
    cnt = [0] * cntlen

    # 2)遍历待排序列表,将每个元素放入对应的计数位置中
    for val in lst:
        cnt[val] += 1

    # 3)从计数数组中依次取出元素,按照顺序放回结果数组(即原数组)
    i = 0
    for val in range(cntlen):
        while cnt[val] > 0:
            lst[i] = val
            cnt[val] -= 1
            i += 1
    return lst

基数排序 radix sort-o(nd),o(k),d为最大元素的最大位数,k为桶大小

动画展示:<img src"https://gitee.com/cjq1311485460/brush-question-notes/raw/master/9a3483c2b6dec0045db27fcccb7db4dd.gif" alt=“在这里插入图片描述” style=“zoom:50%;” />

基数排序是一种非比较排序算法,它根据数字的每个位上的值进行排序。

为什么基数排序适合对数字进行排序?

  • 基数排序通过逐位排序(从最低位到最高位或从最高位到最低位)来处理每个数字的每一位,这使得基数排序特别适合对数字进行排序,尤其是位数较多但每位数的范围较小的情况。

基数排序的过程:

1.确定最大值:找出列表中的最大值以确定排序的位数。
2.按位排序:

3.从个位开始,逐位向左处理每个数字。
4.使用桶对当前位的数字进行分组。
5.按桶的顺序将元素重新组合回原列表。

6.重复:对每一位重复上述过程,直到处理完所有位数。

def radix_sort(lst):
    base = 1  # 初始化基数为1,表示当前处理个位数字
    maxv = max(lst)  # 获取列表中的最大值

    while base <= maxv:  # 处理所有位数,直到最大值的位数
        buckets = [[] for idx in range(10)]  # 创建10个桶,用于存储每一位上的数字(0到9)

        for num in lst:  # 遍历列表中的每个数字
            idx = (num // base) % 10  # 计算当前数字的位数上的值
            buckets[idx].append(num)  # 将数字放入相应的桶中

        l = 0  # 重新填充列表的索引
        for idx in range(10):  # 遍历所有桶
            for val in buckets[idx]:  # 遍历每个桶中的元素
                lst[l] = val  # 将桶中的元素放回列表
                l += 1  # 移动到列表中的下一个位置
        base *= 10  # 将基数乘以10,处理下一个位数
        
    return lst  # 返回排序后的列表

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

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

相关文章

如何实现数字孪生?看这篇就够了

数字孪生&#xff08;Digital Twin&#xff09;是一种集成了物理世界和数字世界的先进概念&#xff0c;通过高精度的模拟来反映现实世界的实体或系统。它利用物联网&#xff08;IoT&#xff09;、大数据、人工智能&#xff08;AI&#xff09;、云计算等先进技术&#xff0c;实现…

应对AI挑战的职业发展与培训策略

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;各行各业正经历着前所未有的变革。为了在这场变革中保持竞争力并实现个人职业发展&#xff0c;职场人士需要积极应对AI带来的挑战&#xff0c;通过制定有效的职业发展与培训策略来不断提升自我。以下是几个关…

大数据决策分析平台建设方案(可编辑的56页PPT)

引言&#xff1a;在当今信息爆炸的时代&#xff0c;大数据已成为企业决策制定、业务优化与市场洞察的重要驱动力。为了充分挖掘大数据的潜在价值&#xff0c;提升决策效率与精准度&#xff0c;构建一套高效、灵活、可扩展的大数据决策分析平台显得尤为重要。通过大数据分析平台…

佰朔资本:沪指跌0.23%,金融板块集体上扬,半导体等板块下挫

6日早盘&#xff0c;沪指盘中轰动回落&#xff0c;深证成指、创业板指弱势下探&#xff0c;上证50指数逆市上扬&#xff0c;场内超4400股飘绿。 到午间收盘&#xff0c;沪指跌0.23%报2782点&#xff0c;深证成指跌1.01%&#xff0c;创业板指跌1.29%&#xff0c;上证50指数微涨…

不小心删除丢失了所有短信?如何在 iPhone 上查找和恢复误删除的短信

不小心删除了一条短信&#xff0c;或者丢失了所有短信&#xff1f;希望还未破灭&#xff0c;下面介绍如何在 iPhone 上查找和恢复已删除的短信。 短信通常都是非正式和无关紧要的&#xff0c;但短信中可能包含非常重要的信息。因此&#xff0c;如果您删除了一些短信以清理 iPh…

LeetCode第414场周赛(第一题)

目录 一&#xff1a;题目&#xff1a;3280. 将日期转换为二进制表示 一&#xff1a;题目&#xff1a;3280. 将日期转换为二进制表示 给你一个字符串 date&#xff0c;它的格式为 yyyy-mm-dd&#xff0c;表示一个公历日期。 date 可以重写为二进制表示&#xff0c;只需要将年…

idea创建一个spring项目,并编写一个初级spring项目实战(全网最详细)

1.创建spring项目 创建后界面显示 2.再pom.xml文件中添加Spring框架依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.10</version> </dependency> 注意&…

Spring中FactoryBean的高级用法实战

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

AT3340-6T杭州中科微BDS定位授时板卡性能指标

AT3340-6T是一款高性能多系统卫星定位安全授时板卡&#xff0c;可通过配置支持各个单系统的定位授时。 外观尺寸&#xff1a; 电气参数 应用领域&#xff1a; 通信基站授时 电力授时 广播电视授时 轨道系统授时 金融系统授时 其他授时应用 注意事项&#xff1a; 为了充分发挥…

nvidia-smi命令视图含义

第一部分&#xff1a;NVIDIA-SMI 标题 ---------------------------------------------------------------------------------------- | NVIDIA-SMI 555.42.06 Driver Version: 555.42.06 CUDA Version: 12.5 | ------------------------------------------------------------…

ML 系列:机器学习和深度学习的深层次总结(01)

​ 文章目录 一、说明二、人工智能和机器学习三、机器学习的类型四、结论 一、说明 欢迎学习机器学习系列。这门综合课程目前包括40个部分&#xff0c;指导您了解机器学习、统计和数据分析的基本概念和技术。以下是到目前为止涵盖的关键主题的简要概述&#xff1a; 1 机器学习…

C与汇编之间的相互调用(29)

1 先来看一下 基本的调用规则。 注意&#xff1a; 程序通过 r1 -r4 来保存 传递的参数&#xff0c;如果 超过了 4个参数怎么办&#xff0c; 那就 放到栈里面。 注意&#xff1a; 堆栈是满递减&#xff0c; FD。 子程序的返回结果 会放到R0 里面。 2 然后是 c 语言调用 汇编语言…

如何最好地制定自动化测试策略

尽管不能否认手动测试的价值&#xff0c;自动化测试的需求却在不断增长。自动化测试可以为公司和团队带来许多好处&#xff1a;时间效率高、覆盖面广。 如何最好地制定自动化测试策略呢&#xff1f; 在本文中&#xff0c;我将展示测试自动化策略的所有7个阶段中的一些最佳实践…

gpt4最新保姆级教程

如何使用 WildCard 服务注册 Claude3 随着 Claude3 的震撼发布&#xff0c;最强 AI 模型的桂冠已不再由 GPT-4 独揽。Claude3 推出了三个备受瞩目的模型&#xff1a;Claude 3 Haiku、Claude 3 Sonnet 以及 Claude 3 Opus&#xff0c;每个模型都展现了卓越的性能与特色。其中&a…

LLM - 理解 多模态大语言模型 (MLLM) 的发展与相关技术 (一)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142063880 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 多模态…

揭秘世界上那些同时横跨两大洲的国家

我们在《世界人口过亿的一级行政区分布》盘点全球是那些人口过亿的一级行政区。 现在我们介绍五个横跨两州的国家&#xff0c;并整理七大洲和这些国家的KML矢量数据分析分享给大家&#xff0c;如果你需要这些数据&#xff0c;请在文末查看领取方式。 世界上横跨两大洲的国家 …

【Python报错已解决】SyntaxError: positional argument follows keyword argument

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一&#xff1a;调整参数顺序2.2 步骤二…

excel分列

Excel中有这么几列&#xff0c;希望将每一列内容再分出3列&#xff1a; 可以通过以下步骤在 Excel 表格中将 B 到 F 列的内容拆分为每列的 3 列&#xff0c;分别为 pred_label、pred_score 和 pred_class&#xff1a; 确定数据结构&#xff1a;假设 B 列到 F 列中的内容都是按类…

洛谷 P10798 「CZOI-R1」消除威胁

题目来源于&#xff1a;洛谷 题目本质&#xff1a;贪心&#xff0c;st表&#xff0c;单调栈 解题思路&#xff1a;由于昨天联练习了平衡树&#xff0c;我就用平衡树STL打了个暴力&#xff0c;超时得了30分 这是暴力代码&#xff1a; #include<bits/stdc.h> using name…

小琳AI课堂:多模态模型的训练与应用

引言 大家好&#xff0c;这里是小琳AI课堂。今天我们将探讨一个热门且前沿的话题——多模态模型的训练与应用。让我们一起走进这个复杂而精致的艺术创作过程&#xff01; 训练关键步骤 1. 数据收集与预处理 准备工作&#xff1a;从多种来源和模态收集数据&#xff0c;如文…