【数据结构与算法】【小白也能学的数据结构与算法】递归 分治 迭代 动态规划 无从下手?一文通!!!

news2024/11/16 0:53:19

 🎉🎉欢迎光临🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟特别推荐给大家我的最新专栏《数据结构与算法:初学者入门指南》📘📘

本专栏纯属为爱发电永久免费!!!

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽icon-default.png?t=N7T8http://suzee.blog.csdn.net/

按自己需要跳哈 还是从小白的出发从浅到深

目录

了解递归:从简单到复杂

递归的概念和基本原理

递归算法的优缺点

优点:

缺点:

进阶递归技巧:优雅解决问题

尾递归和非尾递归

递归的边界条件和终止条件

递归调用的内存管理与性能优化

分治思想的基本原理

场景引发思考

引入分治思想

分析分治思想的原理

如何实现分治算法

分治与递归的关系与区别

分治和递归的定义和特点

分治和递归之间的联系和区别

代码示例解析

动态规划与递归的联系与区别

动态规划的概念和优势

动态规划

动态规划的思路

代码示例解析

迭代替代递归提高效率


递归

了解递归:从简单到复杂

递归是一种强大的问题解决方法,通过将问题分解为子问题并通过调用自身来解决。在本篇博客中,我们将深入了解递归的概念和基本原理,并使用C语言实现一些示例代码。

递归的概念和基本原理

递归是一种通过调用自身来解决问题的方法。它基于两个重要的原则:递归定义和递归终止条件。

递归定义是将一个大问题分解为一个或多个相同类型的子问题,并通过调用自身来解决这些子问题。递归终止条件是指当问题的规模足够小,可以直接解决时,递归停止并返回结果。

一个经典的递归应用场景是计算阶乘。阶乘的递归定义是n的阶乘等于n乘以(n-1)的阶乘,直到n等于1时终止。下面是用C语言实现计算阶乘的递归函数:

#include <stdio.h>

int factorial(int n) {
    if (n == 0 || n == 1) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

int main() {
    int n = 5;
    int result = factorial(n);
    printf("The factorial of %d is %d\n", n, result);
    return 0;
}

在这个例子中,递归函数factorial通过调用自身来计算阶乘,当n等于0或1时,递归终止并返回1作为结果。

递归算法的优缺点

递归算法具有一些优点和缺点,下面我们将分别进行论述。

优点:
  1. 简化问题:递归能够将复杂的问题分解为更小的子问题,使问题更易于理解和解决。

  2. 优雅的解决方案:递归可以提供一种优雅的解决方案,使代码更加简洁和可读。

缺点:
  1. 内存消耗:递归调用会占用额外的内存空间,因为每个递归函数调用都需要保存函数的状态和局部变量。当递归的深度较大时,可能会导致栈溢出的问题。

  2. 性能损耗:递归调用的性能相对较低,因为每次函数调用都需要额外的开销。特别是在处理大规模问题时,递归可能导致性能下降。

进阶递归技巧:优雅解决问题

在递归中,我们可以使用一些技巧和思维模式来优雅地解决问题。下面介绍两个常用的技巧:尾递归和非尾递归。

尾递归和非尾递归

尾递归是指递归函数在递归调用的最后一步执行,且递归调用的返回值直接作为当前递归函数的返回值。尾递归的优点是可以通过尾递归优化,将递归转化为迭代,减少函数调用的内存消耗。

下面是一个计算斐波那契数列的尾递归实现例子:

#include <stdio.h>

int fibonacci(int n, int a, int b) {
    if (n == 0) {
        return a;
    } else if(n == 1) {
        return b;
    } else {
        return fibonacci(n - 1, b, a + b);
    }
}

int main() {
    int n = 6;
    int result = fibonacci(n, 0, 1);
    printf("The %dth Fibonacci number is %d\n", n, result);
    return 0;
}

在这个例子中,fibonacci函数使用尾递归实现斐波那契数列的计算。通过使用额外的参数来保存中间结果,避免了不必要的函数调用和内存消耗。

非尾递归是指递归函数在递归调用后还需要执行一些操作,而不是直接返回递归调用的结果。

非尾递归在某些情况下可能更好,尤其是在处理复杂的数据结构或算法时。以下是一个示例,说明非尾递归在某些情况下的优势。

问题描述:给定一个二叉树,计算树中所有节点的总和。

非尾递归的方案:

#include <stdio.h>
#include <stdlib.h>

typedef struct TreeNode {
    int val;
    struct TreeNode* left;
    struct TreeNode* right;
} TreeNode;

int sumOfNodes(TreeNode* root) {
    if (root == NULL) {
        return 0;
    }
    
    int leftSum = sumOfNodes(root->left);
    int rightSum = sumOfNodes(root->right);
    
    return root->val + leftSum + rightSum;
}

int main() {
    // 构建一个二叉树
    TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
    root->val = 1;
    
    TreeNode* left = (TreeNode*)malloc(sizeof(TreeNode));
    left->val = 2;
    
    TreeNode* right = (TreeNode*)malloc(sizeof(TreeNode));
    right->val = 3;
    
    root->left = left;
    root->right = right;
    
    int result = sumOfNodes(root);
    printf("Sum of nodes: %d\n", result);
    
    free(left);
    free(right);
    free(root);
    
    return 0;
}

在这个例子中,我们使用递归的方式计算二叉树中所有节点的总和。递归地调用sumOfNodes函数计算左子树和右子树的节点总和,然后将根节点的值与子树的总和相加。

尾递归的解决方案如下:

#include <stdio.h>
#include <stdlib.h>

typedef struct TreeNode {
    int val;
    struct TreeNode* left;
    struct TreeNode* right;
} TreeNode;

int sumOfNodes(TreeNode* root, int currentSum) {
    if (root == NULL) {
        return currentSum;
    }
    
    currentSum += root->val;
    
    currentSum = sumOfNodes(root->left, currentSum);
    currentSum = sumOfNodes(root->right, currentSum);
    
    return currentSum;
}

int main() {
    // 构建一个二叉树
    TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
    root->val = 1;
    
    TreeNode* left = (TreeNode*)malloc(sizeof(TreeNode));
    left->val = 2;
    
    TreeNode* right = (TreeNode*)malloc(sizeof(TreeNode));
    right->val = 3;
    
    root->left = left;
    root->right = right;
    
    int result = sumOfNodes(root, 0);
    printf("Sum of nodes: %d\n", result);
    
    free(left);
    free(right);
    free(root);
    
    return 0;
}

在这个例子中,我们使用尾递归的方式计算二叉树中所有节点的总和。将当前节点的值加到currentSum上,并将更新后的currentSum传递给递归调用。这样,递归调用不会增加额外的堆栈帧,而是保持在同一层级上进行计算。

尽管在这个例子中,尾递归的解决方案与非尾递归的解决方案在结果上是相同的,但在处理更复杂的数据结构或算法时,非尾递归的解决方案可能更直观和易于理解。非尾递归可以更好地表达问题的逻辑,而且不需要额外的参数传递。

所以我们要根据题目的具体情况而选定用哪种(其实实际上两种都能互相解决各自的问题 我一般直接用尾递归就好了)

递归的边界条件和终止条件

递归的边界条件和终止条件非常重要,它们决定了递归何时停止并返回结果。边界条件是指问题规模足够小,可以直接解决的情况。终止条件是指当问题满足边界条件时,递归停止并返回结果。

下面是一个递归实现的二分查找算法的例子:

#include <stdio.h>

int binarySearch(int arr[], int low, int high, int target) {
    if (low > high) {
        return -1;
    }
    
    int mid = (low + high) / 2;
    
    if (arr[mid] == target) {
        return mid;
    } else if (arr[mid] > target) {
        return binarySearch(arr, low, mid - 1, target);
    } else {
        return binarySearch(arr, mid + 1, high, target);
    }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
    int n = sizeof(arr) / sizeof(arr[0]);
    int target = 6;
    
    int result = binarySearch(arr, 0, n - 1, target);
    
    if (result == -1) {
        printf("Element not found\n");
    } else {
        printf("Element found at index %d\n", result);
    }
    
    return 0;
}

在这个例子中,binarySearch函数使用递归实现了二分查找算法。递归终止条件是当low大于high时,说明查找范围为空,返回-1表示未找到目标元素。

递归调用的内存管理与性能优化

递归调用涉及内存管理和性能优化。在实际使用中,我们需要注意以下几点来管理内存和提高性能:

  1. 尽量减少递归调用的层数,以避免栈溢出的问题。可以考虑使用迭代或尾递归优化来降低内存消耗。

  2. 注意内存的释放。在使用动态分配的内存(例如使用malloc函数分配的内存)时,要确保在递归结束后释放内存,避免内存泄漏。

下面是一个使用递归实现斐波那契数列的示例代码,同时给出了对应的优化后的代码:

#include <stdio.h>
#include <stdlib.h>

// 未优化的递归实现
int fibonacci(int n) {
    if (n == 0 || n == 1) {
        return n;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

// 优化后的递归实现,使用动态规划保存中间结果
int fibonacciOptimized(int n) {
    int* dp = (int*) malloc((n + 1) * sizeof(int));
    dp[0] = 0;
    dp[1] = 1;
    
    for (int i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    
    int result = dp[n];
    free(dp); // 释放动态分配的内存
    
    return result;
}

int main() {
    int n = 6;
    
    int result = fibonacciOptimized(n);
    
    printf("The %dth Fibonacci number is %d\n", n, result);
    
    return 0;
}

在这个例子中,我们使用动态规划的思想优化了斐波那契数列的递归实现。通过使用一个数组dp来保存中间结果,避免了重复计算。在递归结束后,我们使用free函数释放了动态分配的内存,以避免内存泄漏。

性能优化方面,我们使用了动态规划来避免重复计算,从而提高了运行效率。相比于原始的递归实现,优化后的版本在处理大规模问题时更加高效。

分治思想的基本原理

场景引发思考

假设你需要在一个包含大量数字的数组中找到最大的数字。你会如何解决这个问题呢?

引入分治思想

在解决这个问题的过程中,我们可以引入分治思想。分治法是一种问题解决方法,它将大问题划分为若干个相同或相似的子问题,然后解决子问题,并将子问题的解合并得到原问题的解。

分析分治思想的原理

分治思想的核心原理是将大问题划分为子问题,然后递归地解决子问题,最后将子问题的解合并得到原问题的解。

具体步骤如下:

  1. 分解(Divide):将原问题划分为若干个相同或相似的子问题。
  2. 解决(Conquer):递归地解决每个子问题。如果子问题足够小(可以直接解决),则直接求解。
  3. 合并(Combine):将子问题的解合并得到原问题的解。

如何实现分治算法

分治算法通常通过递归实现。在递归的过程中,将问题划分为子问题,递归地解决子问题,然后将子问题的解合并得到原问题的解。

示例代码如下(使用C语言实现):

#include <stdio.h>

// 分治法求解最大值
int findMax(int arr[], int start, int end) {
    if (start == end) {
        return arr[start];
    } else {
        int mid = (start + end) / 2;
        int leftMax = findMax(arr, start, mid);
        int rightMax = findMax(arr, mid + 1, end);
        return (leftMax > rightMax) ? leftMax : rightMax;
    }
}

int main() {
    int arr[] = {2, 8, 1, 6, 5, 4, 9, 3, 7};
    int n = sizeof(arr) / sizeof(arr[0]);

    int max = findMax(arr, 0, n - 1);
    printf("The maximum number is: %d\n", max);

    return 0;
}

分治与递归的关系与区别

分治和递归的定义和特点

分治和递归都是常见的问题解决方法,它们在一定程度上有相似之处,但也存在一些区别。

分治是一种将问题分解为若干个相同或相似的子问题,递归地解决子问题,并将子问题的解合并得到原问题的解的方法。分治的特点包括:

  • 将问题划分为子问题
  • 子问题的解相互独立
  • 子问题的解可以合并得到原问题的解

递归是一种通过调用自身来解决问题的方法。递归的特点包括:

  • 问题可以通过相同的问题的较小实例的解来表示
  • 递归函数调用自身来解决较小实例
  • 递归调用必须有终止条件,否则会导致无限递归

分治和递归之间的联系和区别

分治和递归之间存在一些联系和区别。

联系:

  • 分治算法通常通过递归来实现,将问题划分为子问题并递归地解决子问题。
  • 递归是分治的一种实现方式,递归函数可以调用自身来解决子问题。

区别:

  • 分治算法将问题划分为子问题,子问题之间相互独立,且子问题的解可以合并得到原问题的解。
  • 递归是通过调用自身来解决较小实例的问题,没有明显的分解和合并过程。
  • 分治算法通常需要明确的分解和合并步骤,而递归算法则更关注问题的分解和终止条件。

代码示例解析

下面我们通过一个代码示例来说明分治和递归的使用。

#include <stdio.h>

// 使用分治法求和
int sum(int arr[], int start, int end) {
    if (start == end) {
        return arr[start];
    } else {
        int mid = (start + end) / 2;
        int leftSum = sum(arr, start, mid);
        int rightSum = sum(arr, mid + 1, end);
        return leftSum + rightSum;
    }
}

// 使用递归法求和
int sumRecursive(int arr[], int start, int end) {
    if (start == end) {
        return arr[start];
    } else {
        return arr[start] + sumRecursive(arr, start + 1, end);
    }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);

    int divideSum = sum(arr, 0, n - 1);
    printf("Sum using divide and conquer: %d\n", divideSum);

    int recursiveSum = sumRecursive(arr, 0, n - 1);
    printf("Sum using recursion: %d\n", recursiveSum);

    return 0;
}

在上述示例代码中,我们使用分治和递归两种方法来求解给定数组的和。通过递归地划分子问题和合并子问题的解,我们可以得到整个数组的和。其中sum()函数使用分治法求和,而sumRecursive()函数使用递归法求和。

动态规划与递归的联系与区别

动态规划的概念和优势

动态规划是一种解决多阶段决策问题的优化方法。它通过将问题分解为多个重叠子问题,并以自底向上的方式解决这些子问题,最终得到原问题的解。动态规划的优势包括:

  • 避免重复计算:动态规划使用表格或数组来保存子问题的解,避免了重复计算,提高了计算效率。
  • 自底向上的求解方式:动态规划通常使用迭代的方式自底向上地求解子问题,而不是通过递归调用。
  • 提供最优解:动态规划可以通过比较子问题的解来得到最优解,适用于求解最优化问题。

动态规划

当使用动态规划来解决斐波那契数列问题时,我们可以使用自底向上的方法,通过解决子问题来构建更大规模的问题的解。

斐波那契数列是一个以递归方式定义的数列,其中每个数字是前两个数字的和。数列的前几个数字通常是0、1或1、1。例如,斐波那契数列的前几个数字是0、1、1、2、3、5、8、13等。

动态规划的思路

动态规划通常涉及将问题分解为较小的子问题,并使用一种记忆化的方法来存储子问题的解,以避免重复计算。对于斐波那契数列问题,我们可以使用动态规划的思路来解决它。

  1. 确定状态:我们可以将斐波那契数列的第n个数字作为状态,记为f(n)。
  2. 定义状态转移方程:根据斐波那契数列的定义,我们知道f(n) = f(n-1) + f(n-2)。
  3. 确定初始条件:斐波那契数列的初始条件是f(0) = 0和f(1) = 1。

代码示例解析

下面我们通过一个代码示例来说明动态规划的实现思路和优化效果。

#include <stdio.h>

// 使用动态规划计算斐波那契数列
int fibonacciDP(int n) {
    int fib[n+1];
    fib[0] = 0;
    fib[1] = 1;

    for (int i = 2; i <= n; i++) {
        fib[i] = fib[i-1] + fib[i-2];
    }

    return fib[n];
}

// 使用递归计算斐波那契数列
int fibonacciRecursive(int n) {
    if (n <= 1) {
        return n;
    } else {
        return fibonacciRecursive(n-1) + fibonacciRecursive(n-2);
    }
}

int main() {
    int n = 6;

    int dpResult = fibonacciDP(n);
    printf("n=%d,recursion=%d\n", n, dpResult);

    int recursiveResult = fibonacciRecursive(n);
    printf("n=%d,recursion=%d\n", n, recursiveResult);

    return 0;
}

在上述示例代码中,我们使用动态规划和递归两种方法来计算斐波那契数列的第n个数。通过动态规划的方式,我们使用迭代的方式自底向上地计算子问题的解并保存在数组中,避免了重复计算。而递归的方式则通过不断调用自身来解决较小实例的问题。

这个示例代码展示了动态规划和递归在求解斐波那契数列问题上的不同实现方式,以及动态规划通过避免重复计算提高了计算效率的优势。

迭代替代递归提高效率

迭代相对于递归具有一些优势,可以提高效率和节省内存。

论证迭代相对于递归的优势:

  • 迭代通常使用循环结构,而不是函数的递归调用,减少了函数调用的开销。
  • 迭代可以使用辅助变量来保存中间结果,避免了递归函数的栈帧开销。
  • 迭代可以更好地利用计算机的缓存,提高了数据访问的效率。
  • 迭代通常更容易理解和调试,代码结构更清晰。

下面是一个具体的代码示例,对比了使用迭代和递归两种方式计算阶乘的效率。

#include <stdio.h>

// 使用迭代计算阶乘
int factorialIterative(int n) {
    int result = 1;
    for (int i = 1; i <= n; i++) 
        result *= i;
       return result;
}

// 使用递归计算阶乘
int factorialRecursive(int n) {
    if (n == 0) {
        return 1;
    } else {
        return n * factorialRecursive(n - 1);
    }
}

int main() {
    int n = 5;
    int dpResult = fibonacciDP(n);
    printf("n=%d,recursion=%d\n", n, dpResult);

    int recursiveResult = fibonacciRecursive(n);
    printf("n=%d,recursion=%d\n", n, recursiveResult);
    return 0;
}

在上述示例代码中,我们使用迭代和递归两种方式来计算阶乘。通过使用迭代的方式,我们避免了递归调用的开销,并使用循环结构直接计算阶乘。与之相比,递归函数调用的开销较大,递归深度增加时容易导致栈溢出。

这个示例代码展示了迭代相对于递归的优势,通过迭代的方式可以提高效率和节省内存。

博主码字不易,要是能帮助到大家麻烦给个免费的三连 支持一下 感谢你的观看 下期再见!

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

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

相关文章

嵌入式系统:挑战与机遇并存的领域

嵌入式系统&#xff1a;挑战与机遇并存的领域嵌入式系统是一个既具有挑战性又充满前景的领域。要成为一名合格的嵌入式系统工程师&#xff0c;需要经过大量的学习和实践。然而&#xff0c;进入这个领域时&#xff0c;刚入行可能会面临许多困境。让我们一起探讨一下嵌入式系统工…

CPU和GPU有什么区别,玩游戏哪个更重要?

大家好&#xff01;今天我们要聊的话题是CPU和GPU&#xff0c;它们在电脑中扮演着重要的角色&#xff0c;虽然看起来只是两个简单的缩写&#xff0c;但它们的功能和影响是截然不同的&#xff01; 那么&#xff0c;究竟CPU和GPU有什么区别呢&#xff1f;在玩游戏时&#xff0c;…

JS高级(四)- 深浅拷贝、异常处理、处理this、防抖节流md

文章目录 1.深浅拷贝1.1浅拷贝1.2深拷贝1.2.1递归实现深拷贝1.2.2 js库lodash里面cloneDeep内部实现了深拷贝1.2.3 JSON序列化 2.异常处理2.1 throw2.2 try ... catch2.3 debugger 3.处理this(this小结)3.1普通函数3.2箭头函数3.3改变this指向3.3.1 call3.3.2 apply3.3.3 bind3…

vtk三维场景基本要素 灯光、相机、颜色、纹理映射 简介

整理一下VTK 三维场景基本要素&#xff0c;后面会一一进行整理&#xff1b; 1. 灯光 vtkLight 剧场里有各式各样的灯光&#xff0c;三维渲染场景中也一样&#xff0c;可以有多个灯光存在。灯光和相机 是三维渲染场景必备的要素&#xff0c;vtkRenderer会自动创建默认的灯光和…

3d渲染100农场如何使用?渲染100邀请码1a12

3d渲染农场通常用于电影、动画或视觉效果的渲染&#xff0c;本文以广受好评的渲染100农场为例&#xff0c;来讲解它的使用方法。 1、注册账号 前往渲染100官网(http://www.xuanran100.com/?ycode1a12)注册账号&#xff0c; 新用户注册记得填邀请码1a12&#xff0c;有30元大礼…

93 log4j-slf4j-impl 搭配上 log4j-to-slf4j 导致的 StackOverflow

前言 呵呵 最近想要 做一个 mongo 低版本的客户端读取高版本的服务端传递过来的数据造成的一个错误的时候, 出现了这样的问题 引入了 mongo-java-driver 之后, 使用相关 api 的时候会触发 com.mongo.internal.connection.BaseCluser 的初始化, 其依赖的 Loggers 间接的依赖…

JVM-类加载器 双亲委派机制

申明&#xff1a;文章内容是本人学习极客时间课程所写&#xff0c;文字和图片基本来源于课程资料&#xff0c;在某些地方会插入一点自己的理解&#xff0c;未用于商业用途&#xff0c;侵删。 什么是JVM JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&a…

centos安装harbor

安装docker yum install epel-release yum-utils#docker官网源 yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repoyum install docker-ce -y 安装docker-compose curl -SL https://github.com/docker/compose/releases/download/v2…

springBoot,springSecurity返回乱码

框架&#xff1a;SpringBoot3 问题&#xff1a;响应内容乱码 问题代码&#xff1a; // 成功登录响应的内容Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication…

C++笔记之regex(正则表达式)

C++笔记之regex(正则表达式) ——2024-02-10 ——《C++标准库》(第2版,侯捷译) Page 717 code review! 文章目录 C++笔记之regex(正则表达式)例1:使用正则表达式进行搜索(`std::regex_search`)例2:使用正则表达式进行全文匹配(`std::regex_match`)例3:使用正则表达式…

【大厂AI课学习笔记】1.5 AI技术领域(1)计算机视觉

人工智能的三大基础应用领域是&#xff0c;自然语言处理&#xff0c;语音识别&#xff0c;计算机视觉。 计算机视觉&#xff1a;定义、关键技术、技术发展、应用场景与商业化成功 一、计算机视觉的定义 计算机视觉&#xff0c;作为一个跨学科的领域&#xff0c;旨在研究如何让…

学习Android的第十天

目录 Android CheckBox 复选框 获得选中的 CheckBox 的值 自定义点击效果 改变文字与选择框的相对位置 修改文字与选择框的距离 Android ToggleButton 开关按钮 改变 ToggleButton 的状态和文本 Android Switch 开关 改变 Switch 的状态和文本 Android CheckBox 复选框…

IDEA中Git的使用小技巧-Toolbar(工具栏)的设置

目录 1 前言 2 步骤 2.1 打开设置 2.2 找到Menus and Toolbars 2.3 Menus and Toolbars界面的介绍 2.4 选择工具 2.5 查看 1 前言 工具栏的合理运用&#xff0c;能够极大程度上为我们省时省力 &#xff0c;接下来我将以Git工具的添加&#xff0c;介绍如何定制我们IDEA…

【新书推荐】7.3 for语句

本节必须掌握的知识点&#xff1a; 示例二十四 代码分析 汇编解析 for循环嵌套语句 示例二十五 7.3.1 示例二十四 ■for语句语法形式&#xff1a; for(表达式1;表达式2;表达式3) { 语句块; } ●语法解析&#xff1a; 第一步&#xff1a;执行表达式1&#xff0c;表达式1…

【Linux】学习-基础IO—上

Linux基础IO—上 复习c语言接口 你真的懂文件吗&#xff1f; 文件的打开与关闭 深入了解文件读与写(C语言级别) 系统文件I/O 我们知道&#xff0c;文件是放在磁盘(硬件)上的&#xff0c;我们用代码访问文件的思路是&#xff1a; 写代码 -> 编译 -> 生成可执行exe …

uniapp小程序端使用计算属性动态绑定style样式踩坑

踩坑点: 使用uniapp编译小程序端动态绑定复杂style使用计算属性方式&#xff0c;return必须返回json字符串格式&#xff0c;不能返回object&#xff0c;否则会不起作用。 代码总览 视图层 逻辑层&#xff08;注意这里是使用的计算属性哈&#xff09; 这里我封装成了一个个性化…

泽攸科技ZEM系列台扫助力环境科研创新:可见光催化抗生素降解的探索

环境污染和能源短缺是当今人类社会面临的最严重威胁之一。为了克服这些问题&#xff0c;特别是在污水处理过程中&#xff0c;寻找新的技术来实现清洁、高效、经济的发展显得尤为重要。在各种工业废水中&#xff0c;抗生素的过量排放引起了广泛关注。抗生素的残留会污染土壤、水…

学会这几个Dynamo数据处理技巧,效率翻倍提升

最近一直在写Dynamo程序&#xff0c;但是很多东西是不能分享出来的&#xff0c;但是一些方法是可以分享的&#xff0c;整理了一些&#xff0c;今天先分享几个给大家。话不多说&#xff0c;直接进入主题&#xff1a; 1、快速筛选出一组物体中&#xff0c;有哪些物体与另一组物体…

【Maven】依赖、构建管理 继承与聚合 快速学习(3.6.3 )

文章目录 Maven是什么&#xff1f;一、Maven安装和配置本地配置文件设置idea配置本地maven 二、基于IDEA的Maven工程创建2.1 Maven工程GAVP属性2.2 Idea构建Maven JavaEE工程 三、Maven工程项目结构说明四、Maven核心功能依赖和构建管理4.1 依赖管理和配置4.2 依赖传递和冲突4.…

C# OCR识别图片中的文字

1、从NuGet里面安装Spire.OCR 2、安装之后&#xff0c;找到安装路径下&#xff0c;默认生成的packages文件夹&#xff0c;复制该文件夹路径下的 6 个dll文件到程序的根目录 3、调用读取方法 OcrScanner scanner new OcrScanner(); string path "C:\1.png"; scann…