01.Linked-List-Sort

1. 链表排序简介

在数组排序中,常见的排序算法有:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序等。

而对于链表排序而言,因为链表不支持随机访问,访问链表后面的节点只能依靠 next 指针从头部顺序遍历,所以相对于数组排序问题来说,链表排序问题会更加复杂一点。

下面先来总结一下适合链表排序与不适合链表排序的算法:

  • 适合链表的排序算法:冒泡排序选择排序插入排序归并排序快速排序计数排序桶排序基数排序
  • 不适合链表的排序算法:希尔排序
  • 可以用于链表排序但不建议使用的排序算法:堆排序

希尔排序为什么不适合链表排序?

希尔排序:希尔排序中经常涉及到对序列中第 i + gap 的元素进行操作,其中 gap 是希尔排序中当前的步长。而链表不支持随机访问的特性,导致这种操作不适合链表,因而希尔排序算法不适合进行链表排序。

为什么不建议使用堆排序?

堆排序:堆排序所使用的最大堆 / 最小堆结构本质上是一棵完全二叉树。而完全二叉树适合采用顺序存储结构(数组)。因为数组存储的完全二叉树可以很方便的通过下标序号来确定父亲节点和孩子节点,并且可以极大限度的节省存储空间。

而链表用在存储完全二叉树的时候,因为不支持随机访问的特性,导致其寻找子节点和父亲节点会比较耗时,如果增加指向父亲节点的变量,又会浪费大量存储空间。所以堆排序算法不适合进行链表排序。

如果一定要对链表进行堆排序,则可以使用额外的数组空间表示堆结构。然后将链表中各个节点的值依次添加入堆结构中,对数组进行堆排序。排序后,再按照堆中元素顺序,依次建立链表节点,构建新的链表并返回新链表头节点。

需要用到额外的辅助空间进行排序的算法

刚才我们说到如果一定要对链表进行堆排序,则需要使用额外的数组空间。除此之外,计数排序、桶排序、基数排序都需要用到额外的数组空间。

接下来,我们将对适合链表排序的 8 种算法进行一一讲解。当然,这些排序算法不用完全掌握,重点是掌握 「链表插入排序」「链表归并排序」 这两种排序算法。

2. 链表冒泡排序

2.1 链表冒泡排序算法描述

  1. 使用三个指针 node_inode_jtail。其中 node_i 用于控制外循环次数,循环次数为链节点个数(链表长度)。node_jtail 用于控制内循环次数和循环结束位置。

  2. 排序开始前,将 node_inode_j 置于头节点位置。tail 指向链表末尾,即 None

  3. 比较链表中相邻两个元素 node_j.valnode_j.next.val 的值大小,如果 node_j.val > node_j.next.val,则值相互交换。否则不发生交换。然后向右移动 node_j 指针,直到 node_j.next == tail 时停止。

  4. 一次循环之后,将 tail 移动到 node_j 所在位置。相当于 tail 向左移动了一位。此时 tail 节点右侧为链表中最大的链节点。

  5. 然后移动 node_i 节点,并将 node_j 置于头节点位置。然后重复第 3、4 步操作。

  6. 直到 node_i 节点移动到链表末尾停止,排序结束。

  7. 返回链表的头节点 head

2.2 链表冒泡排序算法实现代码

class Solution:def bubbleSort(self, head: ListNode):node_i = headtail = None# 外层循环次数为 链表节点个数while node_i:node_j = headwhile node_j and node_j.next != tail:if node_j.val > node_j.next.val:# 交换两个节点的值node_j.val, node_j.next.val = node_j.next.val, node_j.valnode_j = node_j.next# 尾指针向前移动 1 位,此时尾指针右侧为排好序的链表tail = node_jnode_i = node_i.nextreturn headdef sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:return self.bubbleSort(head)

2.3 链表冒泡排序算法复杂度分析

  • 时间复杂度 O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度 O ( 1 ) O(1) O(1)

3. 链表选择排序

3.1 链表选择排序算法描述

  1. 使用两个指针 node_inode_jnode_i 既可以用于控制外循环次数,又可以作为当前未排序链表的第一个链节点位置。
  2. 使用 min_node 记录当前未排序链表中值最小的链节点。
  3. 每一趟排序开始时,先令 min_node = node_i(即暂时假设链表中 node_i 节点为值最小的节点,经过比较后再确定最小值节点位置)。
  4. 然后依次比较未排序链表中 node_j.valmin_node.val 的值大小。如果 node_j.val < min_node.val,则更新 min_nodenode_j
  5. 这一趟排序结束时,未排序链表中最小值节点为 min_node,如果 node_i != min_node,则将 node_imin_node 值进行交换。如果 node_i == min_node,则不用交换。
  6. 排序结束后,继续向右移动 node_i,重复上述步骤,在剩余未排序链表中寻找最小的链节点,并与 node_i 进行比较和交换,直到 node_i == None 或者 node_i.next == None 时,停止排序。
  7. 返回链表的头节点 head

3.2 链表选择排序实现代码

class Solution:def sectionSort(self, head: ListNode):node_i = head# node_i 为当前未排序链表的第一个链节点while node_i and node_i.next:# min_node 为未排序链表中的值最小节点min_node = node_inode_j = node_i.nextwhile node_j:if node_j.val < min_node.val:min_node = node_jnode_j = node_j.next# 交换值最小节点与未排序链表中第一个节点的值if node_i != min_node:node_i.val, min_node.val = min_node.val, node_i.valnode_i = node_i.nextreturn headdef sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:return self.sectionSort(head)

3.3 链表选择排序算法复杂度分析

  • 时间复杂度 O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度 O ( 1 ) O(1) O(1)

4. 链表插入排序

4.1 链表插入排序算法描述

  1. 先使用哑节点 dummy_head 构造一个指向 head 的指针,使得可以从 head 开始遍历。

  2. 维护 sorted_list 为链表的已排序部分的最后一个节点,初始时,sorted_list = head

  3. 维护 prev 为插入元素位置的前一个节点,维护 cur 为待插入元素。初始时,prev = headcur = head.next

  4. 比较 sorted_listcur 的节点值。

    • 如果 sorted_list.val <= cur.val,说明 cur 应该插入到 sorted_list 之后,则将 sorted_list 后移一位。
    • 如果 sorted_list.val > cur.val,说明 cur 应该插入到 headsorted_list 之间。则使用 prevhead 开始遍历,直到找到插入 cur 的位置的前一个节点位置。然后将 cur 插入。
  5. cur = sorted_list.next,此时 cur 为下一个待插入元素。

  6. 重复 4、5 步骤,直到 cur 遍历结束为空。返回 dummy_head 的下一个节点。

4.2 链表插入排序实现代码

class Solution:def insertionSort(self, head: ListNode):if not head or not head.next:return headdummy_head = ListNode(-1)dummy_head.next = headsorted_list = headcur = head.next while cur:if sorted_list.val <= cur.val:# 将 cur 插入到 sorted_list 之后sorted_list = sorted_list.next else:prev = dummy_headwhile prev.next.val <= cur.val:prev = prev.next# 将 cur 到链表中间sorted_list.next = cur.nextcur.next = prev.nextprev.next = curcur = sorted_list.next return dummy_head.nextdef sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:return self.insertionSort(head)

4.3 链表插入排序算法复杂度分析

  • 时间复杂度 O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度 O ( 1 ) O(1) O(1)

5. 链表归并排序

5.1 链表归并排序算法描述

  1. 分割环节:找到链表中心链节点,从中心节点将链表断开,并递归进行分割。
    1. 使用快慢指针 fast = head.nextslow = head,让 fast 每次移动 2 步,slow 移动 1 步,移动到链表末尾,从而找到链表中心链节点,即 slow
    2. 从中心位置将链表从中心位置分为左右两个链表 left_headright_head,并从中心位置将其断开,即 slow.next = None
    3. 对左右两个链表分别进行递归分割,直到每个链表中只包含一个链节点。
  2. 归并环节:将递归后的链表进行两两归并,完成一遍后每个子链表长度加倍。重复进行归并操作,直到得到完整的链表。
    1. 使用哑节点 dummy_head 构造一个头节点,并使用 cur 指向 dummy_head 用于遍历。
    2. 比较两个链表头节点 leftright 的值大小。将较小的头节点加入到合并后的链表中,并向后移动该链表的头节点指针。
    3. 然后重复上一步操作,直到两个链表中出现链表为空的情况。
    4. 将剩余链表插入到合并后的链表中。
    5. 将哑节点 dummy_dead 的下一个链节点 dummy_head.next 作为合并后的头节点返回。

5.2 链表归并排序实现代码

class Solution:def merge(self, left, right):# 归并环节dummy_head = ListNode(-1)cur = dummy_headwhile left and right:if left.val <= right.val:cur.next = leftleft = left.nextelse:cur.next = rightright = right.nextcur = cur.nextif left:cur.next = leftelif right:cur.next = rightreturn dummy_head.nextdef mergeSort(self, head: ListNode):# 分割环节if not head or not head.next:return head# 快慢指针找到中心链节点slow, fast = head, head.nextwhile fast and fast.next:slow = slow.next fast = fast.next.next # 断开左右链节点left_head, right_head = head, slow.next slow.next = None# 归并操作return self.merge(self.mergeSort(left_head), self.mergeSort(right_head))def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:return self.mergeSort(head)

5.3 链表归并排序算法复杂度分析

  • 时间复杂度 O ( n × log ⁡ 2 n ) O(n \times \log_2n) O(n×log2n)
  • 空间复杂度 O ( 1 ) O(1) O(1)

6. 链表快速排序

6.1 链表快速排序算法描述

  1. 从链表中找到一个基准值 pivot,这里以头节点为基准值。
  2. 然后通过快慢指针 node_inode_j 在链表中移动,使得 node_i 之前的节点值都小于基准值,node_i 之后的节点值都大于基准值。从而把数组拆分为左右两个部分。
  3. 再对左右两个部分分别重复第二步,直到各个部分只有一个节点,则排序结束。

6.2 链表快速排序实现代码

class Solution:def partition(self, left: ListNode, right: ListNode):# 左闭右开,区间没有元素或者只有一个元素,直接返回第一个节点if left == right or left.next == right:return left# 选择头节点为基准节点pivot = left.val# 使用 node_i, node_j 双指针,保证 node_i 之前的节点值都小于基准节点值,node_i 与 node_j 之间的节点值都大于等于基准节点值node_i, node_j = left, left.nextwhile node_j != right:# 发现一个小与基准值的元素if node_j.val < pivot:# 因为 node_i 之前节点都小于基准值,所以先将 node_i 向右移动一位(此时 node_i 节点值大于等于基准节点值)node_i = node_i.next# 将小于基准值的元素 node_j 与当前 node_i 换位,换位后可以保证 node_i 之前的节点都小于基准节点值node_i.val, node_j.val = node_j.val, node_i.valnode_j = node_j.next# 将基准节点放到正确位置上node_i.val, left.val = left.val, node_i.valreturn node_idef quickSort(self, left: ListNode, right: ListNode):if left == right or left.next == right:return leftpi = self.partition(left, right)self.quickSort(left, pi)self.quickSort(pi.next, right)return leftdef sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:if not head or not head.next:return headreturn self.quickSort(head, None)

6.3 链表快速排序算法复杂度分析

  • 时间复杂度 O ( n × log ⁡ 2 n ) O(n \times \log_2n) O(n×log2n)
  • 空间复杂度 O ( 1 ) O(1) O(1)

7. 链表计数排序

7.1 链表计数排序算法描述

  1. 使用 cur 指针遍历一遍链表。找出链表中最大值 list_max 和最小值 list_min
  2. 使用数组 counts 存储节点出现次数。
  3. 再次使用 cur 指针遍历一遍链表。将链表中每个值为 cur.val 的节点出现次数,存入数组对应第 cur.val - list_min 项中。
  4. 反向填充目标链表:
    1. 建立一个哑节点 dummy_head,作为链表的头节点。使用 cur 指针指向 dummy_head
    2. 从小到大遍历一遍数组 counts。对于每个 counts[i] != 0 的元素建立一个链节点,值为 i + list_min,将其插入到 cur.next 上。并向右移动 cur。同时 counts[i] -= 1。直到 counts[i] == 0 后继续向后遍历数组 counts
  5. 将哑节点 dummy_dead 的下一个链节点 dummy_head.next 作为新链表的头节点返回。

7.2 链表计数排序代码实现

class Solution:def countingSort(self, head: ListNode):if not head:return head# 找出链表中最大值 list_max 和最小值 list_minlist_min, list_max = float('inf'), float('-inf')cur = headwhile cur:if cur.val < list_min:list_min = cur.valif cur.val > list_max:list_max = cur.valcur = cur.nextsize = list_max - list_min + 1counts = [0 for _ in range(size)]cur = headwhile cur:counts[cur.val - list_min] += 1cur = cur.nextdummy_head = ListNode(-1)cur = dummy_headfor i in range(size):while counts[i]:cur.next = ListNode(i + list_min)counts[i] -= 1cur = cur.nextreturn dummy_head.nextdef sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:return self.countingSort(head)

7.3 链表计数排序算法复杂度分析

  • 时间复杂度 O ( n + k ) O(n + k) O(n+k),其中 k k k 代表待排序链表中所有元素的值域。
  • 空间复杂度 O ( k ) O(k) O(k)

8. 链表桶排序

8.1 链表桶排序算法描述

  1. 使用 cur 指针遍历一遍链表。找出链表中最大值 list_max 和最小值 list_min
  2. 通过 (最大值 - 最小值) / 每个桶的大小 计算出桶的个数,即 bucket_count = (list_max - list_min) // bucket_size + 1 个桶。
  3. 定义数组 buckets 为桶,桶的个数为 bucket_count 个。
  4. 使用 cur 指针再次遍历一遍链表,将每个元素装入对应的桶中。
  5. 对每个桶内的元素单独排序,可以使用链表插入排序、链表归并排序、链表快速排序等算法。
  6. 最后按照顺序将桶内的元素拼成新的链表,并返回。

8.2 链表桶排序代码实现

class ListNode:def __init__(self, val=0, next=None):self.val = valself.next = nextclass Solution:# 将链表节点值 val 添加到对应桶 buckets[index] 中def insertion(self, buckets, index, val):if not buckets[index]:buckets[index] = ListNode(val)returnnode = ListNode(val)node.next = buckets[index]buckets[index] = node# 归并环节def merge(self, left, right):dummy_head = ListNode(-1)cur = dummy_headwhile left and right:if left.val <= right.val:cur.next = leftleft = left.nextelse:cur.next = rightright = right.nextcur = cur.nextif left:cur.next = leftelif right:cur.next = rightreturn dummy_head.nextdef mergeSort(self, head: ListNode):# 分割环节if not head or not head.next:return head# 快慢指针找到中心链节点slow, fast = head, head.nextwhile fast and fast.next:slow = slow.next fast = fast.next.next # 断开左右链节点left_head, right_head = head, slow.next slow.next = None# 归并操作return self.merge(self.mergeSort(left_head), self.mergeSort(right_head))        def bucketSort(self, head: ListNode, bucket_size=5):if not head:return head# 找出链表中最大值 list_max 和最小值 list_minlist_min, list_max = float('inf'), float('-inf')cur = headwhile cur:if cur.val < list_min:list_min = cur.valif cur.val > list_max:list_max = cur.valcur = cur.next# 计算桶的个数,并定义桶bucket_count = (list_max - list_min) // bucket_size + 1buckets = [[] for _ in range(bucket_count)]# 将链表节点值依次添加到对应桶中cur = headwhile cur:index = (cur.val - list_min) // bucket_sizeself.insertion(buckets, index, cur.val)cur = cur.nextdummy_head = ListNode(-1)cur = dummy_head# 将元素依次出桶,并拼接成有序链表for bucket_head in buckets:bucket_cur = self.mergeSort(bucket_head)while bucket_cur:cur.next = bucket_curcur = cur.nextbucket_cur = bucket_cur.nextreturn dummy_head.nextdef sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:return self.bucketSort(head)

8.3 链表桶排序算法复杂度分析

  • 时间复杂度 O ( n ) O(n) O(n)
  • 空间复杂度 O ( n + m ) O(n + m) O(n+m) m m m 为桶的个数。

9. 链表基数排序

9.1 链表基数排序算法描述

  1. 使用 cur 指针遍历链表,获取节点值位数最长的位数 size
  2. 从个位到高位遍历位数。因为 0 ~ 9 共有 10 位数字,所以建立 10 个桶。
  3. 以每个节点对应位数上的数字为索引,将节点值放入到对应桶中。
  4. 建立一个哑节点 dummy_head,作为链表的头节点。使用 cur 指针指向 dummy_head
  5. 将桶中元素依次取出,并根据元素值建立链表节点,并插入到新的链表后面。从而生成新的链表。
  6. 之后依次以十位,百位,…,直到最大值元素的最高位处值为索引,放入到对应桶中,并生成新的链表,最终完成排序。
  7. 将哑节点 dummy_dead 的下一个链节点 dummy_head.next 作为新链表的头节点返回。

9.2 链表基数排序代码实现

class Solution:def radixSort(self, head: ListNode):       # 计算位数最长的位数size = 0cur = headwhile cur:val_len = len(str(cur.val))if val_len > size:size = val_lencur = cur.next# 从个位到高位遍历位数for i in range(size):buckets = [[] for _ in range(10)]cur = headwhile cur:# 以每个节点对应位数上的数字为索引,将节点值放入到对应桶中buckets[cur.val // (10 ** i) % 10].append(cur.val)cur = cur.next# 生成新的链表dummy_head = ListNode(-1)cur = dummy_headfor bucket in buckets:for num in bucket:cur.next = ListNode(num)cur = cur.nexthead = dummy_head.nextreturn headdef sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:return self.radixSort(head)

9.3 链表基数排序算法复杂度分析

  • 时间复杂度 O ( n × k ) O(n \times k) O(n×k)。其中 n n n 是待排序元素的个数, k k k 是数字位数。 k k k 的大小取决于数字位的选择(十进制位、二进制位)和待排序元素所属数据类型全集的大小。
  • 空间复杂度 O ( n + k ) O(n + k) O(n+k)

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

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

相关文章

富格林:曝光暗箱细节确保安全

富格林指出&#xff0c;当下在通胀压力被曝光增加的情况下&#xff0c;不少投资者开始有意识地通过黄金投资来抵御风险。但是对于新手投资者来说缺乏相应的交易安全知识&#xff0c;很容易落入交易的暗箱中。但事实上&#xff0c;市面上有很多暗箱已经被曝光&#xff0c;如果投…

Ubuntu Desktop - Desktop

Ubuntu Desktop - Desktop 1. Amazon2. Ubuntu Software3. Desktop4. 系统桌面快捷方式5. 用户桌面快捷方式References 1. Amazon Amazon -> Unlock from Launcher 2. Ubuntu Software Installed -> Games -> Remove 3. Desktop /home/strong/Desktop 4. 系统桌面…

【题目】【网络系统管理】2022年甘肃省职业院校技能大赛-网络构建-试卷

极安云科专注职业教育技能竞赛培训4年&#xff0c;包含信息安全管理与评估、网络系统管理、网络搭建等多个赛项及各大CTF模块培训学习服务。本团队基于赛项知识点&#xff0c;提供完整全面的系统性理论教学与技能培训&#xff0c;成立至今持续优化教学资源与讲师结构&#xff0…

C++ Qt开发:QUdpSocket网络通信组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍如何运用QUdpSocket组件实现基于UDP的网络通信…

离散制造企业MES与流程企业MES的区别

制造行业根据加工过程管控主要分为两大类&#xff1a;离散型与流程型。 离散型主要是通过对原材料的物理形状改进或组合&#xff0c;使其成为产品并增值&#xff0c;如机械加工、家用电器、电子电气行业等。 流程型则主要是采用物料或化学的方法对原材料进行混合、分离、加热…

11|代理(下):结构化工具对话、Self-Ask with Search以及 Plan and execute代理

在上一讲中&#xff0c;我们深入LangChain程序内部机制&#xff0c;探索了AgentExecutor究竟是如何思考&#xff08;Thought&#xff09;、执行&#xff08;Execute/Act&#xff09;和观察&#xff08;Observe&#xff09;的&#xff0c;这些步骤之间的紧密联系就是代理在推理&…

移除元素(leetcode)

给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面…

AI智能客服所需的数据

实现智能客服所需的数据可以分为几个主要类别&#xff0c;这些数据对于训练和优化智能客服系统都是至关重要的。以下是一些通常需要准备的数据&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.对话数…

Android Studio实现内容丰富的安卓民宿酒店预订平台

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.查看民宿 3.民宿预订 4.民宿预订支付&#xff0c; 5.支付订单 6.评论管…

亚马逊认证考试系列 - 知识点 - Beanstalk简介

Beanstalk是一个开源的分布式消息队列系统&#xff0c;它的设计目标是简单、快速和可靠。Beanstalk使用基于TCP的协议进行通信&#xff0c;支持多种客户端和服务器库&#xff0c;同时还提供了一组命令行工具和RESTful API。 Beanstalk的核心概念包括&#xff1a; Job&#xff…

spring suite搭建springboot操作

一、前言 有时候久了没开新项目了&#xff0c;重新开发一个新项目&#xff0c;搭建springboot的过程都有点淡忘了&#xff0c;所有温故知新。 二、搭建步骤 从0开始搭建springboot 1&#xff0e;创建work空间。步骤FileNewJava Working Set。 2.选择Java Working Set。 3.自…

IPD集成产品开发:塑造企业未来竞争力的关键

随着市场竞争的日益激烈&#xff0c;企业对产品开发的要求也越来越高。如何在快速变化的市场环境中&#xff0c;既保证产品的批量生产效率&#xff0c;又满足客户的个性化需求&#xff0c;成为了企业面临的重要挑战。IPD&#xff08;集成产品开发&#xff09;模式&#xff0c;作…

何为布控球?布控球的分类对比

主要的分类有&#xff1a; 根据内部的主控板卡的系统分类&#xff0c;典型的是基于海思芯片的嵌入式LINUX系统的&#xff0c;一般出国标GB28181&#xff0c;另外一种是剑走偏锋的安卓系统的&#xff0c;需要把球机的输出YUV转换为UVC接入安卓主板&#xff0c;作为外接USB摄像头…

source insight中文乱码怎么办?

很多人不知道source insight中文乱码了该怎么办?今日为你们带来的文章是source insight中文乱码的解决方法&#xff0c;还有不清楚小伙伴和小编一起去学习一下吧。 第一步&#xff1a;首先我们打开source insight软件&#xff0c;进入主界面(如图所示)。 第二步&#xff1a;然…

Python深入理解迭代器和生成器

当说起Python里面的高级特性时&#xff0c;就不能不提迭代器&#xff08;Iterators&#xff09;和生成器&#xff08;Generators&#xff09;啦&#xff01;它们就像是处理数据的一把利器&#xff0c;特别是对付大数据的时候&#xff0c;简直就是神器&#xff01;咱们今天就来聊…

bootstrap表格API文档

表格参数&#xff1a; 名称标签类型默认描述-data-toggleString‘table’不用写 JavaScript 直接启用表格。classesdata-classesString‘table table-hover’表格的类名称。默认情况下&#xff0c;表格是有边框的&#xff0c;你可以添加 ‘table-no-bordered’ 来删除表格的边…

Android 12 SystemUI调试

一、调试步骤 在开发过程中&#xff0c;除了可使用AS(Android Studio)开发工具调试源码&#xff0c;还可使用其他开发工具例如VS code&#xff0c;由于篇幅有限&#xff0c;本文只讲如何使用AS调试System UI&#xff0c;如若需要使用Android Studio进行SystemUI的调试工作&…

QCustomPlot-绘制X轴为日期的折线图

主要代码如下&#xff1a; void Widget::InitQLineXDateAddData() {customPlot new QCustomPlot(this);// 创建日期时间类型的刻度生成器QSharedPointer<QCPAxisTickerDateTime> dateTimeTicker(new QCPAxisTickerDateTime);dateTimeTicker->setDateTimeFormat(&quo…

蓝桥杯第642题——跳蚱蜢

题目描述 如下图所示&#xff1a; 有 9 只盘子&#xff0c;排成 1 个圆圈。 其中 8 只盘子内装着 8 只蚱蜢&#xff0c;有一个是空盘。 我们把这些蚱蜢顺时针编号为 1 ~ 8。 每只蚱蜢都可以跳到相邻的空盘中&#xff0c; 也可以再用点力&#xff0c;越过一个相邻的蚱蜢跳到空盘…

数据库学习记录(一)基础语法与单表查询

基础sql语句分类 DDL操作&#xff08;图形化界面&#xff09; 用来定义数据库对象的&#xff0c;例如创建数据库&#xff0c;创建表单 数据库操作 表操作 DML操作&#xff08;掌握&#xff09; 1、insert为添加语句&#xff0c;该语句功能是添加相关数据到表结构中 下面为添…