Java中的经典排序算法:快速排序、归并排序和计数排序详解(如果想知道Java中有关快速排序、归并排序和计数排序的知识点,那么只看这一篇就足够了!)

news2024/11/15 11:24:34

        前言:排序算法在计算机科学中占有重要地位,不同的算法适用于不同的场景。本文将深入探讨快速排序、归并排序和计数排序。


✨✨✨这里是秋刀鱼不做梦的BLOG

✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客

先让我们看一下本文大致的讲解内容:

        对于每个排序算法,我们都会从算法简介、其原理与步骤、代码实现、时间复杂度分析、空间复杂度分析与该排序算法的应用场景这几个方面来进行讲解。

目录

1.快速排序 (Quicksort)

        (1)算法简介

        (2)算法的原理与步骤

        (3)Java代码实现

        【1】Hoare法

        【2】挖坑法

        【3】前后指针法

        (4)时间复杂度和空间复杂度

        (5)算法的应用场景

2.归并排序 (Merge Sort)

        (1)算法简介

        (2)算法的原理与步骤

        (3)Java代码实现

        (4)时间复杂度和空间复杂度

        (5)算法的应用场景

3.计数排序 (Counting Sort)

        (1)算法简介

        (2)算法的原理与步骤

        (3)Java代码实现

        (4)时间复杂度和空间复杂度

        (5)算法的应用场景


1.快速排序 (Quicksort)

        (1)算法简介

        快速排序是一种高效的排序算法,由C.A.R. Hoare在1960年提出。它采用分治法(Divide and Conquer),通过递归地将未排序的部分分割为较小的子数组进行排序,再将其合并。快速排序的平均时间复杂度为 O(nlog⁡n),在大多数情况下比其他 O(nlog⁡n) 的算法,如归并排序,具有更好的性能。

        当然,我相信读者读完快速排序的简介之后,对于快速排序算法的认识还是没什么认识的,接下来让我们直接带着你边学如何实现排序算法边理解该算法的内核。

        (2)算法的原理与步骤

        快速排序的核心思想是选择一个“基准”(pivot),并通过一系列的比较和交换操作将数组分成两部分:一部分所有元素小于基准,另一部分所有元素大于基准。然后,对这两部分分别递归地应用快速排序。具体步骤如下:

  1. 选择基准: 从数组中选择一个元素作为基准。选择基准的方法有多种,如选择第一个元素、最后一个元素、随机选择或三数取中法。

  2. 分区 (Partitioning): 通过遍历数组,将所有小于基准的元素放在基准的左边,所有大于基准的元素放在右边。

  3. 递归排序: 对基准左边和右边的子数组递归地进行快速排序。

  4. 组合: 由于分区已经确保了基准左边的元素小于基准,右边的元素大于基准,因此当递归完成后,数组已经是有序的。

        ——看完了上述大体如何实现快速排序算法之后,让我们从代码的层面来实现一下快速排序算法。

        (3)Java代码实现

以下为Java中实现快速排序的大致代码:

public void quickSort(int[] array) {
    int end = array.length - 1;
    quickSort(array, 0, end);
}

private void quickSortHo(int[] array, int left, int right) {
    // 如果子数组长度为1或更小,则返回(即递归终止条件)
    if (left >= right) {
        return;
    }

    // 查找基准元素的位置,并将数组分成两部分
    int target = findTarget(array, left, right);
    
    // 对基准元素左边的子数组进行递归排序
    quickSort(array, left, target - 1);
    
    // 对基准元素右边的子数组进行递归排序
    quickSort(array, target + 1, right);
}

        从上述代码中我们可以看到我们在寻找基准元素位置的时候,使用了findTarget()方法,那么这个方法该如何实现呢?

        实现该方法的方式大致有三种,分别是:Hoare法、挖坑法和前后指针法。接下来我们一一进行讲解。

        【1】Hoare法

public int findTargetH(int[] array, int left, int right) {
    // 获取中间索引并将中间元素交换到数组的最左端
    int mid = middleIndex(array, left, right);
    swap(array, left, mid);
    
    // 将最左端的元素作为基准元素
    int temp = array[left];
    int keyi = left; // 保存基准元素的初始位置
    
    // 开始从数组的两端向中间扫描
    while (left < right) {
        // 从右向左扫描,找到第一个小于基准的元素
        while (left < right && array[right] >= temp) {
            right--;
        }
        // 从左向右扫描,找到第一个大于基准的元素
        while (left < right && array[left] <= temp) {
            left++;
        }
        // 交换左侧找到的大于基准的元素和右侧找到的小于基准的元素
        swap(array, left, right);
    }
    
    // 将基准元素放置到最终的位置,即左、右指针相遇的位置
    swap(array, keyi, left);
    
    // 返回基准元素的位置索引
    return left;
}

解释说明:

  • middleIndex(array, left, right):假设这是一个用于计算数组中间索引的方法,以获取中间元素的位置。

  • swap(array, left, mid):将中间元素和最左端元素交换,使得基准元素(最左端元素)在处理前放到适当的位置。

  • temp:基准元素,用于比较其他元素。

  • keyi:保存基准元素的初始索引位置,以便最终将基准元素放到正确的位置。

  • while (left < right):循环扫描数组,直到左右指针相遇。

  • swap(array, left, right):当找到左侧大于基准的元素和右侧小于基准的元素时,交换它们的位置。

  • 最后一次swap:将基准元素放回到排序后应在的位置上,并返回该位置的索引。

        ——这就是Hoare实现查找基准元素位置。

        【2】挖坑法

public int findTargetW(int[] array, int left, int right) {
    // 将最左端的元素作为基准元素
    int temp = array[left];
    
    // 开始从数组的两端向中间扫描
    while (left < right) {
        // 从右向左扫描,找到第一个小于基准的元素
        while (left < right && array[right] >= temp) {
            right--;
        }
        // 将小于基准的元素移到左侧
        array[left] = array[right];
        
        // 从左向右扫描,找到第一个大于基准的元素
        while (left < right && array[left] <= temp) {
            left++;
        }
        // 将大于基准的元素移到右侧
        array[right] = array[left];
    }
    
    // 将基准元素放置到最终的位置,即左、右指针相遇的位置
    array[left] = temp;
    
    // 返回基准元素的位置索引
    return left;
}

解释说明:

  • temp:基准元素,取自数组的最左端,用于比较和调整其他元素的位置。

  • while (left < right):主循环,通过左右指针的移动将数组分为小于基准和大于基准的两部分,直到左右指针相遇。

  • array[left] = array[right]:将右侧扫描中找到的小于基准的元素移动到左侧。

  • array[right] = array[left]:将左侧扫描中找到的大于基准的元素移动到右侧。

  • 最后一步:将基准元素放置在最终的正确位置,并返回该位置的索引,以供进一步的递归使用。

        ——这就是挖坑法实现查找基准元素位置。

        【3】前后指针法

public int findTargetQ(int[] array, int left, int right) {
    // 当前基准元素的位置(初始为左边界)
    int cur = left;
    
    // 从基准元素的下一个位置开始遍历
    int prev = left + 1;
    
    // 保存基准元素的值
    int temp = array[left];
    
    // 遍历数组,直到右边界
    while (prev <= right) {
        // 如果当前元素小于基准元素且 cur 与 prev 不相等,则交换这两个元素
        if (array[prev] < temp && ++cur != prev) {
            swap(array, cur, prev);
        }
        // 移动到下一个元素
        prev++;
    }
    
    // 将基准元素放置到最终的位置,即 cur 的位置
    swap(array, left, cur);
    
    // 返回基准元素的位置索引
    return cur;
}

解释说明:

  • cur:表示当前已经确定位置的元素的索引,初始值为左边界,负责标记小于基准元素的部分的末尾。

  • prev:用于遍历数组的索引,从基准元素的下一个位置开始。

  • temp:基准元素的值,用于与其他元素进行比较。

  • while (prev <= right):遍历数组中的元素,寻找小于基准元素的值,并将其与当前元素进行交换。

  • if (array[prev] < temp && ++cur != prev):如果当前元素小于基准元素,并且 curprev 不相等(确保不进行自我交换),则交换这两个元素。

  • swap(array, cur, left):将基准元素放置到最终的位置,即所有小于基准元素的元素的末尾。

  • return cur:返回基准元素的位置索引,用于进一步的排序。

        ——这就是前后指针法实现查找基准元素位置。

通过上述的学习,我们就了解了如何使用Java代码来实现快速排序算法。

        (4)时间复杂度和空间复杂度

  • 时间复杂度

    • 平均时间复杂度: O(nlog⁡n)。快速排序在分区步骤中,每次都将数组分成两个大致相等的部分,因此递归的深度为 O(log⁡n),每层递归处理的元素数为 O(n)。

    • 最坏时间复杂度: O(n2)。当每次分区产生的子数组大小极度不均匀(如数组已经有序或逆序)时,递归深度变为 O(n)。

  • 空间复杂度: O(log⁡n)(主要为递归调用栈的空间)。由于每次递归都会消耗栈空间,因此快速排序的空间复杂度与递归的深度相关。

        (5)算法的应用场景

快速排序适用于大部分需要排序的场景,尤其是:

  • 大数据集: 快速排序的平均性能优于其他排序算法,适合处理大规模数据集。

  • 内存空间有限的情况: 相较于归并排序,快速排序的空间复杂度更低,更适合内存资源有限的场景。

  • 不需要稳定排序的场景: 快速排序是一个不稳定的排序算法,不适用于需要保持相同元素相对顺序的场景。

        这样我们就学习完了快速排序算法了!!!

2.归并排序 (Merge Sort)

        (1)算法简介

        归并排序是一种稳定的排序算法,采用分治策略,将待排序的数组分成若干子数组,分别对每个子数组进行排序,再将这些子数组合并成一个有序数组。归并排序的时间复杂度为 O(nlog⁡n),在数据量较大且对排序稳定性要求较高的场景中有较好的表现。

同样,我们接下来带着你边学如何实现排序算法边理解该算法的内核。

        (2)算法的原理与步骤

        归并排序的基本思想是将数组分成尽可能小的子数组(每个子数组只有一个元素),然后逐步合并这些子数组,使得合并后的数组有序。具体步骤如下:

  1. 分割: 将数组分成两部分,递归地对每一部分进行归并排序。

  2. 排序并合并: 当每个子数组的长度为1时,开始合并相邻的子数组。在合并时,使用双指针技术,比较两个子数组的元素,将较小的元素放入临时数组中。

  3. 递归处理: 对左右子数组分别递归应用归并排序,直至最终将所有元素合并为一个有序数组。

        

        ——看完了上述大体如何实现归并排序算法之后,让我们从代码的层面来实现一下快速排序算法。

        (3)Java代码实现

以下为Java中实现归并排序的大致代码:

public void mergeSort(int[] array) {
    // 调用归并排序的递归方法,排序整个数组
    mergeInsertSort(array, 0, array.length - 1);
}

public void mergeInsertSort(int[] array, int left, int right) {
    // 如果子数组只有一个元素或为空,则返回(递归终止条件)
    if (left >= right) {
        return;
    }

    // 计算中间位置,将数组分成两部分
    int mid = (left + right) / 2;

    // 对左半部分进行递归排序
    mergeInsertSort(array, left, mid);

    // 对右半部分进行递归排序
    mergeInsertSort(array, mid + 1, right);

    // 合并两个已排序的子数组
    merge(array, left, mid, right);
}

public void merge(int[] array, int left, int mid, int right) {
    // 右半部分的起始位置
    int rightBegin = mid + 1;

    // 左半部分的起始位置
    int leftBegin = left;

    // 用于存放合并结果的临时数组
    int i = 0;
    int[] ret = new int[right - left + 1];

    // 合并两个已排序的子数组
    while (left <= mid && rightBegin <= right) {
        // 比较左右两部分的元素,将较小的元素放入临时数组
        if (array[left] < array[rightBegin]) {
            ret[i++] = array[left++];
        } else {
            ret[i++] = array[rightBegin++];
        }
    }

    // 将左半部分剩余的元素添加到临时数组中
    while (left <= mid) {
        ret[i++] = array[left++];
    }

    // 将右半部分剩余的元素添加到临时数组中
    while (rightBegin <= right) {
        ret[i++] = array[rightBegin++];
    }

    // 将临时数组中的元素复制回原数组的相应位置
    for (int j = 0; j < ret.length; j++) {
        array[j + leftBegin] = ret[j];
    }
}

解释:

  • mergeSort(int[] array):这是归并排序的入口方法,它调用 mergeInsertSort 方法对整个数组进行排序。

  • mergeInsertSort(int[] array, int left, int right):这是归并排序的递归方法,递归地将数组分成更小的部分并排序,然后调用 merge 方法合并已排序的子数组。

  • merge(int[] array, int left, int mid, int right):这是合并两个已排序的子数组的方法。它创建一个临时数组 ret,将左右两部分按顺序合并到 ret 中,然后将合并后的结果复制回原数组。

        ——这样我们就了解了如何使用Java代码来实现归并排序算法。

        (4)时间复杂度和空间复杂度

  • 时间复杂度: O(nlog⁡n)。每次分割将数组对半分,深度为 O(log⁡n),合并过程需要遍历整个数组,因此时间复杂度为 O(nlog⁡n)。

  • 空间复杂度: O(n)。归并排序需要额外的空间来存储临时数组,用于合并过程中临时存放子数组的元素。

        

        (5)算法的应用场景

归并排序的稳定性和时间复杂度使其适用于以下场景:

  • 稳定性要求高的排序: 归并排序是一种稳定排序算法,适用于对相同值的元素相对顺序有要求的场景。

  • 外部排序: 归并排序适用于处理超大数据集的外部排序,由于其稳定性和性能,尤其适用于磁盘文件的排序操作。

  • 数据集较大且未全部加载到内存: 在处理大规模数据时,归并排序由于其分割和合并的特性,可以有效地处理不能一次性加载到内存的数据。

        ——这样我们学习完了如何在Java中实现归并算法。

3.计数排序 (Counting Sort)

        (1)算法简介

        计数排序是一种非比较排序算法,主要用于对整数进行排序。它通过计算每个元素在数组中出现的次数来确定其在排序后数组中的位置。这种排序算法适用于元素范围较小且数据量较大的场景。

同样,我们接下来带着你边学如何实现排序算法边理解该算法的内核。

        (2)算法的原理与步骤

        计数排序的基本思想是创建一个计数数组,通过统计原始数组中每个元素的出现次数来确定它们在排序后数组中的正确位置。具体步骤如下:

  1. 计算最大值和最小值: 确定数组中的最大值和最小值,进而决定计数数组的大小。

  2. 计数: 创建一个计数数组,将每个元素出现的次数记录在计数数组中。

  3. 累加计数: 对计数数组中的值进行累加,以便确定每个元素的最终位置。

  4. 构建排序数组: 遍历原始数组,通过计数数组确定每个元素在排序后数组中的位置,构建最终的有序数组。

        ——接下来让我们使用代码来实现一下计数排序。

        (3)Java代码实现

public void countSort(int[] array) {
    // 初始化最小值和最大值为数组的第一个元素
    int min = array[0];
    int max = array[0];
    
    // 遍历数组,找到最小值和最大值
    for (int i = 0; i < array.length; i++) {
        if (array[i] < min) {
            min = array[i];
        }
        if (array[i] > max) {
            max = array[i];
        }
    }
    
    // 创建计数数组,用于统计每个元素出现的次数
    int[] count = new int[max - min + 1];
    
    // 统计数组中每个元素出现的次数
    for (int i = 0; i < array.length; i++) {
        count[array[i] - min]++;
    }
    
    // 将排序后的元素放回原数组
    int arrayIndex = 0;
    for (int i = 0; i < count.length; i++) {
        // 对计数数组进行处理,将每个元素根据其计数放入原数组中
        while (count[i] != 0) {
            array[arrayIndex++] = i + min;
            count[i]--;
        }
    }
}

解释:

  • int min = array[0]; int max = array[0];:初始化最小值和最大值为数组的第一个元素。

  • for (int i = 0; i < array.length; i++):遍历数组,找到最小值和最大值。

  • int[] count = new int[max - min + 1];:创建计数数组 count,其长度为 max - min + 1,用来存储每个值的出现次数。

  • for (int i = 0; i < array.length; i++):遍历数组并填充计数数组。

  • count[array[i] - min]++:更新计数数组中的值,表示 array[i] 出现的次数。

  • for (int i = 0; i < count.length; i++):遍历计数数组,并将排序后的元素放回原数组中。

  • while (count[i] != 0):根据计数数组的值将元素放入原数组中,每个元素按照计数的次数放入对应的位置。

        ——这样我们就实现了计数排序算法了!!!

        (4)时间复杂度和空间复杂度

  • 时间复杂度: O(n+k)O(n + k)O(n+k),其中 nnn 是数组的长度,kkk 是数组中元素的范围(最大值与最小值之间的差值)。

  • 空间复杂度: O(k)O(k)O(k)。计数排序需要额外的计数数组,空间复杂度与元素的范围成正比。

        (5)算法的应用场景

计数排序的特点使其适用于以下场景:

  • 数据范围较小的整数排序: 计数排序适合整数范围较小的排序任务,如考试成绩、年龄等。

  • 需要稳定排序的场景: 计数排序是一种稳定的排序算法,适用于需要保持相同元素相对顺序的场景。

  • 数据分布相对均匀: 如果数据分布极度不均匀,计数排序的效率会大大降低,因此适用于数据分布较为均匀的情况。

        ——这样我们学习完了如何在Java中实现计数排序算法。


以上就是本篇文章的全部内容了~~~

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

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

相关文章

新生在线分班查询,用这个小程序制作仅需一分钟!

今天许多学校已陆续开学&#xff0c;老师们又开始忙碌起来。他们需要将新生的分班信息逐一通知给每位家长&#xff0c;这不仅是一项繁琐的工作&#xff0c;而且效率也不高。传统的方法是通过电话、短信或邮件一一通知&#xff0c;这不仅耗时耗力&#xff0c;还容易出现信息传递…

百度文库文章-暂存下-------题 目: 链式简单选择排序

题 目: 链式简单选择排序 初始条件&#xff1a; 理论&#xff1a;学习了《数据结构》课程&#xff0c;掌握了基本的数据结构和常用的算法&#xff1b; 实践&#xff1a;计算机技术系实验室提供计算机及软件开发环境。 要求完成的主要任务: &#xff08;包括课程设计工作量…

如何用pytorch进行图像分类

如何用pytorch进行图像分类 使用PyTorch进行图像分类是深度学习中的一个常见任务&#xff0c;涉及一系列步骤&#xff0c;从数据预处理到模型训练和评估。下面将详细描述每个步骤&#xff0c;从零开始构建一个图像分类器。 1. 安装必要的库 在开始之前&#xff0c;首先需要确…

驱动(RK3588S)第四课时:模块化编程

目录 一、什么是模块化编程二、怎么把自己编译代码给加载到开发板上运行三、驱动编程的框架四、驱动编程具体实例1、编写单模块化驱动代码2、编写多模块化驱动代码3、编写向模块传参驱动代码4、编写多模块化驱动代码另一种方式 一、什么是模块化编程 在嵌入式里所谓的模块化编…

Vue——day07之条件渲染、列表渲染以及监测数据

目录 1.template标签 2.条件渲染 3.列表渲染 4.v-for中的key的作用以及原理 5.列表过滤 placeholder 前端空字符串 使用数据监视watch实现 使用计算属性实现 6.列表排序 7.Vue更新数据检测失败 原因 总结 1.template标签 template标签是Vue.js中的一个特殊元素&am…

kube-scheduler调度策略之预选策略(三)

一、概述 摘要&#xff1a;本文我们继续分析源码&#xff0c;并聚焦在预选策略的调度过程的执行。 二、正文 说明&#xff1a;基于 kubernetes v1.12.0 源码分析 上文我们说的(g *genericScheduler) Schedule()函数调用了findNodesThatFit()执行预选策略。 2.1 findNodesTha…

Truncated incorrect max_connections value: ‘999999‘

MySQL 的最大连接数&#xff08;max_connections&#xff09;可以设置的上限值在不同的资料中有所不同。以下是一些关键信息&#xff1a; 默认值和默认范围&#xff1a; MySQL 的默认最大连接数通常为 100 。一些资料提到默认值为 151 。 最大允许值&#xff1a; MySQL 的最大…

ant-design-vue:a-table表格中插入自定义按钮

本文将介绍如何使用ant-design-vue在a-table表格中加入自定义按钮和图标的代码。 结果如下图所示&#xff0c; 一、简单示例 <template><a-table:columns"columns":data-source"data":row-selection"rowSelection":ellipsis"tru…

对称密码学

1. 使用OpenSSL 命令行 在 Ubuntu Linux Distribution (发行版&#xff09;中&#xff0c; OpenSSL 通常可用。当然&#xff0c;如果不可用的话&#xff0c;也可以使用下以下命令安装 OpenSSL: $ sudo apt-get install openssl 安装完后可以使用以下命令检查 OpenSSL 版本&am…

深度学习基础案例4--构建CNN卷积神经网络实现对猴痘病的识别(测试集准确率86.5%)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 下一周会很忙&#xff0c;更新可能不及时&#xff0c;请大家见谅这个项目我感觉是一个很好的入门案例&#xff0c;但是自己测试的时候测试集准确率只比较…

mcu loader升级固件原理与实现

1 mcu loader升级固件原理 mcu 固件有两部分&#xff0c;如下图所示&#xff0c;一部分是 loader.bin&#xff0c;一部分是 app.bin&#xff0c;将两部分的固件合并在一起烧录进 mcu 的 flash 当中。mcu 上电进入loader 模式执行 loader.bin 部分的程序&#xff0c;然后读取 fl…

前端踩坑记录:javaScript复制对象和数组,不能简单地使用赋值运算

问题 如图&#xff0c;编辑table中某行的信息&#xff0c;发现在编辑框中修改名称的时候&#xff0c;表格中的信息同步更新。。。 检查原因 编辑页面打开时&#xff0c;需要读取选中行的信息&#xff0c;并在页面中回显。代码中直接将当前行的数据对象赋值给编辑框中的表单对…

51单片机——I2C总线

1、I2C总线简介 I2C总线&#xff08;Inter IC BUS&#xff09;是由Philips公司开发的一种通用数据总线 两根通信线&#xff1a;SCL&#xff08;Serial Clock&#xff09;、SDA&#xff08;Serial Data&#xff09; 同步、半双工&#xff0c;带数据应答 通用的I2C总线&#…

Linux基础(包括centos7安装、linux基础命令、vi编辑器)

一、安装CentOS7 需要&#xff1a;1、VMware Workstation&#xff1b;2、CentOS7镜像 1、安装镜像 2、虚拟机配置 开启虚拟机&#xff0c;鼠标从vm中移出来用快捷键ctrlalt 点击开始安装&#xff0c;设置密码&#xff0c;等待安装完成,&#xff0c;重启。 3、注意事项 如果没…

通往RAG之路(二):版面结构检测方法介绍

一、基于yolov5的版面结构检测 AG系统搭建过程中&#xff0c;版面分析是不可缺少的一个步骤&#xff0c;本文介绍用yolov5进行版面结构信息识别&#xff0c;后续再搭配表格识别、公式识别、文字识别等模块进行版面还原&#xff0c;完成PDF结构化输出。 1.1、环境搭建 conda c…

解决方案:在autodl环境下为什么已安装torch打印出来版本号对应不上

文章目录 一、现象二、解决方案 一、现象 平台&#xff1a;autodl 镜像&#xff1a;PyTorch 2.0.0 Python 3.8(ubuntu20.04) Cuda 11.8 GPU&#xff1a;A40(48GB) * 1 CPU&#xff1a;15 vCPU AMD EPYC 7543 32-Core Processor 内存&#xff1a;80GB 安装torch:1.13.0环境&a…

深入理解指针(6)

目录&#xff1a; 1.字符指针变量 2.数组指针变量 3.二维数组传参本质 4.函数指针变量 5.函数指针的应用 1.字符指针变量 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() {char a w;char* p &a;printf("%p ", p);} 当我们想取出…

UE 【材质编辑】自定义材质节点

使用UE的材质编辑器&#xff0c;蓝图提供了大量的节点函数&#xff1a; 实际上&#xff0c;这是一段封装好的包含一串HLSL代码的容器。打开“Source/Runtime/Engine/Classes/Material”&#xff0c;可以看到很多不同节点的头文件&#xff1a; 照葫芦画瓢 以UMaterialExpressi…

ORM 编程思想

一、ORM简介 对象关系映射&#xff08;英语&#xff1a;Object Relational Mapping&#xff0c;简称ORM&#xff0c;或 O/R mapping&#xff09;是一种为了解决面向对象语言与关系数据库存在的 互不匹配的现象。 二、实体类 实体类就是一个定义了属性&#xff0c;拥有getter、…

51单片机——存储器

1、存储器简介 RAM优点存储速度非常快&#xff0c;缺点成本高&#xff0c;掉电丢失数据。 ROM优点掉电不丢失数据&#xff0c;缺点存储速度比较慢。 所以在实际应用中&#xff0c;我们都是采用两者结合的方式。程序运行时&#xff0c;数据存储在RAM中&#xff0c;需…