3、排序算法1---按考研大纲做的

news2025/5/10 8:28:18

一、插入排序

1、直接插入排序

推荐先看这个视频

1.1、原理

  • 第一步,索引0的位置是有序区(有序区就是有序的部分,刚开始只有第一个数据是有序的)。
  • 第二步,将第2个位置到最后一个位置的元素,依次进行排序,而这个排序的过程,类似于扑克牌。(我们将后面的2~n个元素一个一个的与有序区对比,将它插入到有序区里面的适当位置)。

我们采用顺序查找的方式,来找到要插入位置,进行插入------>这就是直接插入排序。

在这里插入图片描述

1.2、代码实现(C语言)

  • while和for来实现
#include <stdio.h>
void insertionSort1(int arr[], int n) {
    for (int i = 1; i < n; i++) {
        int temp = arr[i];
        int j = i - 1;
        
        // 从后向前扫描,移动大于key的元素
        while (j >= 0 && arr[j] > temp) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = temp;
    }
}
  • 2个for实现
#include <stdio.h>
void insertSort2(int arr[],int n){
    for(int i =1;i<n;i++){
        int temp = arr[i];
        int j;
        for(j = i;j>0&&temp<arr[j-1];--j){
                arr[j]=arr[j-1];
        }
        arr[j]=temp;
    }
}

2、折半插入排序

折半插入排序视频。

2.1、原理

  • 在直接插入排序基础上,使用二分查找确定插入位置,减少比较次数
  • 算法步骤
    • 第一个元素开始,该元素可认为已排序
    • 取出下一个元素,在已排序序列中使用二分查找找到插入位置
    • 插入位置后的所有元素后移一位
    • 将新元素插入到找到的位置
    • 重复步骤2~4

2.2、代码实现(C语言)

#include <stdio.h>
void insert(int arr[],int n){
    for(int i =1;i<n;i++){
        int temp = arr[i];
        int j = i-1;
        while(j>-1&&temp<arr[j]){
            arr[j+1]=arr[j];
            --j;
        }
        arr[j+1]=temp;
    }
}
void binaryInsert(int arr[],int n){
    for(int i = 1;i<n;i++){
        int left=0;
        int right=i-1;
        int temp = arr[i];
        //二分查找待插入位置
        while(left<=right){
            int mid = (left+right)/2;
            if(arr[mid]>temp){
                right = mid-1;
            }else{
                left = mid+1;
            }
        }
        for(int j = i;j>left;j--){
            arr[j]=arr[j-1];
        }
        //插入元素
        arr[left]=temp;
    }
}
int main(int argc, char const *argv[])
{
    int arr[]={36,27,20,60,55,7,28,36,67,44,16};
    int n = sizeof(arr)/sizeof(arr[0]);
    binaryInsert(arr,n);
    for(int i =0;i<n;++i){
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}

二、希尔排序

1、原理

  • 希尔排序也是插入排序的升级版。
  • 希尔排序的第一步是设计增量(一般默认为序列长度的一半)。

在这里插入图片描述

  • 开始分组,第一组从0 开始,以增量5为例,我们需要 0 ,5,10位置的数据进行交换(这里是用直接插入排序来进行的交换)。
    在这里插入图片描述
  • 那么第2组就是从1开始,以增量5为例,我们需要1,6位置的数据进行交换。依次下去,直到最后一个元素。
  • 增量就需要进行再次改变,设置为之前的一半,向下取整。例如 5/2=2 。
  • 继续分组交换数据(这里是用直接插入排序来进行的交换)。

增量会不断减小的,为了得到最终结果,我们的最后一个增量是1的大小,只有这样才能得到最终结果

2、代码实现(C语言)

void shellSort(int arr[],int n){
    int gap;
    for(gap=n/2;gap>0;gap/=2){//确定增量
        for(int i = 0;i<gap;++i){//每一个增量的分组个数
            for(int j = i+gap;j<n;j+=gap){//直接插入排序
                int temp = arr[j];
                int k = j-gap;
                while(k>-1&&temp<arr[k]){
                    arr[k+gap]=arr[k];
                    k-=gap;
                }
                arr[k+gap]=temp;
            }
        }
    }
}
int main(int argc, char const *argv[])
{
    int arr[]={36,27,20,60,55,7,28,36,67,44,16};
    shellSort(arr,11);
    for(int i =0;i<11;++i){
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}

三、冒泡排序

冒泡排序视频。

1、原理

  • 每一轮的相邻元素进行比较,这2个元素,如果逆序,就交换数据
  • 每轮可以排好1个元素,总共n-1轮每轮都会少比较一对数据

由此我们可知:
n是元素个数。
轮数是n-1次。
比较是n-i-1次。i 是第几轮。

2、代码实现(C语言)

  • 第1种方法----经典写法
void bubbleSort(int arr[],int n){
    for(int i =0;i<n-1;i++){//要进行的轮数,写成n也可以
        for(int j =0;j<n-i-1;j++){//比较的次数
            if(arr[j+1]<arr[j]){
                int temp = arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
    }
}
int main(int argc, char const *argv[])
{
    int arr[]={36,27,20,60,55,7,28,36,67,44,16};
    bubbleSort(arr,11);
    for(int i =0;i<11;++i){
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}
  • 第2种方法-----标记交换
    • 有的时候,并不是每一轮都需要交换,flag标记上一轮是否交换了,就可以减少比较次数。
void bubbleSort(int arr[],int n){
    for(int i =0;i<n-1;i++){//要进行的轮数,写成n也可以
        int flag = 1;
        for(int j =0;j<n-i-1;j++){//比较的次数
            if(arr[j+1]<arr[j]){
                int temp = arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
                flag = 0;//交换了,flag改为0
            }
        }
        if(flag==1){
            break;
        }
    }
}
int main(int argc, char const *argv[])
{
    int arr[]={36,27,20,60,55,7,28,36,67,44,16};
    bubbleSort(arr,11);
    for(int i =0;i<11;++i){
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}
  • 第3种方法----do while优化(推荐这种写法
    • 先把newIndex设置为0,只要交换数据了,newIndex就改变。
      • newIndex来保存交换的元素位置
    • 下一次就只需要进行0到newIndex之间的比较,后面的元素不用比较了,因为它们是有序的。
    • 如果newIndex 没有变化,还是0,就说明不需要排序了。直接结束排序了。
void bubbleSort(int arr[],int n){
    int newIndex;
    int temp_length=n;
    do{
        newIndex = 0;
        for(int i =0;i<n-1;i++){
            if(arr[i]>arr[i+1]){
                int temp = arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=temp;
                newIndex = i+1;
            }
        }
        n=newIndex;
    }while(newIndex>0);
}

四、简单选择排序

简单选择排序

1、原理

  • 每次从待排序序列中选择最小(或最大)的元素放到已排序序列的末尾(或前面),直到全部元素有序。

2、代码实现(Cpp语言和c语言)

  • cpp版本
void selectionSort(vector<int>& arr) {
    int n = arr.size();
    for (int i = 0; i < n - 1; i++) {
        int minIndex = i;  // 记录最小元素的索引
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }
        swap(arr[i], arr[minIndex]);  // 将最小值放到已排序区间末尾
    }
}
  • c语言版本
void selectSort(int arr[],int n){
    for(int i =0;i<n;i++){
        int minIndex = i;
        for(int j =i+1;j<n;j++){
            if(arr[j]<arr[minIndex]){
                minIndex=j;
            }
        }
        swap(arr[minIndex],arr[i]);
    }
}

五、快速排序

1、原理

  • 第一步:确定枢轴pivot),枢轴可以是任意位置。
  • 第二步:设置left、right指针来寻找第一个比pivot大的元素和第一个比pivot小的元素,然后交换这2个元素。【注意:先移动right,避免left越界,超过right
  • 递归处理,直到空或只剩下一个为止。

2、代码实现(C语言)

  • 第1种:双边循环
#include <stdio.h>
#include <vector>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <ctime>
using namespace std;

int quickDoubleSort(int arr[], int startIndex, int endIndex) {
    srand(time(NULL));
    int randomIndex = rand() % (endIndex - startIndex + 1) + startIndex;
    swap(arr[startIndex], arr[randomIndex]);  // 随机选择基准并交换到开头
    int pivot = arr[startIndex];  // 现在再取基准值
    int left = startIndex;
    int right = endIndex;

    while (left < right) {
        while (left < right && arr[right] > pivot) {  // 先移动 right,避免 left 越界
            right--;
        }
        while (left < right && arr[left] <= pivot) {  // 再移动 left
            left++;
        }
        if (left < right) {
            swap(arr[left], arr[right]);
        }
    }
    swap(arr[left], arr[startIndex]);  // 把基准值放到正确位置
    return left;
}

void quickSort(int arr[], int startIndex, int endIndex) {
    if (startIndex >= endIndex) return;
    int pivot = quickDoubleSort(arr, startIndex, endIndex);
    quickSort(arr, startIndex, pivot - 1);
    quickSort(arr, pivot + 1, endIndex);
}

int main() {
    int arr[] = {36, 27, 20, 60, 55, 7, 28, 36, 67, 44, 16};
    int n = sizeof(arr) / sizeof(arr[0]);
    quickSort(arr, 0, n - 1);
    for (int i = 0; i < n; ++i) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

  • 第2种:单边循环

int singleQuickSort(int arr[],int startIndex,int endIndex){
    int tmp = arr[startIndex];
    int mark = startIndex;
    for(int i = startIndex+1;i<=endIndex;++i){
        if(arr[i]<tmp){
            mark++;
            swap(arr[mark],arr[i]);
        }
    }
    swap(arr[mark],arr[startIndex]);
    return mark;
}
void singleQuick(int arr[],int startIndex,int endIndex){
    if(startIndex>=endIndex)return;
    int pivot= singleQuickSort(arr,startIndex,endIndex);
    singleQuick(arr,startIndex,pivot-1);
    singleQuick(arr,pivot+1,endIndex);
}
int main(int argc,char*const argv[]){
    int arr[]={36,27,20,60,55,7,28,36,67,44,16};
    int n = sizeof(arr) / sizeof(arr[0]);
    singleQuick(arr,0,n-1);
    for(int i =0;i<n;i++){
        printf("%d ",arr[i]);
    }
    printf("\n");
}                         
  • 第3种:算法常用的写法—ACWing里面的写法。(c++)
  • 可以发现到,它没有swap( arr [ mark ] , q[ i ] )这一步,所以它是把这一步放入到了quick_sort( q , l , j ) 。
#include <algorithm>
#include <vector>
#include<iostream>
using namespace std;
const int N = 1e5+10;
int q[N];
int n;
void quick_sort(int q[],int l,int r){
    if(l>=r)return;
    int x = q[l];
    int i = l-1;
    int j = r+1;
    while(i<j){
        do i++;while(q[i]<x);
        do j--;while(q[j]>x);
        if(i<j)swap(q[i],q[j]);
    }
    quick_sort(q,l,j);
    quick_sort(q,j+1,r);
}
int main(int argc,char*const argv[]){
    cin>>n;
    for(int i =0;i<n;i++){
        cin>>q[i];
    }
    quick_sort(q,0,n-1);
    for(int i=0;i<n;i++){
        cout<<q[i]<<" ";
    }
    cout<<endl;
}

六、堆排序

堆排序视频

1、原理可以看这篇文章了解堆。

1.1、大根堆
  • 根堆(完全二叉树
    • 任一节点大于等于左右孩子
    • i节点的左孩子是2i,右孩子是2i+1,而它的父亲是i/2的绝对值。【下标1开始存储的规律】
    • 虽然是完全二叉树的理想结构,实际上是用数组来存储数据,进行操作。

步骤

  • 1、插入节点
    • 是插入到完全二叉树的最后一个位置。然后开始上移操作。
  • 2、获取/移除最小元素
    • 获取和删除的是堆顶节点。
    • 删除后,就需要把最后一个节点临时补充到原本堆顶的位置。再判断堆顶的顺序进行交换。
1.2、小根堆
  • 根堆(完全二叉树
    • 任一节点小于等于左右孩子
    • i节点的左孩子是2i,右孩子是2i+1,而它的父亲是i/2的绝对值。【下标1开始存储的规律
    • 虽然是完全二叉树的理想结构,实际上是用数组来存储数据,进行操作。

步骤

  • 1、插入节点
    • 是插入到完全二叉树的最后一个位置。然后开始上移操作。
  • 2、获取/移除最小元素
    • 获取和删除的是堆顶节点。
    • 删除后,就需要把最后一个节点临时补充到原本堆顶的位置。再判断堆顶的顺序进行交换。

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

  • 时间复杂度
    • 插入 (push):O(log n)
    • 删除 (pop):O(log n)
    • 获取堆顶 (top):O(1)

2、代码实现(Cpp语言)

  • 大根堆
#include <algorithm>
#include <vector>
#include<iostream>
using namespace std;
class MaxHeap{
private:
    vector<int> heap;
    //  i/2              (j-1)/4
    //   i        =>     (j-1)/2
    //2i    2i+1     j-1           j

    //上浮调整(插入时,使用)
    void shiftUp(int index){//index是插入的位置
        while(index>0){
            int parent = (index-1)/2;
            if(heap[parent]>=heap[index]){
                break;
            }
            swap(heap[parent],heap[index]);
            index = parent;
        }
    }
    //下浮调整(删除时,使用)
    void shiftDown(int index){
        int size = heap.size();
        int leftChild = 2*index+1;
        while(leftChild<size){
            int rightChild = leftChild+1;
            int maxChild = leftChild;//假设左节点是最大值
            if(rightChild<size&&heap[rightChild]>heap[leftChild]){
                maxChild = rightChild;
            }
            if(heap[index]>=heap[maxChild]){
                break;//当前节点是最大
            }
            swap(heap[index],heap[maxChild]);
            index = maxChild;
            leftChild=2*index +1;
        }
    }
public:
    void push(int val){
        heap.push_back(val);
        shiftUp(heap.size()-1);
    }
    void pop(){
        if(heap.empty())return;//为空就不进行了
        swap(heap[0],heap.back());
        heap.pop_back();
        shiftDown(0);
    }
    int top()const{
        if(!heap.empty())return heap[0];
        throw runtime_error("Heap is empty");
    }
    bool empty()const{
        return heap.empty();
    }
};
int main(int argc,char*const argv[]){
    // 大根堆测试
    MaxHeap maxHeap;
    maxHeap.push(3);
    maxHeap.push(1);
    maxHeap.push(4);
    std::cout << "MaxHeap Top: " << maxHeap.top() << std::endl; // 4
    maxHeap.pop();
    std::cout << "After pop, MaxHeap Top: " << maxHeap.top() << std::endl; // 3
    cout<<endl;
}
  • 小根堆
class MinHeap {
private:
    std::vector<int> heap;

    void siftUp(int idx) {
        while (idx > 0) {
            int parent = (idx - 1) / 2;
            if (heap[parent] <= heap[idx]) 
                break;  // 父节点更小,无需调整
            std::swap(heap[parent], heap[idx]);
            idx = parent;
        }
    }

    void siftDown(int idx) {
        int size = heap.size();
        int leftChild = 2 * idx + 1;
        while (leftChild < size) {
            int rightChild = leftChild + 1;
            int minChild = leftChild; // 假设左子节点是最小值
            if (rightChild < size && heap[rightChild] < heap[leftChild]) {
                minChild = rightChild; // 右子节点更小
            }
            if (heap[idx] <= heap[minChild]) 
                break;  // 当前节点已满足小根堆性质
            std::swap(heap[idx], heap[minChild]);
            idx = minChild;
            leftChild = 2 * idx + 1;
        }
    }

public:
    void push(int val) {
        heap.push_back(val);
        siftUp(heap.size() - 1);
    }

    void pop() {
        if (heap.empty()) return;
        std::swap(heap[0], heap.back());
        heap.pop_back();
        siftDown(0);
    }

    int top() const {
        if (!heap.empty()) return heap[0];
        throw std::runtime_error("Heap is empty");
    }

    bool empty() const {
        return heap.empty();
    }
};
#include <iostream>
#include <vector>
int main() {
    
    // 小根堆测试
    MinHeap minHeap;
    minHeap.push(3);
    minHeap.push(1);
    minHeap.push(4);
    std::cout << "MinHeap Top: " << minHeap.top() << std::endl; // 1
    minHeap.pop();
    std::cout << "After pop, MinHeap Top: " << minHeap.top() << std::endl; // 3
    return 0;
}

七、归并排序

归并排序视频

1、原理

  • 分治思想
    • 将数组递归地二分,直到子数组长度为1(天然有序)
    • 合并两个已排序的子数组
  • 合并操作
    • 用双指针比较两个子数组的元素
    • 每次选择较小者放入新数组
    • 剩余元素直接追加

2、代码实现(C语言)

static void merge(int arr[],int left,int right,int mid){
    const int n1 = mid - left+1;//左边空间的个数
    const int n2 = right - mid;//右边空间的个数
    int arr1[n1];//暂时存储左边的值
    int arr2[n2];//暂时存储右边的值
    for(int i =0;i<n1;++i){
        arr1[i]=arr[left+i];
    }
    for(int i =0;i<n2;++i){
        arr2[i]=arr[mid+1+i];
    }
    int i =0;
    int j =0;
    int k =left;
    while(i<n1&&j<n2){
        if(arr1[i]<=arr2[j]){
            arr[k]=arr1[i++];
        }else if(arr1[i]>arr2[j]){
            arr[k]=arr2[j++];
        }
        ++k;
    }
    //不一定全部arr数据都重新传入了,可能还剩一些
    while(i<n1){
        arr[k++]=arr1[i++];
    }
    while(j<n2){
        arr[k++]=arr2[j++];
    }
}
void mergeLoop(int arr[],int left,int right){
    if(left==right){
        return;
    }
    int mid = (left+right)/2;
    mergeLoop(arr,left,mid);
    mergeLoop(arr,mid+1,right);
    //拆分完后进行归并
    merge(arr,left,right,mid);
}
int main(int argc,char*const argv[]){
    int arr[] = {36 ,27 ,20 ,60 ,55 ,7 ,28 ,36, 67 ,44 ,16};
    int n =sizeof(arr)/sizeof(arr[0]);
    mergeLoop(arr,0,n-1);
    for(int i =0;i<n;++i){
        printf("%d ",arr[i]);
    }
}

八、基数排序

基数排序视频。

1、原理

  • 基数排序的核心:
    • 将整数按每一位(从低位到高位,或高位到低位)依次排序。由于每个位的排序必须稳定(相同值的元素顺序不变),多次排序后整体数组有序。
  • 具体步骤(以 LSD 为例):
    • 确定最大数的位数(决定排序轮次)。
    • 从最低位开始(个位 → 十位 → 百位…):
    • 将数字按当前位的数值分到 10 个桶(0~9)。
    • 按桶顺序(0→9)合并所有元素,形成新数组。
    • 重复步骤 2 直到所有位处理完毕。
      在这里插入图片描述

2、代码实现(Cpp语言)(支持非负整数)

#include <vector>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
void radixSort(vector<int>&arr){
    if(arr.empty())return ;
    //找到最大数的位数

    int maxVal = *max_element(arr.begin(),arr.end());//获取最大数
    int maxDigit = 0;//记录位数
    while(maxVal>0){
        maxVal/=10;
        maxDigit++;
    }
    //从低到高位排序
    vector<vector<int>>buckets(10);//设置10个桶
    for(int i =0;i<maxDigit;i++){
        //将元素按当前位分到桶中
        for(int num:arr){
            int digit = (num/static_cast<int>(pow(10,i)))%10;
            //digit的作用是 从整数 num 中提取第 i 位的数字(从右往左数,最低位为第0位)
            //pow计算 10 的 i 次方
            //static_cast<int>强制转换,避免浮点数影响
            //num/pow(10,i)将num右移i位,例如num=1234->1234/100 = 12
            //%10:得到最右边的数字 12%10=2
            buckets[digit].push_back(num);
        }
        //合并桶,形成新的数组
        int index =0;
        for(auto & bucket:buckets){
            for(int num:bucket){
                arr[index++]=num;
            }
            bucket.clear();
        }
    }
}


int main() {
    std::vector<int> arr = {170, 45, 75, 90, 802, 24, 2, 66};
    radixSort(arr);
    std::cout << "Sorted Array: ";
    for (int num : arr) {
        std::cout << num << " ";
    }
    // 输出:2 24 45 66 75 90 170 802
    return 0;
}

  • 例子
原数组:[170, 45, 75, 90, 802, 24, 2, 66]
最大数 8023 位

第一轮(个位)分桶:
0: 170, 90 
2: 802, 2
4: 24
5: 45, 75
6: 66
合并后:[170, 90, 802, 2, 24, 45, 75, 66]

第二轮(十位)分桶:
0: 802, 2
2: 24
6: 66 
7: 170, 75 
9: 90 
5: 45 
合并后:[802, 2, 24, 45, 66, 170, 75, 90]

第三轮(百位)分桶:
0: 2, 24, 45, 66, 75, 90 
8: 802 
合并后:[2, 24, 45, 66, 75, 90, 802]

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

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

相关文章

llama-webui docker实现界面部署

1. 启动ollama服务 [nlp server]$ ollama serve 2025/04/21 14:18:23 routes.go:1007: INFO server config env"map[OLLAMA_DEBUG:false OLLAMA_FLASH_ATTENTION:false OLLAMA_HOST: OLLAMA_KEEP_ALIVE:24h OLLAMA_LLM_LIBRARY: OLLAMA_MAX_LOADED_MODELS:4 OLLAMA_MAX_…

Linux的Socket开发补充

是listen函数阻塞等待连接&#xff0c;还是accept函数阻塞等待连接&#xff1f; 这两个函数的名字&#xff0c;听起来像listen一直在阻塞监听&#xff0c;有连接了就accept&#xff0c;但其实不是的。 调用listen()后&#xff0c;程序会立即返回&#xff0c;继续执行后续代码&a…

Spring-AOP分析

Spring分析-AOP 1.案例引入 在上一篇文章中&#xff0c;【Spring–IOC】【https://www.cnblogs.com/jackjavacpp/p/18829545】&#xff0c;我们了解到了IOC容器的创建过程&#xff0c;在文末也提到了AOP相关&#xff0c;但是没有作细致分析&#xff0c;这篇文章就结合示例&am…

【专业解读:Semantic Kernel(SK)】大语言模型与传统编程的桥梁

目录 Start:什么是Semantic Kernel&#xff1f; 一、Semantic Kernel的本质&#xff1a;AI时代的操作系统内核 1.1 重新定义LLM的应用边界 1.2 技术定位对比 二、SK框架的六大核心组件与技术实现 2.1 内核&#xff08;Kernel&#xff09;&#xff1a;智能任务调度中心 2…

你学会了些什么211201?--http基础知识

概念 HTTP–Hyper Text Transfer Protocol&#xff0c;超文本传输协议&#xff1b;是一种建立在TCP上的无状态连接&#xff08;短连接&#xff09;。 整个基本的工作流程是&#xff1a;客户端发送一个HTTP请求&#xff08;Request &#xff09;&#xff0c;这个请求说明了客户端…

每天学一个 Linux 命令(29):tail

​​可访问网站查看,视觉品味拉满: http://www.616vip.cn/29/index.html tail 命令用于显示文件的末尾内容,默认显示最后 10 行。它常用于实时监控日志文件或查看文件的尾部数据。以下是详细说明和示例: 命令格式 tail [选项] [文件...]常用选项 选项描述-n <NUM> …

【形式化验证基础】活跃属性Liveness Property和安全性质(Safety Property)介绍

文章目录 一、Liveness Property1、概念介绍2、形式化定义二、Safety Property1. 定义回顾2. 核心概念解析3. 为什么强调“有限前缀”4. 示例说明4.1 示例1:交通信号灯系统4.2 示例2:银行账户管理系统5. 实际应用的意义三. 总结一、Liveness Property 1、概念介绍 在系统的…

PI0 Openpi 部署(仅测试虚拟环境)

https://github.com/Physical-Intelligence/openpi/tree/main 我使用4070tisuper, 14900k,完全使用官方默认设置&#xff0c;没有出现其他问题。 目前只对examples/aloha_sim进行测试&#xff0c;使用docker进行部署, 默认使用pi0_aloha_sim模型(但是文档上没找到对应的&…

计算机视觉——利用AI幻觉检测图像是否是生成式算生成的图像

概述 俄罗斯的新研究提出了一种非常规方法&#xff0c;用于检测不真实的AI生成图像——不是通过提高大型视觉-语言模型&#xff08;LVLMs&#xff09;的准确性&#xff0c;而是故意利用它们的幻觉倾向。 这种新方法使用LVLMs提取图像的多个“原子事实”&#xff0c;然后应用自…

FlaskRestfulAPI接口的初步认识

FlaskRestfulAPI 介绍 记录学习 Flask Restful API 开发的过程 项目来源&#xff1a;【Flask Restful API教程-01.Restful API介绍】 我的代码仓库&#xff1a;https://gitee.com/giteechaozhi/flask-restful-api.git 后端API接口实现功能&#xff1a;数据库访问控制&#xf…

CSS预处理工具有哪些?分享主流产品

目前主流的CSS预处理工具包括&#xff1a;Sass、Less、Stylus、PostCSS等。其中&#xff0c;Sass是全球使用最广泛的CSS预处理工具之一&#xff0c;以强大的功能、灵活的扩展性以及完善的社区生态闻名。Sass通过增加变量、嵌套、混合宏&#xff08;mixin&#xff09;等功能&…

AI 速读 SpecReason:让思考又快又准!

在大模型推理的世界里&#xff0c;速度与精度往往难以兼得。但今天要介绍的这篇论文带来了名为SpecReason的创新系统&#xff0c;它打破常规&#xff0c;能让大模型推理既快速又准确&#xff0c;大幅提升性能。想知道它是如何做到的吗&#xff1f;快来一探究竟&#xff01; 论…

Qt通过ODBC和QPSQL两种方式连接PostgreSQL或PolarDB PostgreSQL版

一、概述 以下主要在Windows下验证连接PolarDB PostgreSQL版&#xff08;阿里云兼容 PostgreSQL的PolarDB版本&#xff09;。Linux下类似&#xff0c;ODBC方式则需要配置odbcinst.ini和odbc.ini。 二、代码 以下为完整代码&#xff0c;包含两种方式连接数据库&#xff0c;并…

MobaXterm连接Ubuntu(SSH)

1.查看Ubuntu ip 打开终端,使用指令 ifconfig 由图可知ip地址 2.MobaXterm进行SSH连接 点击session,然后点击ssh,最后输入ubuntu IP地址以及用户名

蓝桥杯2024省A.成绩统计

蓝桥杯2024省A.成绩统计 题目 题目解析与思路 题目要求返回至少要检查多少个人的成绩&#xff0c;才有可能选出k名同学&#xff0c;他们的方差小于一个给定的值 T 二分枚举答案位置&#xff0c;将答案位置以前的数组单独取出并排序&#xff0c;然后用k长滑窗O(1)计算方差 问…

Mac mini 安装mysql数据库以及出现的一些问题的解决方案

首先先去官网安装一下mysql数据库&#xff0c;基本上都是傻瓜式安装的流程&#xff0c;我也就不详细说了。 接下来就是最新版的mysql安装的时候&#xff0c;他就会直接让你设置一个新的密码。 打开设置&#xff0c;拉到最下面就会看到一个mysql的图标&#xff1a; 我设置的就是…

俄罗斯方块-简单开发版

一、需求分析 实现了一个经典的俄罗斯方块小游戏&#xff0c;主要满足以下需求&#xff1a; 1.图形界面 使用 pygame 库创建一个可视化的游戏窗口&#xff0c;展示游戏的各种元素&#xff0c;如游戏区域、方块、分数等信息。 2.游戏逻辑 实现方块的生成、移动、旋转、下落和锁…

你学会了些什么200601?--Flask搭建造测试数据平台

搭建造数平台的环境&#xff1a; ***python3.7 ***html5 ***css ***JavaScript ***Ajax ***MySQL 前台页面的显示 1.为了页面美化&#xff0c;使用了JavaScript&#xff0c;通过逐级展开/隐藏的的方式显示下一级菜单 2.为了在提交表单数据时页面不发生跳转&#xff0c;需要引用…

【音视频】FLV格式分析

FLV概述 FLV(Flash Video)是Adobe公司推出的⼀种流媒体格式&#xff0c;由于其封装后的⾳视频⽂件体积⼩、封装简单等特点&#xff0c;⾮常适合于互联⽹上使⽤。⽬前主流的视频⽹站基本都⽀持FLV。采⽤FLV格式封装的⽂件后缀为.flv。 FLV封装格式是由⼀个⽂件头(file header)和…

Keil5没有stm32的芯片库

下载完重启就行了&#xff0c;我这里就不演示了&#xff0c;stm已经下载&#xff0c;随便选的一个芯片库演示一下