C语言---数据结构(1)--时间复杂和空间复杂度计算

 





1.什么是时间复杂度和空间复杂度

1.1算法效率

算法效率分为时间效率和空间效率

时间效率被称为时间复杂度,而空间效率被称作空间复杂度。 时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间,在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度,现在主要关注的是空间效率

1.2时间复杂度的概念

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运

行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机

器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻

烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比

例,算法中的基本操作的执行次数,为算法的时间复杂度。

1.3 空间复杂度的概念

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用

了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计

算规则基本跟实践复杂度类似,也使用大O渐进表示法。

2.如何计算常见算法的时间复杂度和空间复杂度

时间复杂度不算时间,算次数,空间复杂度不算空间,算变量个数

时间复杂度的计算

实际中我们在计算时间复杂度时,我们其实并不一定要计算精确的执行次数,只需要大概执行次数,那么我们这里就使用大O的渐进表示法

大O符号:是用于描述函数渐进行为的数学符号

推导大O阶方法:

1、用常数1取代运行时间中的所有加法常数。

2、在修改后的运行次数函数中,只保留最高阶项。

3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

使用大O的渐进表示法以后,

另外有些算法的时间复杂度存在最好、平均和最坏情况:

最坏情况:任意输入规模的最大运行次数(上界)

平均情况:任意输入规模的期望运行次数

最好情况:任意输入规模的最小运行次数(下界)

例如:在一个长度为N数组中搜索一个数据x

最好情况:1次找到

最坏情况:N次找到

平均情况:N/2次找到

在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

比如后面的计算strchr的时间复杂度

// 请计算一下Func1基本操作执行了多少次?
void Func1(int N)
{
    int count = 0;
    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            ++count;
        }
    }
    //对于这个循环来说,因为这是一个嵌套的循环,两层循环,外面执行N次,里面执行N次
    //所以这个循环总共执行N*N次
    for (int k = 0; k < 2 * N; ++k)
    {
        ++count;
    }
    //这个循环的循环次数是2*N
    int M = 10;
    while (M--)
    {
        ++count;
    }
    printf("%d\n", count);
}
//因为M被初始化为10,那么这个while循环会执行10次
int main()
{
    int n=0;
    scanf("%d", &n);
    Func1(n);
    return 0;

}
//所以看来这个准确的次数是:N*N+2*N+10
//F(N)=N^2+2*N+10
//N=10F(N)=130
//N=100F(N)=10210
//N=1000F(N)=1002010
//随着N的增大,这个表达式中N^2对结果的影响是最大的

//时间复杂度是一个估算,是去看表达式中影响最大的那一项

//时间复杂度用到一个
//大O的渐进表示法,估算

//时间复杂度:O(N^2)

Func1的时间复杂度为:O(N6^2)

我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表达了代码执行的次数

// 计算Func2的时间复杂度?
void Func2(int N)
{
    int count = 0;
    for (int k = 0; k < 2 * N; ++k)
    {
        ++count;
    }

    int M = 10;
    while (M--)
    {
        ++count;
    }
    printf("%d\n", count);
}

//2*N+10
//时间复杂度就是O(N)
//那么为什么不是O(2N)呢?

//根据大O阶推导的方法三中提到:
//3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。

//使用大O的渐进表示法以后,

//因为我们的N逐渐变大,前面的2对结果的影响不大

//所以这个题目的时间复杂度就是O(N)

我们要求去掉N前面的2,随着N的变大,前面的2对结果的影响不是很大,所以去掉

那么这个代码的时间复杂度就是O(N)

// 计算Func3的时间复杂度?
void Func3(int N, int M)
{
    int count = 0;
    for (int k = 0; k < M; ++k)
    {
        ++count;
    }
    for (int k = 0; k < N; ++k)
    {
        ++count;
    }

    printf("%d\n", count);
}

//这个代码的时间复杂度就是O(N+M)
//因为我们现在不知道N和M的大小,现在对于我都是未知数

//所以我们在计算时间复杂度的时候,可能遇到的不止一个未知数,可能有多个未知数

//一般情况下只有1个未知数的


//但是这个题如果有个条件:M远大于N,那么这个代码的时间复杂度就是O(M)

//假设M和N差不多大,那么时间复杂度就是O(M)或者O(N)

这个代码存在多个未知的值,M和N,那么这个复杂度就要根据这个M和N的大小进行比较了

// 计算Func4的时间复杂度?
void Func4(int N)//这个N我们没有用到
{
    int count = 0;
    for (int k = 0; k < 100; ++k)
    {
        ++count;
    }
    printf("%d\n", count);
}
//因为这个代码给的N我们没有用到
//那么这个代码的时间复杂度是多少呢?
//是O(1)

//为什么呢
/*
根据推导大O阶方法1我,们可以知道
1、用常数1取代运行时间中的所有加法常数。

因为这个循环的次数是100,是常数,那么我们的这个时间复杂度就用1来替换了

//那么我们最终就得到了O(1)

所以我们在以后遇到的常数次都是O(1)


不管这个常数次是多大,N永远都是不变的,N的效率是固定的*/

因为这个代码是没有用到未知数的,循环的次数仅仅只是一个常数,那么这个题的时间复杂度我们就用O(1)表示,将常量用1来替换

// 计算strchr的时间复杂度?
const char* strchr(const char* str, char character)
{
    //遍历字符串中'\0'之前的字符,
    while (*str != '\0')
    {
        if (*str == character)//将这个指针指向的字符和传过来的字符进行判断
            //如果是一样的字符,那么我们就返回这个字符的位置
            return str;

        ++str;//指针++,换下一个字符进行判断
    }

    return NULL;//走到最后都没找到,我们就直接返回一个空指针
}
//这个函数是我们在字符串里面找到我们想要的字符
//那么这个题的时间复杂度怎么说呢?
/*
* 假设这个字符串的长度是N
那么就存在三种可能性:最好、最坏、平均
最坏:就是运行N次才找到                   O(N)
平均:进行到一半才找到                    O(N/2)
最好:一个常数下,假如5次、1次就找到了    O(1)


但是在实际中一般情况关注的是算法的最坏运行情况
所以数组中搜索数据的这个题的时间复杂度是O(N)

我们做出最坏的打算,但是这里也是最靠谱的
*/



/*
做出拓展
1.我们现在给出一个字符串,是长还是短,这个字符串的长度都是不变的
那么这个题时间复杂度就是O(1),效率是不变的


2.如果时间复杂度是O(N)的话,是表达的什么呢?
N就是字符串的长度,随着字符串的变长,这个题目的效率也线性的变长了


*/

这里我们用到了最坏运行情况,在这个字符串中找了N次才找到我们想要的字符

// 计算BubbleSort的时间复杂度?
void BubbleSort(int* a, int n)
{
    assert(a);
    for (size_t end = n; end > 0; --end)
    {
        int exchange = 0;
        for (size_t i = 1; i < end; ++i)
        {
            if (a[i - 1] > a[i])
            {
                Swap(&a[i - 1], &a[i]);
                exchange = 1;
            }
        }
        if (exchange == 0)
            break;
    }
}

/*
我们先来归纳一下冒泡排序的思想:
在这个数组中,如果第一个数大于第二个数,那么就将这两个数的位置进行交换
将大的数字放后面,小的数字放前面


第一趟冒泡N
第二趟冒泡N-1
第三趟冒泡N-2

第N趟冒泡1


那么这里的次数就是首项+尾项乘以项数除以二
(N+1)*N/2=(N*N+N)/2
上面就是这道题准确的次数

但对于结果影响最大的一项是N^2,因为上面将表达式分解了,所以最大影响的是N方

那么表达就是O(N^2)


这个是阶乘,我们将阶乘的每一项加起来就是这个准确次数了

*/

这个是阶乘,我们将阶乘的每一项加起来就是这个准确次数了,

不是说一层循环就是O(N),两层循环就是O(N^2)

具体看程序,最好通过过程去分析

// 计算BinarySearch的时间复杂度?

//二分查找
//二分查找的前提是数组是有序的
int BinarySearch(int* a, int n, int x)
{
    assert(a);
    int begin = 0;
    int end = n;
    while (begin < end)
    {
        int mid = begin + ((end - begin) >> 1);
        if (a[mid] < x)
            begin = mid + 1;
        else if (a[mid] > x)
            end = mid;
        else
            return mid;
    }
    return -1;
}

/*
最好的情况:O(1)

假设找了x次
1*2*2*2*2*2.....找了多少次就乘了多少次2
最后的结果就是这整个数组的长度

2^x=N
所以次数x就是log2N--以2为底N的对数

那么对于这个题的话
算法的复杂度计算,喜欢省略写成logN,将2省略掉,因为很多地方不好写底数

有些书本,或者网上资料会写成O(lgN),严格来说这个是不对的,因为
这个底数就是10,不符合

那么时间复杂度就是O(logN)
*/
// 计算阶乘递归Factorial的时间复杂度?
//这道题实现阶乘递归
long long Factorial(size_t N)
{
    return N < 2 ? N : Factorial(N - 1) * N;
}
/*
整个次数就是1*2*3*4*5*6*7*8*9*10
就是10的阶乘
那么这个时间复杂度是多少呢?
递归调用了N次,每次递归运算是O(1)
那么整体就是O(N)
*/

常见的时间复杂度:O(N^2) O(N) O(logN) O(1)

复杂度对比

 

O(1)就是随着这个数量的增加,他是一直都是不变的

二分查找,在一个中国有14亿人中找一个人,最多找几次

31次就行 2的30次方是10亿,那么2的31次方就是20亿人

空间复杂度的计算

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用

了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计

算规则基本跟实践复杂度类似,也使用大O渐进表示法,类似时间复杂度的方式,也是估算

总结:时间复杂度不算时间,算次数,空间复杂度不算空间,算变量个数

// 计算BubbleSort的空间复杂度?
void BubbleSort(int* a, int n)
{
    assert(a);
    for (size_t end = n; end > 0; --end)
    {
        int exchange = 0;
        for (size_t i = 1; i < end; ++i)
        {
            if (a[i - 1] > a[i])
            {
                Swap(&a[i - 1], &a[i]);
                exchange = 1;
            }
        }
        if (exchange == 0)
            break;
    }
}
/*
size_t end = n
int exchange = 0
size_t i = 1
三个变量
因为这里的3是常数,那么我们就用1将3代替
那么空间复杂度就是O(1)

循环走了N次,重复利用的是一个空间
*/
// 计算Fibonacci的空间复杂度?
long long* Fibonacci(size_t n)
{
    if (n == 0)
        return NULL;
    long long* fibArray = (long long*)malloc((n + 1) * sizeof(long long));
    fibArray[0] = 0;
    fibArray[1] = 1;
    for (int i = 2; i <= n; ++i)
    {
        fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
    }
    return fibArray;
}
/*
size_t n
fibArray
fibArray[0] = 0;
fibArray[1] = 1;
i

这里是5个变量,但是那里有一个malloc,开辟了一个N+1个元素的数组,有n+1个
所以总共是N+6个,但是随着N的增大,6对结果的影响不大
所以这里的空间复杂度就是O(N)

大多数情况之下我们遇到的空间复杂度都是O(1)
因为变量都是常数个
*/

这里就不同了,因为我们使用malloc开辟了一个n+1个元素的空间,原本的变量就有5个,所以总共的变量就是N+6,但是6对结果的影响不大,所以这个题的空间复杂度就是O(N)

// 计算阶乘递归Factorial的空间复杂度?
long long Factorial(size_t N)
{
    return N < 2 ? N : Factorial(N - 1) * N;
}
/*
递归调用了N层,每次调用简历一个栈帧使用了常数个空间,那么每一层就是O(1)
有N个栈帧,空间复杂度就是O(N)

空间复杂度看的是我们最多的时候占了多少空间,也就是看最坏的情况之最大空间是多少


对于递归,调用时建立栈帧,返回时就会销毁栈帧

*/

空间复杂度看的是我们最多的时候占了多少空间,也就是看最坏的情况的时候我们用了最大空间是多少

复杂度计算在算法中的意义

3.有复杂度要求的算法题练习

找到消失的数字--类似单身狗问题

重点:0跟任何数异或那么得到的就是任何数

//数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
/*
思路一:给数组排序,我们现将数组排成有序数列,再进行判断,看看两个数之间相差的大小是不是1
但是不符合时间复杂度,存在问题,用快速排序的时间复杂度都是O(N*logN),那么其他的排序的时间复杂度更大了
排序直接将时间都消耗完了,所以这个题目排序是不行的


思路二:将原本不缺少数字的数组内的数字相加得到S1,再将缺少了一个数字的数字内的元素全加,得到了S2
那么S2-S1得到的就是缺少的数字


思路三:使用异或*(相同就为0,相异为1)
2^3
00000010
00000011
00000001---异或的结果

相同的数异或就是0    1^1=0   2^2=0
那么我们将两个数组内的数依次进行异或
一个数组不差数字
一个数组差一个数字
两个数组内的元素进行异或,最后出现两次的数就抵消为0,那么最后的结果就是只出现一个的那个数
*/
int missingNumber(int*nums,int numsSize)//numsSize是这个却数字的数组的元素个数
{
    int x=0;//创建变量x并赋值为0,因为0跟任何数异或得到的都是任何数
    for(int i=0;i<numsSize;i++)
    {
        x^=nums[i];//将数组内的值进行累异或
    }
    for(int j=0;j<numsSize+1;j++)//因为上面传的是一个差了一个数的数组,那么我们现在要将不差数字的那个数组进行累异或操作,所以这个数组的大小是nmusSize+1
    {
        //这里的x最开始是上面缺数字的那个数组累异或的结果
        x^=j;//从0开始累异或,0和任何数异或得到的就是那个任何数,
    }
    return x;


}

旋转数组

/*
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?

要求空间复杂度为O(1)
*/

第一种方法:

跑不过去,存在漏洞,不符合题目要求,测试用例中给了一个非常大的数字

/*
一次右旋就是将数组中最后的一个数保留,再将前面的数字往后挪一位,再把最后的那个数放到第一位

*/
void rotate(int* nums, int numsSize, int k)
{
  //当前算法时间复杂度是:O(N*K),内循环走了N次,外循环走了k次,那么总的次数就是N*K
    while(k--)
    {
        int tmp=nums[numsSize-1];//创建一个临时变量将数组中最后一个元素进行保存,总共numsSize个数,那么最后一个数下标就是numsSize-1
        for(int end=numsSize-2;end>=0;--end)//创建临时变量end,让end指向这个数组的倒数第二个元素的位置,下标就是numsSize-2
        {//循环从这个数组的倒数第二个元素开始,我们每次将数组中两个相邻的数字中的后面一位上的数字赋值为前面的数字
    //就是相当于将前面的数字往后挪了一位
            nums[end+1]=nums[end];
        }
        nums[0]=tmp;//将数组内的元素整体向后移了一位,那么第一位的数字我们就将之前赋值上的最后一位数组放过去
    //那么现在第一位上面就是上次右旋最后一位数字了
    //那么上面的代码就是第一次旋转的代码了,如果像旋转k次的话,那我们就将这个旋转一次的代码放到while循环里面去
    }
}
//但是这个方法对于这个题是跑不过的,所以我们得换方法

第二种方法:

以空间换时间

/*
思路二:以空间换时间
将数组中的后k个放到前面开,将前面的剩下的N-K个放到后面去

这种的话时间复杂度是O(N),空间复杂度是O(N),但是这样就不满足题目的要求了,题目要求空间复杂度为O(1)
*/

void rotate(int* nums, int numsSize, int k)
{

}
#include <stdio.h>

void rotate(int nums[], int n, int k) {
    // 计算实际需要轮转的位数,因为 k 可能大于数组长度
    k = k % n;
    int temp[k]; // 创建临时数组存储 k 个元素

    // 将数组的后 k 个元素存储到临时数组
    for (int i = 0; i < k; i++) {
        temp[i] = nums[n - k + i];
    }

    // 将数组的前 n-k 个元素向后移动 k 个位置
    for (int i = n - 1; i >= k; i--) {
        nums[i] = nums[i - k];
    }

    // 将临时数组中的元素复制到数组的前 k 个位置
    for (int i = 0; i < k; i++) {
        nums[i] = temp[i];
    }
}

第三种方法:

将后K个逆置,前N-K个逆置,再整体逆置

创建逆置的函数,我们再将具体的区间传上去进行逆置

/*
思路三:将后K个逆置,前N-K个逆置,再整体逆置
1   2   3   4   5   6   7
1   2   3   4   7   6   5
4   3   2   1   7   6   5         将4 5 对换位置,6 3对换位置  2 7对换位置
5   6   7   1   2   3   4----这就是旋转3步的结果
*/

/*
假设k=3
假设数组是1 2 3 4 5 6 7
我们现在要旋转k次,那么我们先旋转数组后K个
最后一个元素7的下表是N-1,那么5的下标就是N-K
将N-K到N-1这个范围的元素先进行逆置

我们再将前面剩下的N-K个元素进行逆置
数组首元素的下标是0,4的下标是N-K-1

最后我们就将整体进行逆置就好了

*/
//有可能K大于这个数组的大小,那么就会存在越界的情况,
/*
假如k是13,但是数组元素是7,那么我们应该怎么办呢?
k是13相当于我们旋转了6次,因为旋转7次相当于不变,因为旋转了7次的结果和原来是一样的,
那么我们就要进行判断,如果k>=numsSize,旋转次数大于数组元素个数的话,我们就将k的值取模
*/



void Reverse(int* nums, int left, int right)//对数组的一段区间进行逆置
{
    /*
    1 2 3 4
    1和4交换,2和3交换,最开始的left指向1,right指向4,交换完成之后,;left++,right--,再进行2和3的交换
    */
    while(left<right)
    {
        //下面的就是交换的代码
        int tmp=nums[left];
        nums[left]=nums[right];
        nums[right]=tmp;
        ++left;
        --right;
    }
}
void rotate(int* nums, int numsSize, int k)
{
    if(k>=numsSize)
    {
        k%=numsSize;
    }
   Reverse(nums,numsSize-k,numsSize-1);//先将后K个进行逆置
   Reverse(nums,0,numsSize-k-1);//将剩下的N-K个元素进行逆置
   Reverse(nums,0,numsSize-1);//将整体进行逆置
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python自动化系列:自动制作PPT演示稿(多种元素)

作品介绍 作品名称&#xff1a;自动制作PPT演示稿&#xff08;多种元素&#xff09; 开发环境&#xff1a;PyCharm 2023.3.4 python3.7 用到的库&#xff1a;pptx 作品简介&#xff1a;该实例使用python-pptx库从头开始创建一个包含多种元素&#xff08;如标题、文本、图片…

中国能源统计年鉴(1986-2023年)

数据年份&#xff1a;1986-2023年&#xff0c;无1987、1988、1990三年&#xff0c;1991-2023年齐 数据格式&#xff1a;pdf、excel 数据内容&#xff1a;《中国能源统计年鉴》是一部反映中国能源建设、生产、消费、供需平衡的权威性资料书。 共分为7个篇章&#xff1a;1.综合&a…

AI赋能天气:微软研究院发布首个大规模大气基础模型Aurora

编者按&#xff1a;气候变化日益加剧&#xff0c;高温、洪水、干旱&#xff0c;频率和强度不断增加的全球极端天气给整个人类社会都带来了难以估计的影响。这给现有的天气预测模型提出了更高的要求——这些模型要更准确地预测极端天气变化&#xff0c;为政府、企业和公众提供更…

Python-矩阵元素定位

[题目描述] 小理得到了一个 n 行 m 列的矩阵&#xff0c;现在他想知道第 x 行第 y 列的值是多少&#xff0c;请你帮助他完成这个任务。输入格式&#xff1a; 第一行包含两个数 n 和m &#xff0c;表示这个矩阵包含 n行 m 列。从第 2 行到第 n1 行&#xff0c;每行输入 m 个整数…

vue中用JSON格式查看数据(vue-json-viewer)

vue中把string用JSON格式展示数据 vue-json-viewer使用 官网地址&#xff1a;https://www.npmjs.com/package/vue-json-viewer 1. 安装插件vue-json-viewer //vue2 npm install vue-json-viewer2 --save //vue3 npm install vue-json-viewer3 --save2. 引入vue-json-viewer…

“论SOA在企业集成架构设计中的应用”写作框架,系统架构设计师

论文真题 企业应用集成(Enterprise Application Integration, EAI)是每个企业都必须要面对的实际问题。面向服务的企业应用集成是一种基于面向服务体系结构(Service-OrientedArchitecture,SOA&#xff09;的新型企业应用集成技术&#xff0c;强调将企业和组织内部的资源和业务…

【C语言】函数执行背后的秘密:函数栈帧的创建和销毁超详解

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 目录 1. 什么是函数栈帧 2. 理解函数栈帧能解决什么问题呢&#xff1f; 3. 函数栈帧的创建和销毁解析 3.1 什么是栈&#xff1f; 3.2 认识相关寄存器和汇编指…

vscode在windows系统上进行C/C++环境配置

随手笔记前言 vscode在windows系统上进行C/C环境配置 步骤如下 第一步 下载安装VSCode 这应该是最简单的一步&#xff0c;相信大家自己就可以完成。如果在vscode官网感觉下载特别慢的话&#xff0c;可以去试一下腾讯软件中心&#xff0c;我都是在这个网页上下载的。下载好之…

Huffman树——AcWing 148. 合并果子

目录 Huffman树 定义 运用情况 注意事项 解题思路 AcWing 148. 合并果子 题目描述 运行代码 代码思路 其它代码 代码思路 Huffman树 定义 它是一种最优二叉树。通过构建带权路径长度最小的二叉树&#xff0c;经常用于数据压缩等领域。 运用情况 在数据压缩中&a…

RK3568开发笔记(三):瑞芯微RK3588芯片介绍,入手开发板的核心板介绍

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/139905873 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

格雷码计数器

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 参考代码 描述 实现4bit位宽的格雷码计数器。 电路的接口如下图所示。 输入描述&#xff1a; input clk, input rst_n 输出描述&#xff1a; output reg [3:0] gray_out 参考代码 timescale 1ns/1nsmod…

等级保护测评中的建设整改要做什么?

随着信息技术的飞速发展&#xff0c;信息系统已成为现代社会运转的核心。然而&#xff0c;网络安全问题的日益突出&#xff0c;使得信息系统的安全稳定运行面临着严峻挑战。为了有效应对这一挑战&#xff0c;我国推行了等级保护制度&#xff0c;其中建设整改作为等级保护工作的…

指令微调数据集构建方法

指令微调&#xff08;Instruction Tuning&#xff09;&#xff0c;是指使用自然语言形式的数据对预训练后的大语言模型进行参数微调&#xff0c;在一些文章中也称为有监督微调&#xff08;Supervised Fine-tuning&#xff0c;SFT&#xff09;或多任务提示训练&#xff08;Multi…

ONLYOFFICE8.1版本桌面编辑器测评

OO官方链接点这里&#xff1a;ONLYOFFICE 文档 8.1 现已发布&#xff1a;功能全面的 PDF 编辑器、幻灯片版式、优化电子表格的协作等等 | ONLYOFFICE 博客 一、界面与用户体验 整体布局和设计的美观性、易用性&#xff1a; ONLYOFFICE 8.1 版本的桌面编辑器展现出了令人眼前一亮…

【ISAC】通感一体化讲座(刘凡)

高斯信道下通信感知一体化的性能极限(刘凡) 文章目录 背景背景 通信和感知在硬件结构上相似,高效地利用资源,实现相互的增益; 感知是基于不同的任务,比如目标检测(检测概率,虚警概率),估计任务(从收到的信号中去估计有用的参数,均方误差,CRB),识别(知道目标的…

开源seata的分布式事务解决方案-XA、AT、TCC、SAGA哪个模式好

分布式事务是分布式系统中非常重要的一部分。假设一个用户购买商品的业务逻辑&#xff0c;系统有3个微服务组成&#xff0c;分别是订单服务、账户服务、库存服务&#xff0c;用户在提交订单后会从用户账户余额中扣款&#xff0c;同时扣减库存数量。在这样的场景下扣款和减库存需…

Vue核心指令解析:探索MVVM与数据操作之美

文章目录 前言一、Vue.js1. MVVM模式介绍2. 单页面组件介绍及案例讲解3. 插值表达式介绍及案例讲解 二、Vue常用指令详解1. 数据绑定指令v-textv-html 2. 条件渲染指令v-ifv-show 3. 列表渲染指令v-for循环数组介绍及案例讲解循环对象介绍及案例讲解 4. 事件监听指令v-on事件修…

【unity小技巧】unity事件系统创建通用的对象交互的功能

文章目录 前言实现1. **InteractEvent 类**&#xff1a;2. **Interact 类**&#xff1a;3. **Player 类**&#xff1a;4. **Chest 类**&#xff1a; 工作流程说明&#xff1a;开单个箱子按钮触发打开很多箱子拾取物品&#xff08;传参&#xff09;参考完结 前言 游戏开发过程中…

有效利用MRP能为中小企业带来什么?

在离散制造企业&#xff0c;主流的生产模式主要为面向订单生产和面向库存生产&#xff08;又称为预测生产&#xff09;&#xff0c;在中小企业中&#xff0c;一般为面向订单生产&#xff0c;也有部分面向库存和面向订单混合的生产方式&#xff08;以面向订单为主&#xff0c;面…

【初阶数据结构】深入解析栈:探索底层逻辑

&#x1f525;引言 本篇将深入解析栈:探索底层逻辑&#xff0c;理解底层是如何实现并了解该接口实现的优缺点&#xff0c;以便于我们在编写程序灵活地使用该数据结构。 &#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1…