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

算法编程题-排序

算法编程题-排序

    • 比较型排序算法
      • 冒泡排序
      • 选择排序
      • 插入排序
      • 希尔排序
      • 堆排序
      • 快速排序
      • 归并排序
    • 非比较型排序算法
      • 计数排序
      • 基数排序

本文将对七中经典比较型排序算法进行介绍,并且给出golang语言的实现,还包括基数排序、计数排序等非比较型的算法的介绍和实现。

比较型排序算法

所谓的比较型排序算法就是算法中会使用数据之间的比较,只能数组保存的是能相关比较大小的数据即可使用该类算法,相比于非比较型排序算法适用面更广。
在实现上进行了一定的封装,支持泛型和自定义排序规则,默认传入一个比较函数less,按照less指定的小于关系进行“从小到大”排序。抽象接口代码如下:

type Sorter[T any] struct {less func(item1, item2 T) bool
}func NewSorter[T any](less func(item1, item2 T) bool) *Sorter[T] {return &Sorter[T]{less: less}
}

冒泡排序

冒泡排序如其名,就是排序的过程和冒泡有点像。一个气泡从水底浮向水面,其体积是越来越大的。那么同理,在排序的过程中,也可以让一个个大的元素浮上去,从而完成整个的排序。代码实现如下:

// BubbleSort 冒泡排序,时间复杂度:O(n^2) 空间复杂度:O(1), 稳定
func (s *Sorter[T]) BubbleSort(arr []T) {n := len(arr)for i := 0; i < n; i++ {var bubbleFlag bool // 是否有冒泡for j := i; j+1 < n; j++ {if s.less(arr[j+1], arr[j]) {arr[j], arr[j+1] = arr[j+1], arr[j]bubbleFlag = true}}if !bubbleFlag { // 无冒泡,说明已经排序完成,提前退出break}}
}

冒泡排序时间复杂度是 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( 1 ) O(1) O(1)。其是一种稳定的排序算法。在实现上可以记录一个标志,表明此一轮有没有发生冒泡,如果没有,说明数组已经完全有序,可以以前退出。

选择排序

选择排序同样也是人如其名,在每一轮中,选择剩余数组中的最小值,放入一个位置,经过n轮,完成排序。实现代码如下:

// SelectSort 选择排序,时间复杂度:(n ^ 2), 空间复杂度:O(1),不稳定
func (s *Sorter[T]) SelectSort(arr []T) {n := len(arr)for i := 0; i < n; i++ {minPtr := ifor j := i + 1; j < n; j++ {if s.less(arr[j], arr[minPtr]) {minPtr = j}}arr[minPtr], arr[i] = arr[i], arr[minPtr]}
}

选择排序时间复杂度 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( 1 ) O(1) O(1),是一种不稳定的排序算法。

插入排序

插入排序的排序过程为:维护一个有序序列,然后将待排序的数字找到一个合适的位置,然后插入进去,这样还是一个有序序列,依次将所有元素完成这一个操作,即可完成数组的排序。实现代码如下:

// InsertSort 插入排序,时间复杂度:O(n^2) 空间复杂度:O(1), 稳定
func (s *Sorter[T]) InsertSort(arr []T) {n := len(arr)for i := 1; i < n; i++ {for j := i; j > 0; j-- {if s.less(arr[j], arr[j-1]) {arr[j], arr[j-1] = arr[j-1], arr[j]} else {break}}}
}

插入排序的时间复杂度平均为 O ( n 2 ) O(n^2) O(n2),但是对于一个基本有序的数组进行排序,时间复杂度可以达到 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1),是一种稳定的排序算法。
优化插入排序,可以从两个方面入手,减少找位置的时间或者移动元素的时间,每一轮这两个的时间都是 O ( n ) O(n) O(n)级别的,前者可以通过二分查找来优化,后者可以通过链表来优化,但是如何同时优化呢?笔者认为可以使用跳表,这样可以将插入排序的平均时间复杂度优化到 O ( n l o g n ) O(nlogn) O(nlogn),但是缺点在于实现复杂,且空间开销较大,相比于快速排序堆排序等,有点得不偿失。

希尔排序

希尔排序其实就是对于插入排序的优化,前文提到,插入排序在基本有序的数组排序效率比较高,那么可以考虑对于数组的子序列进行排序,具体的思路就是将子数组分为多个子序列,在每一轮中只对子序列内部进行插入排序。子序列分组的规则是每隔gap个的元素作为一个子序列,gap值在轮数下不断减小,直到为一后相当于是对全部数据进行插入排序,由于此时数组已经基本有序,所以最后一轮插入排序的效率很高。

// 希尔排序,时间复杂度: O(n^(3 / 2)) 空间复杂度:O(1), 不稳定
func (s *Sorter[T]) ShellSort(arr []T) {n := len(arr)gap := n >> 1for gap > 0 {for i := 0; i < gap; i++ {for j := i; j < n; j += gap {for k := i + gap; k < n; k += gap {if s.less(arr[k], arr[k-gap]) {arr[k], arr[k-gap] = arr[k-gap], arr[k]}}}}gap >>= 1}
}

希尔排序的时间复杂度为 O ( n 3 / 2 ) O(n ^ {3 / 2}) O(n3/2),但是最坏情况下也可能恶化成 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( 1 ) O(1) O(1),是一种不稳定的排序算法,适用于中等规模的数据集排序。

堆排序

堆排序就是基于堆这种数据结构的性质,往往使用一个最小堆,将堆顶的元素取出,然后将最后一个元素放到堆顶后,从上到下进行调整,重复这一个过程,就能完成数组的排序。

type Heap[T any] struct {less   func(item1, item2 T) boolarray  []Tlength int // 标识实际长度
}// NewHeap 构建一个空的堆
func NewHeap[T any](less func(item1, item2 T) bool) *Heap[T] {return &Heap[T]{less: less, array: make([]T, 0), length: 0}
}// NewHeapWithArr 根据数组构建一个堆
func NewHeapWithArr[T any](less func(item1, item2 T) bool, arr []T) *Heap[T] {h := &Heap[T]{less: less, array: arr, length: len(arr)}for i := 1; i < len(arr); i++ {h.siftUp(i)}return h
}// Push 往堆h中插入一个元素
func (h *Heap[T]) Push(v T) {h.pushBack(v)h.siftUp(h.length - 1)
}// Top 返回堆顶的元素
func (h *Heap[T]) Top() T {return h.array[0]
}// Pop 移除堆顶的元素并返回
func (h *Heap[T]) Pop() T {ret := h.array[0]h.array[0] = h.array[h.length-1]h.length--h.siftDown(0)return ret
}func (h *Heap[T]) ToArr() []T {return h.array
}func (h *Heap[T]) IsEmpty() bool {return h.length == 0
}// pushBack 在尾部插入一个元素
func (h *Heap[T]) pushBack(v T) {if len(h.array) == h.length {h.array = append(h.array, v)} else {h.array[h.length] = v}h.length++
}// siftUp 从pos位置处开始往上调整
func (h *Heap[T]) siftUp(pos int) {if pos < 0 || pos >= h.length {return}i := posj := (pos - 1) / 2for j >= 0 && h.less(h.array[i], h.array[j]) {h.array[i], h.array[j] = h.array[j], h.array[i]i = jj = (i - 1) / 2}
}// siftDown 从pos位置处开始往下调整
func (h *Heap[T]) siftDown(pos int) {if pos < 0 || pos >= len(h.array) {return}i := 0j1 := 2*i + 1j2 := 2*i + 2for j1 < h.length {if h.less(h.array[j1], h.array[i]) && ((j2 >= h.length) || h.less(h.array[j1], h.array[j2])) {h.array[i], h.array[j1] = h.array[j1], h.array[i]i = j1} else if h.less(h.array[j2], h.array[i]) {h.array[i], h.array[j2] = h.array[j2], h.array[i]i = j2} else {break}j1 = 2*i + 1j2 = 2*i + 2}
}// HeapSort 堆排序,时间复杂度:O(nlogn), 空间复杂度:O(1), 不稳定
func (s *Sorter[T]) HeapSort(arr []T) {h := NewHeapWithArr(s.less, arr)k := len(arr) - 1for !h.IsEmpty() {arr[k] = h.Pop()k--}for i := 0; i < len(arr) / 2; i++ {arr[i], arr[len(arr) - 1 - i] = arr[len(arr) - 1 - i], arr[i]}
}

堆排序的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度为 O ( n ) O(n) O(n),是一种不稳定的排序算法,适用于大数据量下且内存资源相对宝贵的条件下。

快速排序

快速排序是一种基于分制的思路,对于一个数组,从中选择一个基准点,以这个基准点,小于的数交换到左边取,大于的数交换到右边去,然后递归地对左边和右边的子数组进行同样的处理,从而完成整个排序过程。

// 快速排序实现,时间复杂度:O(nlogn), 空间复杂度:O(1), 不稳定
func (s *Sorter[T]) QuickSort(arr []T) {s.quickSortV1(arr, 0, len(arr)-1)
}// 递归形式的排序
func (s *Sorter[T]) quickSortV1(arr []T, left, right int) {if left >= right { // 递归终点return}base := arr[left]basePtr := lefti := left + 1for i <= right {if s.less(arr[i], base) {basePtr++if basePtr != i {arr[basePtr], arr[i] = arr[i], arr[basePtr]}}i++}arr[left] = arr[basePtr]arr[basePtr] = bases.quickSortV1(arr, left, basePtr-1)s.quickSortV1(arr, basePtr+1, right)
}

以上实现版本的快速排序时间复杂度是 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度为 O ( 1 ) O(1) O(1),是一种不稳定的排序算法,但是最坏情况下时间复杂度也会恶化到 O ( n 2 ) O(n^2) O(n2)。比如上面的实现在数组基本有序的情况下,会化身为时间刺客,如下图。

在这里插入图片描述
一种常见的优化手段是从数组中取三个数字,然后以这三个数字的中位数作为基准点,如下为相关代码实现:

// quickSortV3优化实现,基准取头尾中三数中的平均数
func (s *Sorter[T]) quickSortV3(arr []T, left, right int) {if left >= right { // 递归终点return}s.adjustBase(arr, left, right)base := arr[left]basePtr := lefti := left + 1for i <= right {if s.less(arr[i], base) {basePtr++if basePtr != i {arr[basePtr], arr[i] = arr[i], arr[basePtr]}}i++}arr[left] = arr[basePtr]arr[basePtr] = bases.quickSortV3(arr, left, basePtr-1)s.quickSortV3(arr, basePtr+1, right)
}// adjustBase 调整基准值,将头尾中三数中的平均数放在头部作为基准
func (s *Sorter[T]) adjustBase(arr []T, left, right int) {basePtrs := []int{left, right, (left + right) / 2}s1 := NewSorter(func(i, j int) bool {return s.less(arr[i], arr[j])})s1.InsertSort(basePtrs)arr[left], arr[basePtrs[1]] = arr[basePtrs[1]], arr[left]
}

但是以上方法对于一个全是相同数字的数组还是会恶化成 O ( n 2 ) O(n^2) O(n2)
在某些面试中,可能有些面试官要求实现一些递归算法的非递归版本,比如实现非递归版本的快速排序。递归在编程语言中的实质就是借助栈来实现的,所以这种题目本质上就是在模拟递归,代码实现如下:

// 非递归实现,借助栈来模拟递归
func (s *Sorter[T]) quickSortV2(arr []T, left, right int) {stack := NewStack[[2]int]()stack.Push([2]int{left, right})for !stack.IsEmpty() {state := stack.Pop()left, right := state[0], state[1]if left >= right {continue}base := arr[left]basePtr := lefti := left + 1for i <= right {if s.less(arr[i], base) {basePtr++if basePtr != i {arr[basePtr], arr[i] = arr[i], arr[basePtr]}}i++}arr[left] = arr[basePtr]arr[basePtr] = basestack.Push([2]int{left, basePtr - 1})stack.Push([2]int{basePtr + 1, right})}
}

实际上,也可以不使用栈,使用队列或者其他的数据结构都是可以的。

归并排序

归并排序的重点在于归并上,对于两个已经有序的数组而言,可以合并到一个有序的数组中,时间复杂度为 O ( n ) O(n) O(n),这样,最小的段即一个数的数组,必然是有序的,小段合成大段,最后合并完成整个数组的排序。

// MergeSort 归并排序,时间复杂度:O(nlogn), 空间复杂度:O(n), 稳定
func (s *Sorter[T]) MergeSort(arr []T) []T {return s.mergeSortV1(arr)
}// 递归形式的归并排序
func (s *Sorter[T]) mergeSortV1(arr []T) []T {if len(arr) <= 1 { // 递归终点return arr}// 递归过程leftArr := s.mergeSortV1(append([]T(nil), arr[:len(arr)/2]...))rightArr := s.mergeSortV1(append([]T(nil), arr[len(arr)/2:]...))// 合并i := 0j := 0k := 0for i < len(leftArr) || j < len(rightArr) {if i >= len(leftArr) || (j < len(rightArr) && s.less(rightArr[j], leftArr[i])) {arr[k] = rightArr[j]j++k++} else {arr[k] = leftArr[i]i++k++}}return arr
}

归并排序也可以实现非递归的形式,如下:

// 非递归形式的归并排序
func (s *Sorter[T]) mergeSortV2(arr []T) []T {segLen := 1 // 比较的段长for segLen < len(arr) {for p := 0; p < len(arr); p += 2 * segLen {leftArr := append([]T(nil), arr[p:min(p+segLen, len(arr))]...)rightArr := append([]T(nil), arr[min(p+segLen, len(arr)):min(p+2*segLen, len(arr))]...)// 合并i := 0j := 0k := 0for i < len(leftArr) || j < len(rightArr) {if i >= len(leftArr) || (j < len(rightArr) && s.less(rightArr[j], leftArr[i])) {arr[p+k] = rightArr[j]j++k++} else {arr[p+k] = leftArr[i]i++k++}}}segLen *= 2}return arr
}

归并排序时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度为 O ( n ) O(n) O(n),是一种稳定的排序算法。归并排序适用于大数据量且要求稳定的场景,毕竟同时间复杂度的排序算法快速排序和堆排序都是不稳定的。

非比较型排序算法

可以注意到以上的排序算法都需要通过比较元素的大小来交换位置或者其他的操作,这类算法统称为比较型排序算法。另外一类非比较型排序算法,不需要比较大小,但是其适用面比较小。

计数排序

所谓的计数排序就是维护一个数组,用来表示每一个元素出现的次数,然后遍历数组,将各个数字取出即可。

type IntSorter struct {
}func NewIntSorter() *IntSorter {return &IntSorter{}
}// 计数排序,时间复杂度:O(n+k) k为数据范围 空间复杂度:O(k) 稳定
// 适用于数据范围不大的情况下
func (s *IntSorter) CountSort(arr []int64) {minv := arr[0]maxv := arr[0]for _, item := range arr {minv = min(minv, item)maxv = max(maxv, item)}counts := make([]int64, maxv-minv+1)for _, item := range arr {counts[item-minv]++}k := 0for i := int64(0); i < maxv-minv+1; i++ {for j := int64(0); j < counts[i]; j++ {arr[k] = i + minvk++}}
}

计数排序的时间复杂度为 O ( n ) O(n) O(n)级别,空间复杂度为 O ( m ) O(m) O(m),其中m为数组中最大数减去最小数,可以看到,计数排序只适用于整数,且最好数据比较集中。

基数排序

以整数的基数排序来说明这一个过程。由于整数的每一位只有十种可能,从0到9,那么可以建立十个桶,遍历数组,按照最低位对应的数字放到对应的桶中,然后再将所有数组按照0号桶收集起来,然后从数字的低第二位做重复的操作,直到最大数字的最高位。代码实现如下:

func (s *IntSorter) RadixSort(arr []int) {var newBuckets func() []*List[int] = func() []*List[int] {buckets := make([]*List[int], 10)for i := 0; i < 10; i++ {buckets[i] = NewList[int]()}return buckets}buckets := newBuckets()oldBuckets := newBuckets()for _, num := range arr {oldBuckets[num%10].AppendNodeTail(NewListNode[int](num/10, num))}flag := true // 停止标志for flag {flag = falsefor i := 0; i < 10; i++ {for node := oldBuckets[i].Begin(); node != oldBuckets[i].End(); node = node.Next {if node.Key != 0 {flag = true}buckets[node.Key%10].AppendNodeTail(NewListNode[int](node.Key/10, node.Val))}}oldBuckets = bucketsbuckets = newBuckets()}// 此时所有数据都在零号桶里k := 0for node := oldBuckets[0].Begin(); node != oldBuckets[0].End(); node = node.Next {arr[k] = node.Valk++}
}

基数排序的时间复杂度也大致在 O ( n m ) O(nm) O(nm)左右,对于整数可以认为是 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n),适用于整数或者字符串等。

相关文章:

算法编程题-排序

算法编程题-排序 比较型排序算法冒泡排序选择排序插入排序希尔排序堆排序快速排序归并排序 非比较型排序算法计数排序基数排序 本文将对七中经典比较型排序算法进行介绍&#xff0c;并且给出golang语言的实现&#xff0c;还包括基数排序、计数排序等非比较型的算法的介绍和实现…...

【AIGC】如何准确引导ChatGPT,实现精细化GPTs指令生成

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | 提示词Prompt应用实例 文章目录 &#x1f4af;前言&#x1f4af;准确引导ChatGPT创建爆款小红书文案GPTs指令案例&#x1f4af; 高效开发GPTs应用的核心原则明确应用场景和目标受众构建多样化风格模板提问与引导技巧持续优…...

【Axure高保真原型】或和且条件

今天和大家分享或和且条件案例的原型模板&#xff0c;效果包括&#xff1a; 可以选择指标、等式和填写对应值构成条件等式&#xff1b; 点击添加条件按钮&#xff0c;可以增加一行新的条件&#xff1b; 点击所在行的号按钮&#xff0c;可以在该行下方添加一行新的条件&#x…...

KubeVirt下gpu operator实践(GPU直通)

KubeVirt下gpu operator实践(GPU直通) 参考《在 KubeVirt 中使用 GPU Operator》&#xff0c;记录gpu operator在KubeVirt下实践的过程&#xff0c;包括虚拟机配置GPU直通&#xff0c;容器挂载GPU设备等。 KubeVirt 提供了一种将主机设备分配给虚拟机的机制。该机制具有通用性…...

Vue通过file控件上传文件到Node服务器

功能&#xff1a; 1.多文件同时上传、2.拖动上传、3.实时上传进度条、4.中断上传和删除文件、5.原生file控件的美化 搁置的功能: 上传文件夹、大文件切片上传、以及其他限制条件未处理 Node服务器的前置准备: 新建文件夹: file_upload_serve初始化npm: npm …...

如何在 SQL Server 中新增账户并指定数据库权限

在日常的数据库维护与开发中,管理用户的权限是必不可少的一环。本文将指导你如何在 SQL Server 中为新用户创建账户,并为其指定相应的数据库权限,使其只能查看有权访问的数据。我们将以步骤和代码示例的方式展示整个流程。用户权限分配包括:读取权限、写入权限、执行权限。…...

c#编码技巧(十九):各种集合特点汇总

.NET 常用集合对比&#xff1a; .NET 常见的线程安全集合 .NET 只读集合...

汽车软件DevOps解决方案

汽车软件DevOps解决方案是专为现代汽车行业设计的一套集成化需求、开发、测试、部署、OTA与监控&#xff0c;旨在加速软件开发流程&#xff0c;提高软件质量和安全性&#xff0c;同时确保整个生命周期的高效性和灵活性。以下是经纬恒润汽车软件DevOps解决方案的关键组成部分和优…...

同步的意义以及机制

一、同步的意义 同步&#xff08;Synchronization&#xff09;的意义在于确保在多线程环境中&#xff0c;多个线程对共享资源的访问是安全的&#xff0c;避免竞争条件&#xff08;race conditions&#xff09;和数据不一致的情况。 具体来说&#xff0c;同步的核心目标是&…...

leetcode 面试150之 156.LUR 缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则返回 -…...

启发式搜索算法复现

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月21日19点05分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文链接 点击开启你的论文编程之旅…...

【IDE】使用指南

定期更新实用技能&#xff0c;建议关注收藏点赞。 友情链接&#xff1a; 点击跳转常见代码编辑器的报错解决方案 目录 常用快捷键pycharm右下角边栏脚本头安装IDE的插件git配置TODO 代码编辑器里有许多小技巧&#xff0c;便于办公。本篇主要以pycharm,vscode等主流常用IDE为…...

设计编程网站集:简述可扩展性系统设计(笔记)

视频连接&#xff1a;简述可扩展性系统设计 三个关键原则 无状态 松散耦合 异步处理 扩展 负载均衡 缓存 分片...

「Mac玩转仓颉内测版25」基础篇5 - 布尔类型详解

本篇将介绍 Cangjie 中的布尔类型&#xff0c;包括布尔值的定义、运算操作符、逻辑运算、布尔类型的常见应用场景及其在条件判断中的应用&#xff0c;帮助开发者理解和使用布尔类型。 关键词 布尔类型定义布尔运算逻辑运算符条件判断常见应用场景 一、布尔类型概述 布尔类型&…...

Fashion-VDM:引领视频虚拟试穿技术的新篇章

引言 随着虚拟现实和增强现实技术的飞速发展,视频虚拟试穿(VVT)已成为时尚产业的一大创新领域。然而,现有的VVT方法在服装细节和时间一致性方面仍存在诸多不足。为了解决这些问题,Johanna Karras等人提出了Fashion-VDM,一种基于视频扩散模型(VDM)的新型视频虚拟试穿技…...

Scala中的集合复习(1)

Map、Set、Array、List 一、集合的三大类 1.序列Seq表示有先后顺序的集合。&#xff08;Array、List&#xff09; 2.集Set&#xff1a;表示无序且不重复的集合。 3.映射Map&#xff1a;表示键值对。 Stack&#xff1a;栈&#xff0c;特点是&#xff1a;后进先出。 packag…...

Java依赖包漏洞检测命令

1、漏洞扫描工具 maven插件方式&#xff1a;Dependency-Check 2、命令 检查单个 Maven 工程的安全漏洞 mvn dependency-check:check 这个命令会在 target 目录下生成一个 dependency-check-report.html 文件&#xff0c;其中包含了依赖项的安全漏洞分析报告。 检查多个 M…...

【Java】强制类型转换

int a23; short b(short) a; 小的接受大的接受不了&#xff0c;强制类型转换. 带有Buffer的&#xff0c;带有流的&#xff0c;都是数组。 网络流&#xff0c;文件流都是数组. 这种就是流。 操作系统底层就是C. 没有直系关系的&#xff0c;不让转换 语法不报错&#xff0c;运行…...

RabbitMQ消息可靠性保证机制4--消费端限流

7.7 消费端限流 在类似如秒杀活动中&#xff0c;一开始会有大量并发写请求到达服务端&#xff0c;城机对消息进行削峰处理&#xff0c;如何做&#xff1f; 当消息投递的速度远快于消费的速度时&#xff0c;随着时间积累就会出现“消息积压”。消息中间件本身是具备一定的缓冲…...

查找萤石云IOS Sdk中的编解码接口

2021/1/20 以前的时候&#xff0c;碰到的问题&#xff0c;想把萤石云视频介入到TRTC&#xff0c;但是... 萤石云的IOS接口中没有相应的解码播放库&#xff0c;也就是找不到PlayerSDK对应部分&#xff0c;怎么做呢&#xff1f; 一个是坐等萤石云开放这部分接口&#xff0c;可能…...

erchas

#include <iostream> #include <vector> https://gitee.com/tongchaowei/front-native-page-template/tree/main/image-display/template-01 using namespace std; class BinaryTree { private: vector<char> tree; // 存储二叉树的数组 int size;…...

【网络安全】SSL(一):为什么需要 Keyless SSL?

未经许可,不得转载。 文章目录 背景正文背景 随着网站和应用程序向云端迁移,使用 HTTPS(SSL/TLS)加密流量已成为行业标准。然而,传统的 HTTPS 配置要求服务器持有网站的私钥,这在云计算环境中引发了一系列安全性和合规性问题。一旦云服务器遭到攻击,私钥泄露可能带来不…...

ggplot2 分面图等添加注释文字,相加哪里加哪里: 自定义函数 AddText()

如果分面图上还想再添加文字&#xff0c;只能使用底层的grid包了。 函数定义 # Add text to ggplot2 figures # # param label text you want to put on figure # param x position x, left is 0, right 1 # param y position y, bottom is 0, up 1 # param color text color…...

解读缓存问题的技术旅程

目录 前言1. 问题的突发与初步猜测2. 缓存的“隐身术”3. 缓存策略的深层优化4. 反思与感悟结语 前言 那是一个普通的工作日&#xff0c;团队例行的早会刚刚结束&#xff0c;我正准备继续优化手头的模块时&#xff0c;突然收到了用户反馈。反馈的内容是部分数据显示异常&#…...

洛谷P1597

语句解析 - 洛谷 语句解析 题目背景 木有背景…… 题目描述 一串长度不超过255的 PASCAL 语言代码&#xff0c;只有 a,b,c 三个变量&#xff0c;而且只有赋值语句&#xff0c;赋值只能是一个一位的数字或一个变量&#xff0c;每条赋值语句的格式是 [变量]:[变量或一位整数…...

2411rust,76~79

1.76.0稳定版 此版本较小 ABI兼容更新 函数指针文档中新增的ABI兼容部分介绍了函数签名与ABI兼容的意义.大部分是参数类型和返回类型的兼容,及在当前Rust中兼容的列表.文档仅描述现有兼容的状态. 一个新增功能是,现在保证符和u32是ABI兼容的.它们一直有相同大小和对齐方式,…...

vue2.0前端管理系统界面布局设置

前言 后台管理系统的核心就是用户管理、角色管理&#xff08;含权限分配&#xff09;、菜单管理&#xff0c;以及一些业务管理。业务管理通常以及根据不同的角色进行了权限分配。本次任务完成用户管理页面。 一 界面设计 1.引用Element 的Container 布局容器。 以上次博客中…...

4. SQL视图

MySQL中的视图&#xff08;View&#xff09;是一种虚拟表&#xff0c;本质是存储了一条SELECT语句。视图并不直接存储数据&#xff0c;而是动态生成结果集&#xff0c;帮助开发者简化查询逻辑和增强数据安全性。本文将从视图的基础概念到实际应用&#xff0c;逐步深入地探讨如何…...

Simulink学习笔记【PID UG联动仿真】

Simulink进行PID控制及调参&#xff1a; 建立系统动力学框图&#xff08;把状态方程翻译出来&#xff09;&#xff0c;设置成subsystem建立PID反馈回路。示波器叫scope&#xff0c;多变量输出用demux和mux。可以用自动调参Tune模块&#xff0c;调整响应速度和稳定性&#xff0…...

【Python】30个Python爬虫的实战项目!!!(附源码)

Python爬虫是数据采集自动化的利器。本文精选了30个实用的Python爬虫项目&#xff0c;从基础到进阶&#xff0c;每个项目都配有完整源码和详细讲解。通过这些项目的实战&#xff0c;可以全面掌握网页数据抓取、反爬处理、并发下载等核心技能。 一、环境准备 在开始爬虫项目前…...

网站视频怎么做的好处/各平台推广费用

过去有很多网页设计师喜欢将他们的网页效果图用table布局实现成网页&#xff0c;但是这样做会遇到一个比较麻烦的问题就是&#xff0c;后期调试和维护会相当的困难。现在&#xff0c;越来越多的前端开发er们开始使用xHTML CSS替代最初的table布局完成网页的整体布局&#xff0c…...

wordpress调用服务器/如何开网站呢

idstart_timeperiod_ytpeperiod_value11461427200day321461427200month2如上表&#xff0c;start_time 表示开始时间&#xff0c;period_ytpe 表示期限类型&#xff0c;period_value表示期限值&#xff0c;第一第记录表是 3天&#xff0c;第二条表示2个月如果查询出&#xff0c…...

扬州企业网站建设/重庆百度快速优化

sessionStorage作为HTML5的Web Storage的两种存储方式之一。 用于本地存储一个会话&#xff08;session&#xff09;中的数据&#xff0c;这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据会被销毁。 不是一种持久化的本地存储。 会话级的存储。1、接口…...

深圳网站建设 site/盘古百晋广告营销是干嘛

一般编程语言中喜欢用符号来判断java中两个字符串是否相等&#xff0c;例如c。c提供了操作符的重载&#xff0c;所以可以重载运算符来判断。 但是由于java中&#xff0c;没有提供运算符重载&#xff0c;而且java中没有提供基本的string类型、也没有把string看成char数组&#x…...

税务网站怎样查询建设项目/aso优化是什么意思

背景: 我手头有个项目,因为之前没注意&#xff0c;把公网环境的IP地址&#xff0c;数据库写到了Github。 但是项目已经提交100多次.这个时候我只想单纯的把这个application-test.yml删掉&#xff0c;包括历史记录 网上一大堆&#xff0c;都感觉是一个人写的&#xff0c;全部…...

三合一网站选什么系统/seo网络优化软件

变形转换 属性&#xff1a;transfrom 1.Translate----位移 概念 该属性值可以让元素从当前位置根据X轴Y轴&#xff0c;在水平和垂直方向进行移动。 注意&#xff1a; 在浏览器中一般只要说到x,y轴&#xff0c;那么基本是都是以下面方式计算原点和方向 原点&#xff1a; 元素…...