[算法沉淀记录]排序算法 —— 快速排序

排序算法 —— 快速排序介绍

基本概念

快速排序(Quicksort)是一种排序算法,最早由东尼·霍尔提出。在平均状况下,排序 n 个项目要 Ο(n log n) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上被优化掉。

算法描述

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上做的改进。

快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它是怎么排序的。它的大概思路就是:找到一个基准点(一般是数组中间的数),然后将数组分为两个部分,一部分比这个基准点小,一部分比这个基准点大,然后递归对这两部分排序即可。

算法步骤

  1. 选择一个基准元素,将列表分割成两个子序列。
  2. 对每个子序列重复步骤1,直到列表只有一个元素为止。
  3. 合并排序。
  4. 返回排序后列表。
  5. 结束。

算法伪代码

function quickSort(arr[], low, high)if (low < high){// pi is partitioning index, arr[p] is now at right placepi = partition(arr, low, high)// Separately sort elements before partition and after partitionquickSort(arr, low, pi - 1)quickSort(arr, pi + 1, high)}

优缺点

优点

  1. 通常明显比其他 Ο(n log n) 算法更快。
  2. 内循环较小,快速排序通常内循环较少。
  3. 是一种分治算法。
  4. 是递归的。
  5. 是原地的。
  6. 不需要额外的存储。

缺点

  1. 快速排序的最差时间复杂度是 Ο(n²)。
  2. 快速排序是不稳定的。
  3. 快速排序的空间复杂度是 Ο(log n)。
  4. 快速排序的递归深度是 Ο(log n)。
  5. 快速排序的运行时间取决于分区的方式。

常见应用场景

  • 快速排序被广泛应用于各种应用中,例如对大型数据集进行排序、实现高效的排序算法、优化算法性能等。
  • 它也用于各种数据结构,如数组、链表和集合,以高效地搜索和操作数据。
  • 快速排序也用于各种排序算法中,例如堆排序和归并排序,作为数据分区的子例程。
  • 快速排序也用于图遍历的各种算法中,如深度优先搜索和广度优先搜索,以高效地访问图中的所有节点。

时间复杂度

  • 最好情况 : O(n log n)
  • 平均情况 : O(n log n)
  • 最坏情况 : O(n^2)

为什么时间复杂度是O(n log n)?

快速排序算法的时间复杂度为O(n log n),这是因为它对n个元素排序时具有线性时间复杂度,而将数组划分为更小的子数组时具有对数时间复杂度。

如何避免最坏情况下的时间复杂度?

为了避免最坏情况下的时间复杂度,可以使用随机版本的快速排序,它随机选择基准值元素,而不是使用第一个或最后一个元素。这确保了最坏的情况不会频繁发生。

空间复杂度

  • O(log n)

为什么空间复杂度是O(log n)?

快速排序算法的空间复杂度是O(log n),因为它使用栈来管理递归。在最坏的情况下,递归树的深度可能为O(n),但由于该算法是对输入向量进行原地排序,因此平均空间复杂度为O(log n)。

在每次递归调用中,算法都会将输入向量划分为两个大小大致相等的子向量。然后使用相同的算法对这些子向量进行排序,但输入向量更小。这个过程会一直持续,直到达到基线条件(即输入向量只有一个元素)。

实现

快速排序背后的思想是什么?

快速排序是一种分而治之的排序算法,它的工作原理是从数组中选择一个基准值元素,并根据其他元素是否小于基准值将它们划分为两个子数组。然后对子数组进行递归排序。这可以就地完成,只需要少量的额外内存来执行排序。

快速排序具有良好的平均性能,但当输入数组已经排好序或逆序时,其最差性能为O(n^2)。因此,对于需要考虑最坏情况性能的排序算法,例如针对系统库的排序算法,就不使用这个参数。

非递归版本的代码

template <typename T>
int partition(vector<T> &arr, int low, int high)
{T pivot = arr[high];int i = low - 1;for (int j = low; j <= high - 1; j++){if (arr[j] <= pivot){i++;swap(arr[i], arr[j]);}}swap(arr[i + 1], arr[high]);return i + 1;
}// This is a recursive quicksort code.
template <typename T>
void quickSort(vector<T> &arr, int low, int high)
{if (low < high){int pivotIndex = partition(arr, low, high);quickSort(arr, low, pivotIndex - 1);quickSort(arr, pivotIndex + 1, high);}
}

现在我想解释一下上面的代码:

partition函数用于找到基准元素的正确位置。它接受一个数组、下标和大标作为参数。它返回基准值元素被放置到正确位置后的索引。基准值被选为数组的最后一个元素。然后,该函数遍历数组,将小于或等于基准值的元素替换到数组的左侧。最后,将基准值放在正确的位置,并返回基准值的下标。

No Recursive version of the code

template <typename T>
int partitionNew(vector<T> &arr, int low, int high)
{T pivot = arr[low];int i = low + 1;int j = high;while (i < j){while (i <= j && arr[i] <= pivot){i++;}while (i <= j && arr[j] >= pivot){j--;}if (i < j){swap(arr[i], arr[j]);}}swap(arr[low], arr[j]);return j;
}template <typename T>
void quickSortNew(vector<T> &arr)
{stack<pair<int, int>> stk;stk.push(make_pair(0, arr.size() - 1));while (!stk.empty()){int low = stk.top().first;int high = stk.top().second;stk.pop();if (low >= high){continue;}int pivot = partitionNew(arr, low, high);stk.push(make_pair(pivot + 1, high));stk.push(make_pair(low, pivot - 1));}
}

这段代码使用栈来管理递归,实现了快速排序算法。partitionNew函数是快速排序算法中使用的划分函数的修改版本。它接受一个元素向量和两个下标lowhigh作为输入,并返回对向量进行分区后主元素的下标。

quickSortNew函数是使用快速排序算法对输入向量进行排序的主要函数。它接受一个指向元素向量的引用作为输入,并对向量进行原地排序。该函数使用栈来管理递归,并调用partitionNew函数对向量进行分区并获得基准值索引。然后,它将接下来要排序的子向量的下标压入栈中,直到栈为空。

完整的代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <stack>
#include <cassert>#pragma warning(push)
#pragma warning(disable : 4267)using namespace std;template <typename T>
int partition(vector<T> &arr, int low, int high)
{T pivot = arr[high];int i = low - 1;for (int j = low; j <= high - 1; j++){if (arr[j] <= pivot){i++;swap(arr[i], arr[j]);}}swap(arr[i + 1], arr[high]);return i + 1;
}template <typename T>
int partitionNew(vector<T> &arr, int low, int high)
{T pivot = arr[low];int i = low + 1;int j = high;while (i < j){while (i <= j && arr[i] <= pivot){i++;}while (i <= j && arr[j] >= pivot){j--;}if (i < j){swap(arr[i], arr[j]);}}swap(arr[low], arr[j]);return j;
}// This is a recursive quicksort code.
template <typename T>
void quickSort(vector<T> &arr, int low, int high)
{if (low < high){int pivotIndex = partition(arr, low, high);quickSort(arr, low, pivotIndex - 1);quickSort(arr, pivotIndex + 1, high);}
}template <typename T>
void quickSortNew(vector<T> &arr)
{stack<pair<int, int>> stk;stk.push(make_pair(0, arr.size() - 1));while (!stk.empty()){int low = stk.top().first;int high = stk.top().second;stk.pop();if (low >= high){continue;}int pivot = partitionNew(arr, low, high);stk.push(make_pair(pivot + 1, high));stk.push(make_pair(low, pivot - 1));}
}class Person
{
public:Person(string name, int age, int score){this->name = name;this->age = age;this->socre = score;}// Override the operator> for other function to use.bool operator>(const Person &other) const{// Compare the socre of two Person objects.return this->socre > other.socre;}// Override the operator< for other function to use.bool operator<(const Person &other) const{// Compare the socre of two Person objects.return this->socre < other.socre;}// Override the operator== for other function to use.bool operator==(const Person &other) const{// Compare the socre, age and name of two Person objects.return this->socre == other.socre &&this->age == other.age &&this->name == other.name;}// Override the operator!= for other function to use.bool operator!=(const Person &other) const{// Compare the socre, age and name of two Person objects.return this->socre != other.socre ||this->age != other.age ||this->name != other.name;}// Override the operator<= for other fnction to use.bool operator<=(const Person &other) const{// Compare the socre, age and name of two Person objects.return this->socre <= other.socre &&this->age <= other.age &&this->name <= other.name;}// Override the operator>= for other function to use.bool operator>=(const Person &other) const{// Compare the socre, age and name of two Person objects.return this->socre >= other.socre &&this->age >= other.age &&this->name >= other.name;}// Now there are some get parameters function for this calss:const string &getName() const { return this->name; }int getAge() const { return this->age; }int getScore() const { return this->socre; }private:string name;int age;int socre;
};// This is a unit test function for Person class.
void testPerson()
{Person person1("Alice", 20, 90);Person person2("Bob", 21, 80);Person person3("Charlie", 22, 85);// Test operator>assert(person1 > person2);assert(!(person1 > person3));// Test operator<assert(person2 < person1);assert(!(person3 < person1));// Test operator==assert(person1 == person1);assert(!(person1 == person2));// Test operator!=assert(person1 != person2);assert(!(person1 != person1));
}void basicTypesQuickSortCase()
{// The int type test case:vector<int> intArr = {10, 7, 8, 9, 1, 5};quickSort<int>(intArr, 0, intArr.size() - 1);cout << "Sorted int array: ";for (int i = 0; i < intArr.size(); i++){cout << intArr[i] << " ";}cout << endl;// The float type test case:vector<double> floatArr = {10.5, 7.2, 8.1, 9.6, 1.8, 5.3};quickSort<double>(floatArr, 0, floatArr.size() - 1);cout << "Sorted float array: ";for (int i = 0; i < floatArr.size(); i++){cout << floatArr[i] << " ";}cout << endl;// The string type test case:vector<string> stringArr = {"apple", "banana", "cherry", "orange", "grape", "kiwi"};quickSort<string>(stringArr, 0, stringArr.size() - 1);cout << "Sorted string array: ";for (int i = 0; i < stringArr.size(); i++){cout << stringArr[i] << " ";}cout << endl;
}void basicTypesQuickSortNewCase()
{// The int type test case:vector<int> intArr = {10, 7, 8, 9, 1, 5};quickSortNew<int>(intArr);cout << "Sorted int array: ";for (size_t i = 0; i < intArr.size(); i++){cout << intArr[i] << " ";}cout << endl;// The float type test case:vector<double> floatArr = {10.5, 7.2, 8.1, 9.6, 1.8, 5.3};quickSortNew<double>(floatArr);cout << "Sorted float array: ";for (size_t i = 0; i < floatArr.size(); i++){cout << floatArr[i] << " ";}cout << endl;// The string type test case:vector<string> stringArr = {"apple", "banana", "cherry", "orange", "grape", "kiwi"};quickSortNew<string>(stringArr);cout << "Sorted string array: ";for (size_t i = 0; i < stringArr.size(); i++){cout << stringArr[i] << " ";}cout << endl;
}void personQuickSortCase()
{// Now I want to write some Person class's quick sort examples in here:vector<Person> personArr = {Person("John", 25, 88), Person("Alice", 30, 77), Person("Bob", 20, 66)};quickSortNew<Person>(personArr);cout << "Sorted Person array: ";const auto &personSize = personArr.size();for (size_t i = 0; i < personSize; i++){const auto &person = personArr[i];cout << person.getName() << " " << person.getAge() << " " << person.getScore() << endl;}cout << endl;// Now I want to write some Person class's quick sort examples in here:vector<Person> personArrNew = {Person("Tom", 35, 77), Person("Panda", 22, 88), Person("Alex", 50, 99)};const auto &personSizeNew = personArrNew.size();quickSort<Person>(personArrNew, 0, personSizeNew - 1);cout << "Sorted Person array: " << endl;for (size_t i = 0; i < personSizeNew; i++){const auto &person = personArrNew[i];cout << person.getName() << " " << person.getAge() << " " << person.getScore() << endl;}cout << endl;
}int main()
{// Test Person classtestPerson();// Test basic types quick sortbasicTypesQuickSortCase();basicTypesQuickSortNewCase();personQuickSortCase();return 0;
}#pragma warning(pop)
class Person:def __init__(self, name, age, score):self.name = nameself.age = ageself.score = scoredef __gt__(self, other):return self.score > other.scoredef __lt__(self, other):return self.score < other.scoredef __eq__(self, other):return self.score == other.score and self.age == other.age and self.name == other.namedef __ne__(self, other):return self.score != other.score or self.age != other.age or self.name != other.namedef __le__(self, other):return self.score <= other.score and self.age <= other.age and self.name <= other.namedef __ge__(self, other):return self.score >= other.score and self.age >= other.age and self.name >= other.namedef get_name(self):return self.namedef get_age(self):return self.agedef get_score(self):return self.scoredef partition(arr, low, high):pivot = arr[high]i = low - 1for j in range(low, high):if arr[j] <= pivot:i += 1arr[i], arr[j] = arr[j], arr[i]arr[i + 1], arr[high] = arr[high], arr[i + 1]return i + 1def quick_sort(arr, low, high):if low < high:pivot_index = partition(arr, low, high)quick_sort(arr, low, pivot_index - 1)quick_sort(arr, pivot_index + 1, high)def test_person():person1 = Person("Alice", 20, 90)person2 = Person("Bob", 21, 80)person3 = Person("Charlie", 22, 85)assert person1 > person2assert not (person1 > person3)assert person2 < person1assert not (person3 < person1)assert person1 == person1assert not (person1 == person2)assert person1 != person2assert not (person1 != person1)def basic_types_quick_sort_case():int_arr = [10, 7, 8, 9, 1, 5]quick_sort(int_arr, 0, len(int_arr) - 1)print("Sorted int array:", int_arr)float_arr = [10.5, 7.2, 8.1, 9.6, 1.8, 5.3]quick_sort(float_arr, 0, len(float_arr) - 1)print("Sorted float array:", float_arr)string_arr = ["apple", "banana", "cherry", "orange", "grape", "kiwi"]quick_sort(string_arr, 0, len(string_arr) - 1)print("Sorted string array:", string_arr)def person_quick_sort_case():person_arr = [Person("John", 25, 88), Person("Alice", 30, 77), Person("Bob", 20, 66)]quick_sort(person_arr, 0, len(person_arr) - 1)print("Sorted Person array:")for person in person_arr:print(person.get_name(), person.get_age(), person.get_score())if __name__ == "__main__":# test_person()basic_types_quick_sort_case()person_quick_sort_case()

上面的代码是快速排序算法对基本数据类型和用户定义数据类型的完整实现。它包括针对每种数据类型的测试用例,以及如何在自定义数据类型上使用快速排序算法的演示。

总结

在本文中,我们梳理了快速排序算法,它的时间复杂度,以及如何用c++实现它。我们还学习了如何在基本数据类型和用户定义数据类型上使用快速排序算法。

扩展阅读

随机快速排序算法(Randomized Quick Sort)

随机快速排序是使用随机基准值的快速排序算法的一种变体。其基本思想是随机从数组中选择一个基准值,并根据其他元素是否小于基准值将其划分为两个子数组。然后对子数组进行递归排序。

使用随机基准值的主要好处是避免了对已经排序或倒序的输入数组的最差情况性能。通过随机选择基准值,得到糟糕基准值(将数组划分为两个大小不等的子数组)的机会减少了,从而提高了算法的平均性能。

随机快速排序通常用于未知输入数据是否已排序或逆序的情况,良好的平均性能比最差情况下的性能更重要。它对于大型数据集的排序特别有用,因为即使在最坏的情况下,预期的性能也非常好。

下面是随机快速排序的一个简单实现:

import randomdef randomized_partition(arr, low, high):pivot_index = random.randint(low, high)arr[pivot_index], arr[high] = arr[high], arr[pivot_index]return partition(arr, low, high)def randomized_quick_sort(arr, low, high):if low < high:pivot_index = randomized_partition(arr, low, high)randomized_quick_sort(arr, low, pivot_index - 1)randomized_quick_sort(arr, pivot_index + 1, high)

下面是随机快速排序算法的c++代码:

#include <iostream>
#include <vector>
#include <random>std::random_device rd;
std::mt19937 gen(rd());int randomized_partition(std::vector<int>& arr, int low, int high) {int pivot_index = std::uniform_int_distribution<>(low, high)(gen);std::swap(arr[pivot_index], arr[high]);return partition(arr, low, high);
}void randomized_quick_sort(std::vector<int>& arr, int low, int high) {if (low < high) {int pivot_index = randomized_partition(arr, low, high);randomized_quick_sort(arr, low, pivot_index - 1);randomized_quick_sort(arr, pivot_index + 1, high);}
}int main() {std::vector<int> arr = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};randomized_quick_sort(arr, 0, arr.size() - 1);for (int num : arr) {std::cout << num << " ";}return 0;
}

这段代码使用了c++ 11的随机数生成功能来随机选择一个主元素。randomized_partition函数是快速排序算法中使用的分区函数的修改版本。它接受一个元素向量的引用和两个索引,lowhigh,作为输入,并返回对向量进行分区后主元素的索引。

randomized_quick_sort函数是使用随机快速排序算法对输入向量进行排序的主要函数。它接受一个元素向量的引用和两个索引lowhigh作为输入,并对向量进行原地排序。该函数使用randomized_partition函数对向量进行分区并获得基准值索引。然后递归调用自己对子向量进行排序,直到栈为空。

三中位数快排(Median of Three Quick Sort)

三中位数快排算法(Median of Three fast Sort algorithm)是快速排序算法的一种变体,它随机选择三个元素中的中间元素作为基准值。这种方法旨在提高快速排序算法在处理有很多重复元素的数组或已经排序过的数组时的性能。

三中位数快排算法的中位数工作原理如下:

  1. 从数组中随机选择三个元素。
  2. 对这三个元素进行排序,找到中位数。
  3. 在快速排序算法中,使用中位数元素作为基准值。

这种方法背后的主要思想是,使用中位数元素作为基准值,可以减少遇到最坏情况的可能性,即分区过程导致子数组不平衡。这反过来又提高了快速排序算法的整体性能。

下面是三次快速排序中位数算法的简单Python实现:

import randomdef median_of_three_quick_sort(arr):if len(arr) <= 1:return arr# Choose three random elementsidx1, idx2, idx3 = random.sample(range(len(arr)), 3)elem1, elem2, elem3 = arr[idx1], arr[idx2], arr[idx3]# Sort the three elementsif elem1 > elem2:elem1, elem2 = elem2, elem1if elem2 > elem3:elem2, elem3 = elem3, elem2if elem1 > elem2:elem1, elem2 = elem2, elem1# Use the median element as the pivotpivot = elem2less = [x for x in arr if x <= pivot]greater = [x for x in arr if x > pivot]# Recursively sort the less and greater arraysreturn median_of_three_quick_sort(less) + [pivot] + median_of_three_quick_sort(greater)

请注意,三中位数快排算法的中位数比标准快速排序算法的性能提升取决于特定的用例和输入数据的性质。在某些情况下,标准的快速排序算法仍然可能优于三种快速排序算法中的中位数。

下面是快速排序算法的中位数的c++实现:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>using namespace std;// Swap two elements in the vector
void swap(vector<int> &arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}// Median of Three function to find the median of three elements
int median_of_three(vector<int> &arr, int low, int high) {int mid = low + (high - low) / 2;if (arr[mid] < arr[low]) {swap(arr, low, mid);}if (arr[high] < arr[low]) {swap(arr, low, high);}if (arr[high] < arr[mid]) {swap(arr, mid, high);}swap(arr, mid, high - 1);return arr[high - 1];
}// Quick Sort function
void quick_sort(vector<int> &arr, int low, int high) {if (low >= high) {return;}int pivot = median_of_three(arr, low, high);int i = low;int j = high - 1;while (i <= j) {while (arr[i] < pivot) {i++;}while (arr[j] > pivot) {j--;}if (i <= j) {swap(arr, i, j);i++;j--;}}quick_sort(arr, low, i - 1);quick_sort(arr, j + 1, high);
}int main() {vector<int> arr = {3, 6, 8, 10, 1, 2, 1};quick_sort(arr, 0, arr.size() - 1);for (int i = 0; i < arr.size(); i++) {cout << arr[i] << " ";}return 0;
}

这段代码定义了一个median_of_three函数,用于查找数组中三个元素的中位数,并将其用作基准值。然后,quick_sort函数被修改为使用这种三选中值基准值选择。main函数演示了一个示例数组的排序。

个人格言
追寻与内心共鸣的生活,未来会逐渐揭晓答案。

Pursue the life that resonates with your heart, and the future will gradually reveal the answer.

在这里插入图片描述

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

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

相关文章

linux centos7.9改dns和ip

vi /etc/sysconfig/network-scripts/ifcfg-ens32 &#xff1a;wq后 重启网络服务 systemctl restart network —————————————————————————— 篇外话题 软件下载 xshell可以从腾讯软件中心下载

Open CASCADE学习|GC_MakeArcOfCircle构造圆弧

目录 1、通过圆及圆的两个参数创建圆弧&#xff0c;参数为弧度角 2、通过圆及圆上的一点、圆的1个参数创建圆弧&#xff0c;参数为弧度角&#xff0c;Sense决定方向 3、通过圆及圆上的两个点创建圆弧&#xff0c;Sense决定方向 4、通过三点创建圆弧&#xff0c;最后一点应安…

react useRef用法

1&#xff0c;保存变量永远不丢失 import React, { useState,useRef } from react export default function App() { const [count,setcount] useState(0) var mycount useRef(0)//保存变量永远不丢失--useRef用的是闭包原理 return( <div> <button onClick{()>…

SpringBoot使用classfinal-maven-plugin插件加密Jar包

jar包加密 1、在启动类的pom.xml中加入classfinal-maven-plugin插件 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><…

Qt QWidget 简约美观的加载动画 第五季 - 小方块风格

给大家分享两个小方块风格的加载动画 &#x1f60a; 第五季来啦 &#x1f60a; 效果如下: 一个三个文件,可以直接编译运行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <QGridLayout> int main(int argc, char *arg…

Python之词频统计(自然语言处理)

背景 词频统计是指对一段文本中每个单词出现的次数进行计数分析。这种分析有助于了解文本的重点词汇、主题或作者的写作风格。如果你有一个特定的文本或想要分析某些内容的词频&#xff0c;你可以提供文本&#xff0c;我可以为你进行简单的词频统计。 例如&#xff0c;如果你…

jeesite用字典项配置二级下拉选

1、配置字典项 2、html代码&#xff1a;修改下拉选项框 <div class"col-xs-6"><div class"form-group"><label class"control-label col-sm-4" title""><span class"required">*</span> ${…

备考北京高考数学:历年选择题真题练一练和解析(2014-2023)

还有三个多月的时间就要高考了&#xff0c;我们今天继续看北京市高考数学真题和解析。今天看5道选择题。独家制作的在线练习集&#xff0c;可以便捷地反复刷这些真题&#xff0c;吃透真题&#xff08;背后的知识点和解题技巧&#xff09;&#xff0c;让高考数学再上一个台阶。 …

OpenAI Sora 关键技术详解:揭秘时空碎片 (Spacetime Patches) 技术

编者按&#xff1a;近日&#xff0c;OpenAI发布其首个视频生成模型“Sora”&#xff0c;该模型生成的视频内容可以呈现出多个角色、特定动作以及复杂场景&#xff0c;为构建能够理解和模拟现实世界的人工智能模型奠定了基础。 本文解析的重点即是 Sora 背后的核心技术 Spacetim…

单片机51 定时器

一、基本概念 1.1简介 单片机的定时器是一种内部功能模块&#xff0c;用于产生计时、计数、延时等功能。定时器通常由一个或多个计数器和相关的控制逻辑组成。单片机的定时器可以运行在不同的工作模式下&#xff0c;以适应不同的计时和计数需求。 C51中的定时器和计数器是同…

Tomcat 下部署若依单体应用可观测最佳实践

实现目标 采集指标信息采集链路信息采集日志信息采集 RUM 信息会话重放 即用户访问前端的一系列过程的会话录制信息&#xff0c;包括点击某个按钮、操作界面、停留时间等&#xff0c;有助于客户真是意图、操作复现 版本信息 Tomcat (9.0.81)Springboot(2.6.2)JDK (>8)DDT…

请求包的大小会影响Redis每秒处理请求数量

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容压测规划客户端长连接数量对性能的影响请求包大小的影响Pipleline模式对Redis的影响 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领…

第二章 Xshell5连接VM中虚拟系统Ubuntu1704

第二章 Xshell5连接VM中虚拟系统Ubuntu1704 第一章 Win10系统VM安装Ubuntu1704虚拟机 第三章 VMware虚拟机ubuntu显示屏幕太小&#xff0c;无法自适应解决办法 一、设置全新安装的Ubuntu的root密码 1.1、启动Ubuntu系统&#xff0c;在桌面右键打开终端 1.2、尝试登陆root用户…

【postgresql】数据表id自增与python sqlachemy结合实例

需求&#xff1a; postgresql实现一个建表语句&#xff0c;表名&#xff1a;student,字段id,name,age&#xff0c; 要求&#xff1a;每次添加一个数据id会自动增加1 在PostgreSQL中&#xff0c;您可以使用SERIAL或BIGSERIAL数据类型来自动生成主键ID。以下是一个创建名为stude…

TiDB之分布式数据库TiDB 操作管理规范【附可下载文档】

一、 目的 为了在软件生命周期内规范数据库相关的设计、开发、运维工作,便于不同团队之间的沟通及协调,制定此文档,以期在相关规范上达成共识和默契,提升相关环节的工作效率及系统的可维护性。同时好的规范,在执行的时候可以培养出好的习惯,好的习惯是软件质量的很好保证…

EMQX Enterprise 5.5 发布:新增 Elasticsearch 数据集成

EMQX Enterprise 5.5.0 版本已正式发布&#xff01; 在这个版本中&#xff0c;我们引入了一系列新的功能和改进&#xff0c;包括对 Elasticsearch 的集成、Apache IoTDB 和 OpenTSDB 数据集成优化、授权缓存支持排除主题等功能。此外&#xff0c;新版本还进行了多项改进以及 B…

Qt项目:网络1

文章目录 项目&#xff1a;网路项目1&#xff1a;主机信息查询1.1 QHostInfo类和QNetworkInterface类1.2 主机信息查询项目实现 项目2&#xff1a;基于HTTP的网络应用程序2.1 项目中用到的函数详解2.2 主要源码 项目&#xff1a;网路 项目1&#xff1a;主机信息查询 使用QHostI…

【练习——打印每一位数】

打印一个数的每一位 举个例子&#xff1a;我们现在要求打印出123的每一位数字。我们需要去想123%10等于3&#xff0c;就可以把3单独打印出来了&#xff0c;然后再将123/10可以得到12&#xff0c;将12%10就可以打印出2&#xff0c;而我们最后想打印出1&#xff0c;只需要1%10就…

前端路由与后端路由的区别

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

MySQL之Pt-kill工具

工具下载 [rootlocalhost1 bin]# wget percona.com/get/percona-toolkit.tar.gz [rootlocalhost1 bin]# yum install perl-DBI [rootlocalhost1 bin]# yum install perl-DBD-MySQL [rootlocalhost1 bin]# ./pt-kill --help1、每10秒检查一次&#xff0c;发现有 Query 的进程就…