数据结构与算法(八):排序算法

参考引用

  • Hello 算法
  • Github:hello-algo

1. 选择排序

  • 选择排序的工作原理非常直接:开启一个循环,每轮从未排序区间选择最小的元素,将其放到已排序区间的末尾,设数组的长度为 n
    • 初始状态下,所有元素未排序,即未排序(索引)区间为 [0, n-1]
    • 选取区间 [0, n-1] 中的最小元素,将其与索引 0 处元素交换。完成后,数组前 1 个元素已排序
    • 选取区间 [1, n-1] 中的最小元素,将其与索引 1 处元素交换。完成后,数组前 2 个元素已排序
    • 以此类推。经过 n-1 轮选择与交换后,数组前 n-1 个元素已排序
    • 仅剩的一个元素必定是最大元素,无须排序,因此数组排序完成
/* 选择排序 */
// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
void selectionSort(vector<int> &nums) {int n = nums.size();// 外循环:未排序区间为 [i, n-1]for (int i = 0; i < n - 1; i++) {// 内循环:找到未排序区间内的最小元素int k = i;for (int j = i + 1; j < n; j++) {if (nums[j] < nums[k])k = j; // 记录最小元素的索引}// 将该最小元素与未排序区间的首个元素交换swap(nums[i], nums[k]);}
}

2. 冒泡排序

  • 冒泡过程可以利用元素交换操作来模拟:从数组最左端开始向右遍历,依次比较相邻元素大小,如果 “左元素 > 右元素” 就交换它俩。遍历完成后,最大的元素会被移动到数组的最右端

算法流程

  • 设数组的长度为 n,冒泡排序的步骤如下图所示
    • 首先,对 n 个元素执行 “冒泡”,将数组的最大元素交换至正确位置
    • 接下来,对剩余 n-1 个元素执行 “冒泡”,将第二大元素交换至正确位置
    • 以此类推,经过 n-1 轮 “冒泡” 后,前 n-1 大的元素都被交换至正确位置
    • 仅剩的一个元素必定是最小元素,无须排序,因此数组排序完成

在这里插入图片描述

/* 冒泡排序(标志优化)*/
// 时间复杂度:O(n^2),引入 flag 优化后,最佳时间复杂度可达到 O(n)
// 空间复杂度:O(1)
void bubbleSortWithFlag(vector<int> &nums) {// 外循环:未排序区间为 [0, i],控制冒泡排序的轮数for (int i = nums.size() - 1; i > 0; i--) {bool flag = false; // 初始化标志位,用于标志当前轮次是否有元素交换的标志位// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端for (int j = 0; j < i; j++) {if (nums[j] > nums[j + 1]) {// 交换 nums[j] 与 nums[j + 1]// 这里使用了 std::swap() 函数swap(nums[j], nums[j + 1]);flag = true; // 记录交换元素}}if (!flag)break; // 此轮冒泡未交换任何元素,即数组已经是有序的,直接跳出}
}

3. 插入排序

  • 插入排序的工作原理与手动整理一副牌的过程非常相似。具体来说,在未排序区间选择一个基准元素,将该元素与其左侧已排序区间的元素逐一比较大小,并将该元素插入到正确的位置

  • 下图展示了数组插入元素的操作流程。设基准元素为 base ,需要将从目标索引到 base 之间的所有元素向右移动一位,然后再将 base 赋值给目标索引

在这里插入图片描述

3.1 算法流程

  • 初始状态下,数组的第 1 个元素已完成排序
  • 选取数组的第 2 个元素作为 base,将其插入到正确位置后,数组的前 2 个元素已排序
  • 选取第 3 个元素作为 base,将其插入到正确位置后,数组的前 3 个元素已排序
  • 以此类推,在最后一轮中,选取最后一个元素作为 base ,将其插入到正确位置后,所有元素均已排序

在这里插入图片描述

/* 插入排序 */
// 时间复杂度:O(n^2),当输入数组完全有序时为 O(n)
// 空间复杂度:O(1)
void insertionSort(vector<int> &nums) {// 外循环:已排序元素数量为 1, 2, ..., nfor (int i = 1; i < nums.size(); i++) {int base = nums[i], j = i - 1;// 内循环:将 base 插入到已排序部分的正确位置while (j >= 0 && nums[j] > base) {nums[j + 1] = nums[j]; // 将 nums[j] 向右移动一位j--;}nums[j + 1] = base; // 将 base 赋值到正确位置}
}

3.2 插入排序优势

  • 插入排序的时间复杂度为 O(n^2),而快速排序的时间复杂度为 O(nlog n)

    • 尽管插入排序的时间复杂度相比快速排序更高,但在数据量较小的情况下,n^2 和 nlog n 数值接近,插入排序通常更快
  • 实际情况中,插入排序的使用频率显著高于冒泡排序和选择排序

    • 冒泡排序基于元素交换实现,需要借助一个临时变量,共涉及 3 个单元操作;插入排序基于元素赋值实现,仅需 1 个单元操作。因此,冒泡排序的计算开销通常比插入排序更高
    • 选择排序在任何情况下的时间复杂度都为 O(n^2)。如果给定一组部分有序的数据,插入排序通常比选择排序效率更高
    • 选择排序不稳定,无法应用于多级排序

4. 快速排序

  • 快速排序是一种基于分治策略的排序算法
  • 快速排序的核心操作是 “哨兵划分”,其目标是:选择数组中的某个元素作为 “基准数”,将所有小于基准数的元素移到其左侧,而大于基准数的元素移到其右侧
    • 选取数组最左端元素作为基准数,初始化两个指针 i 和 j 分别指向数组的两端
    • 设置一个循环,在每轮中使用 i(j)分别寻找第一个比基准数大(小)的元素,然后交换这两个元素
    • 循环执行步骤 2,直到 i 和 j 相遇时停止,最后将基准数交换至两个子数组的分界线

    哨兵划分的实质是将一个较长数组的排序问题简化为两个较短数组的排序问题

    • 哨兵划分完成后,原数组被划分成三部分:左子数组、基准数、右子数组,且满足 “左子数组任意元素 ≤ 基准数 ≤ 右子数组任意元素”。因此,接下来只需对这两个子数组进行排序

在这里插入图片描述

/* 元素交换 */
void swap(vector<int> &nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;
}/* 哨兵划分 */
int partition(vector<int> &nums, int left, int right) {// 以 nums[left] 作为基准数int i = left, j = right;while (i < j) {while (i < j && nums[j] >= nums[left])j--;          // 从右向左找首个小于基准数的元素while (i < j && nums[i] <= nums[left])i++;          // 从左向右找首个大于基准数的元素swap(nums, i, j); // 交换这两个元素}swap(nums, i, left);  // 将基准数交换至两子数组的分界线return i;             // 返回基准数的索引
}

4.1 算法流程

  • 首先,对原数组执行一次 “哨兵划分”,得到未排序的左子数组和右子数组
  • 然后,对左子数组和右子数组分别递归执行 “哨兵划分”
  • 持续递归,直至子数组长度为 1 时终止,从而完成整个数组的排序

在这里插入图片描述

/* 快速排序 */
// 时间复杂度:O(nlog n),最差情况下 O(n^2)
// 空间复杂度:O(n)
void quickSort(vector<int> &nums, int left, int right) {// 子数组长度为 1 时终止递归if (left >= right)return;// 哨兵划分int pivot = partition(nums, left, right);// 递归左子数组、右子数组quickSort(nums, left, pivot - 1);quickSort(nums, pivot + 1, right);
}

4.2 快排为什么快

  • 快速排序在效率方面应该具有一定的优势。尽管快速排序的平均时间复杂度与 “归并排序” 和 “堆排序” 相同,但通常快速排序的效率更高,主要有以下原因
    • 出现最差情况的概率很低
      • 虽然快速排序的最差时间复杂度为 O(n^2),没有归并排序稳定,但在绝大多数情况下,快速排序能在 O(nlog n) 的时间复杂度下运行
    • 缓存使用效率高
      • 在执行哨兵划分操作时,系统可将整个子数组加载到缓存,因此访问元素的效率较高。而像 “堆排序” 这类算法需要跳跃式访问元素,从而缺乏这一特性
    • 复杂度的常数系数低
      • 在上述三种算法中,快速排序的比较、赋值、交换等操作的总数量最少。这与 “插入排序” 比 “冒泡排序” 更快的原因类似

4.3 基准数优化

  • 快速排序在某些输入下的时间效率可能降低

    • 例如:假设输入数组是完全倒序的,由于选择最左端元素作为基准数,那么在哨兵划分完成后,基准数被交换至数组最右端,导致左子数组长度为 n-1、右子数组长度为 0。如此递归下去,每轮哨兵划分后的右子数组长度都为 0,分治策略失效,快速排序退化为 “冒泡排序”
  • 为避免这种情况发生,可以优化哨兵划分中的基准数的选取策略

    • 例如,可以随机选取一个元素作为基准数。然而,如果运气不佳,每次都选到不理想的基准数,效率仍然不尽如人意
    • 可以在数组中选取三个候选元素(通常为数组的首、尾、中点元素),并将这三个候选元素的中位数作为基准数。这样,基准数 “既不太小也不太大” 的概率将大幅提升。还可以选取更多候选元素,以进一步提高算法的稳健性
    /* 选取三个元素的中位数 */
    int medianThree(vector<int> &nums, int left, int mid, int right) {// 此处使用异或运算来简化代码// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right]))return left;else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))return mid;elsereturn right;
    }/* 哨兵划分(三数取中值) */
    int partition(vector<int> &nums, int left, int right) {// 选取三个候选元素的中位数int med = medianThree(nums, left, (left + right) / 2, right);// 将中位数交换至数组最左端swap(nums, left, med);// 以 nums[left] 作为基准数int i = left, j = right;while (i < j) {while (i < j && nums[j] >= nums[left])j--; // 从右向左找首个小于基准数的元素while (i < j && nums[i] <= nums[left])i++;          // 从左向右找首个大于基准数的元素swap(nums, i, j); // 交换这两个元素}swap(nums, i, left); // 将基准数交换至两子数组的分界线return i;            // 返回基准数的索引
    }
    

4.4 尾递归优化

  • 在某些输入下,快速排序可能占用空间较多
    • 以完全倒序的输入数组为例,由于每轮哨兵划分后右子数组长度为 0,递归树的高度会达到 n-1,此时需要占用 O(n) 大小的栈帧空间
  • 为了防止栈帧空间的累积,可以在每轮哨兵排序完成后,比较两个子数组的长度
    • 仅对较短的子数组进行递归。由于较短子数组的长度不会超过 n/2,因此这种方法能确保递归深度不超过 log n,从而将最差空间复杂度优化至 O(log n)
    /* 快速排序(尾递归优化) */
    void quickSort(vector<int> &nums, int left, int right) {// 子数组长度为 1 时终止while (left < right) {// 哨兵划分操作int pivot = partition(nums, left, right);// 对两个子数组中较短的那个执行快排if (pivot - left < right - pivot) {quickSort(nums, left, pivot - 1); // 递归排序左子数组left = pivot + 1;                 // 剩余未排序区间为 [pivot + 1, right]} else {quickSort(nums, pivot + 1, right); // 递归排序右子数组right = pivot - 1;                 // 剩余未排序区间为 [left, pivot - 1]}}
    }
    

5. 归并排序

  • 归并排序是一种基于分治策略的排序算法,包含下图所示的 “划分” 和 “合并” 阶段
    • 划分阶段:通过递归不断地将数组从中点处分开,将长数组的排序问题转换为短数组的排序问题
    • 合并阶段:当子数组长度为 1 时终止划分,开始合并,持续地将左右两个较短的有序数组合并为一个较长的有序数组,直至结束

在这里插入图片描述

5.1 算法流程

  • “划分阶段” 从顶至底递归地将数组从中点切分为两个子数组
    • 计算数组中点 mid,递归划分左子数组(区间 [left, mid])和右子数组(区间 [mid + 1, right])
    • 递归执行步骤 1,直至子数组区间长度为 1 时,终止递归划分
  • “合并阶段” 从底至顶地将左子数组和右子数组合并为一个有序数组。需要注意的是,从长度为 1 的子数组开始合并,合并阶段中的每个子数组都是有序的

在这里插入图片描述

  • 归并排序与二叉树后序遍历的递归顺序是一致的
    • 后序遍历:先递归左子树,再递归右子树,最后处理根节点
    • 归并排序:先递归左子数组,再递归右子数组,最后处理合并
    /* 合并左子数组和右子数组 */
    // 左子数组区间 [left, mid]
    // 右子数组区间 [mid + 1, right]
    void merge(vector<int> &nums, int left, int mid, int right) {// 初始化辅助数组vector<int> tmp(nums.begin() + left, nums.begin() + right + 1);// 左子数组的起始索引和结束索引int leftStart = left - left, leftEnd = mid - left;// 右子数组的起始索引和结束索引int rightStart = mid + 1 - left, rightEnd = right - left;// i, j 分别指向左子数组、右子数组的首元素int i = leftStart, j = rightStart;// 通过覆盖原数组 nums 来合并左子数组和右子数组for (int k = left; k <= right; k++) {// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++if (i > leftEnd)nums[k] = tmp[j++];// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++else if (j > rightEnd || tmp[i] <= tmp[j])nums[k] = tmp[i++];// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++elsenums[k] = tmp[j++];}
    }/* 归并排序 */
    // 时间复杂度:O(nlog n)
    // 空间复杂度:O(n)
    void mergeSort(vector<int> &nums, int left, int right) {// 终止条件if (left >= right)return; // 当子数组长度为 1 时终止递归// 划分阶段int mid = (left + right) / 2;    // 计算中点mergeSort(nums, left, mid);      // 递归左子数组mergeSort(nums, mid + 1, right); // 递归右子数组// 合并阶段merge(nums, left, mid, right);
    }
    

merge() 函数注意事项

  • nums 的待合并区间为 [left, right] ,但由于 tmp 仅复制了 nums 该区间的元素,因此 tmp 对应区间为 [0, right - left]
  • 在比较 tmp[i] 和 tmp[j] 的大小时,还需考虑子数组遍历完成后的索引越界问题,即 i > leftEnd 和 j > rightEnd 的情况。索引越界的优先级是最高的,如果左子数组已经被合并完了,那么不需要继续比较,直接合并右子数组元素即可

6. 堆排序

  • 堆排序是一种基于堆数据结构实现的高效排序算法。可利用 “建堆操作” 和 “元素出堆操作” 实现堆排序
    • 输入数组并建立小顶堆,此时最小元素位于堆顶
    • 不断执行出堆操作,依次记录出堆元素,即可得到从小到大排序的序列

    以上方法虽然可行,但需要借助一个额外数组来保存弹出的元素,比较浪费空间

算法流程

  • 1、输入数组并建立大顶堆
    • 完成后,最大元素位于堆顶
  • 2、将堆顶元素(第一个元素)与堆底元素(最后一个元素)交换
    • 完成交换后,堆的长度减 1,已排序元素数量加 1
  • 3、从堆顶元素开始,从顶到底执行堆化操作
    • 完成堆化后,堆的性质得到修复
  • 4、循环执行第 2 和 3 步
    • 循环 n-1 轮后,即可完成数组排序

在这里插入图片描述

/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */
void siftDown(vector<int> &nums, int n, int i) {while (true) {// 判断节点 i, l, r 中值最大的节点,记为 maint l = 2 * i + 1;int r = 2 * i + 2;int ma = i;if (l < n && nums[l] > nums[ma])ma = l;if (r < n && nums[r] > nums[ma])ma = r;// 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出if (ma == i) {break;}// 交换两节点swap(nums[i], nums[ma]);// 循环向下堆化i = ma;}
}/* 堆排序 */
// 时间复杂度:O(nlog n)
// 空间复杂度:O(1)
void heapSort(vector<int> &nums) {// 建堆操作:堆化除叶节点以外的其他所有节点for (int i = nums.size() / 2 - 1; i >= 0; --i) {siftDown(nums, nums.size(), i);}// 从堆中提取最大元素,循环 n-1 轮for (int i = nums.size() - 1; i > 0; --i) {// 交换根节点与最右叶节点(即交换首元素与尾元素)swap(nums[0], nums[i]);// 以根节点为起点,从顶至底进行堆化siftDown(nums, i, 0);}
}

7. 桶排序

  • 前述的几种排序算法都属于 “基于比较的排序算法”,它们通过比较元素间的大小来实现排序。此类排序算法的时间复杂度无法超越 O(nlog n)。接下来,将探讨几种 “非比较排序算法”,它们的时间复杂度可以达到线性阶
  • 桶排序是分治策略的一个典型应用
    • 它通过设置一些具有大小顺序的桶,每个桶对应一个数据范围,将数据平均分配到各个桶中
    • 然后,在每个桶内部分别执行排序
    • 最终按照桶的顺序将所有数据合并

算法流程

  • 考虑一个长度为 n 的数组,元素是范围 [0, 1) 的浮点数
    • 初始化 k 个桶,将 n 个元素分配到 k 个桶中
    • 对每个桶分别执行排序
    • 按照桶的从小到大的顺序,合并结果

在这里插入图片描述

/* 桶排序 */
// 时间复杂度:O(n + k),最差(所有元素被分至同一个桶中)时间复杂度是 O(n^2)
// 空间复杂度:O(n + k)
void bucketSort(vector<float> &nums) {// 初始化 k = n/2 个桶,预期向每个桶分配 2 个元素int k = nums.size() / 2;vector<vector<float>> buckets(k);// 1. 将数组元素分配到各个桶中for (float num : nums) {// 输入数据范围 [0, 1),使用 num * k 映射到索引范围 [0, k-1]int i = num * k;// 将 num 添加进桶 bucket_idxbuckets[i].push_back(num);}// 2. 对各个桶执行排序for (vector<float> &bucket : buckets) {// 使用内置排序函数,也可以替换成其他排序算法sort(bucket.begin(), bucket.end());}// 3. 遍历桶合并结果int i = 0;for (vector<float> &bucket : buckets) {for (float num : bucket) {nums[i++] = num;}}
}

8. 小结

在这里插入图片描述

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

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

相关文章

湖南互联网医院|湖南互联网医院牌照办理流程及材料

互联网医牌照&#xff0c;一个让医疗行业焕发数字化新生的通行证。随着时代的进步和技术的发展&#xff0c;互联网已经深入各个行业&#xff0c;医疗领域也不例外。而互联网医牌照的办理流程、内容以及所需材料&#xff0c;则是诸多医疗机构所关注的核心内容。 第一种是实体医…

轻量限制流量?阿里云轻量应用服务器月流量包收费说明

阿里云轻量应用服务器部分套餐限制月流量&#xff0c;轻量应用服务器按照套餐售卖&#xff0c;有的套餐限制月流量&#xff0c;有的不限制流量。像阿里云轻量2核2G3M带宽轻量服务器一年108元和轻量2核4G4M带宽一年297.98元12个月&#xff0c;这两款是不限制月流量的。阿里云百科…

Java学习笔记(一)

目录 一、Java概述 &#xff08;一&#xff09;Java技术体系平台 &#xff08;二&#xff09;Java重要特点 &#xff08;三&#xff09;Java运行机制及运行过程 &#xff08;四&#xff09;JDK &#xff08;五&#xff09;JRE 二、Java的快速入门 &#xff08;一&#…

墨西哥专线空加派一条龙服务性价比高吗?

随着全球贸易的不断发展&#xff0c;越来越多的企业开始关注跨境物流&#xff0c;以满足国际市场的需求。墨西哥专线空加派一条龙服务作为一种便捷、高效的物流解决方案&#xff0c;越来越受到企业的青睐。那么&#xff0c;墨西哥专线空加派一条龙服务的性价比高吗?本文将从服…

企业门户的必备选择,WorkPlus的定制化解决方案

在当今数字化时代&#xff0c;企业门户成为了企业内外沟通与协作的重要基础设施。WorkPlus作为领先的品牌&#xff0c;为企业提供了一站式的企业门户解决方案&#xff0c;旨在提升企业形象、改善内外部沟通与协作效率。本文将深入探讨WorkPlus如何通过定制化的设计&#xff0c;…

fastadmin 后台列表数据多表查询筛选

记录一下fastadmin后台列表数据连表查询筛选提示&#xff1a; 1&#xff1a;下拉框方式搜索 示例&#xff1a; 在对应js文件中添加如下代码&#xff1a; 代码&#xff1a; {field: s.area_id,title: __(所属片区),visible: false,//不显示在列表中operate: ,searchList: $.…

关于Jupyter notebook 创建python3 时进去不能重命名问题及不能编程问题

首先写这篇博客时&#xff0c;已经被这个问题折磨了三天&#xff0c;看了很多博客&#xff0c;其实解决这个问题的关键就是要么没有下pyzmq或者等级太高&#xff0c;要么等级太低&#xff0c;首先我会按照我思路来。 问题如图&#xff1a; 1.自动换行 2.不能重命名 我的解决办…

MOM与MES管理系统有哪些本质上的区别

随着企业业务的不断发展&#xff0c;许多制造企业开始面临车间管理失控、生产不透明等问题。这时候&#xff0c;很多企业选择上线MES生产管理系统来提高生产管理水平。然而&#xff0c;随着企业业务的不断拓展&#xff0c;MES系统也逐渐暴露出其局限性。于是&#xff0c;MOM平台…

水库安全监测方案(实时数据采集、高速数据传输)

​ 一、引言 水库的安全监测对于防止水灾和保障人民生命财产安全至关重要。为了提高水库安全监测的效率和准确性&#xff0c;本文将介绍一种使用星创易联DTU200和SG800 5g工业路由器部署的水库安全监测方案。 二、方案概述 本方案主要通过使用星创易联DTU200和SG800 5g工业路…

ws升级为wss

需求&#xff1a;项目中需要使用netty&#xff0c;本地测试的时候使用的是ws&#xff0c;然后要部署到服务器上&#xff0c;使用https连接&#xff0c;https下就不能用ws了&#xff0c;必须升级到wss 1.阿里云申请免费证书 2.保存证书到本地目录 3.修改代码 SslUtil 工具类…

集成学习

集成学习&#xff08;Ensemble Learning) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/27689464集成学习就是组合这里的多个弱监督模型以期得到一个更好更全面的强监督模型&#xff0c;集成学习潜在的思想是即便某一个弱分类器得到了错误的预测&#xff0c;其他的弱分类器…

网络爬虫中的代理技术:socks5代理和HTTP代理

网络爬虫是一种非常重要的数据采集工具&#xff0c;但是在进行网络爬虫时&#xff0c;我们经常会遇到一些限制&#xff0c;比如IP封锁、反爬虫机制等&#xff0c;这些限制会影响我们的数据采集效果。为了解决这些问题&#xff0c;我们可以使用代理服务器&#xff0c;其中socks5…

关于打造安卓测试机的方法以及常见问题的解决方式

摘要&#xff1a; 本文主要讲解如何打造安卓测试机&#xff0c;并刷机google原生系统、部署Magisk对测试机进行root的常用方式&#xff1b;并对一些常见问题进行思路解答。本文适合新手学习&#xff0c;大佬请绕过 本次实验使用的设备及环境如下&#xff1a; Nexus 5x 测试机…

深入了解归并排序:原理、性能分析与 Java 实现

归并排序&#xff08;Merge Sort&#xff09;是一种高效且稳定的排序算法&#xff0c;其优雅的分治策略使它成为排序领域的一颗明珠。它的核心思想是将一个未排序的数组分割成两个子数组&#xff0c;然后递归地对子数组进行排序&#xff0c;最后将这些排好序的子数组合并起来。…

TensorFlow入门(十四、数据读取机制(1))

TensorFlow的数据读取方式 TensorFlow的数据读取方式共有三种,分别是: ①预加载数据(Preloaded data) 预加载数据的方式,其实就是静态图(Graph)的模式。即将数据直接内嵌到Graph中,再把Graph传入Session中运行。 示例代码如下: import tensorflow.compat.v1 as tf tf.disabl…

符合 EN55022B 规格、LTM4613EY、LTM4613MPV直流µModule稳压器【RG500Q 5G Sub-6 GHz 模块】

一、LTM4613&#xff0c;符合 EN55022B 规格的 36VIN、15VOUT、8A、DC/DC Module 稳压器 &#xff08;简介&#xff09;LTM4613 是一款完整、超低噪声、8A 开关模式 DC/DC 电源。封装中内置了开关控制器、功率 FET、电感器和所有的支持元件。LTM4613 的工作输入电压范围为 5V 至…

基于maven的项目搭建(已跑通)

1、直接选择archetype-webapp即可 &#xff08;这里很多人会觉得很慢–解决方案&#xff1a;https://blog.csdn.net/qq_45591895/article/details/133705674?spm1001.2014.3001.5501&#xff09; 2、手动添加一个java目录即可。 3、添加Tomcat 3、这就跑通了&#xff0c;可以…

Python 樱花

Python实现樱花 效果图 &#xff08;源码在下面&#xff09; 源码&#xff1a; from turtle import * from random import * from math import *def tree(n, l):pd() # 下笔# 阴影效果t cos(radians(heading() 45)) / 8 0.25pencolor(t, t, t)pensize(n / 3)forward(l…

基于 FPGA 的机器博弈五子棋游戏

基于 FPGA 的机器博弈五子棋游戏 一,设计目的 五子棋是一种深受大众喜爱的游戏,其规则简单,变化多端,非常富有趣味性 和消遣性。棋类游戏在具备娱乐性、益智性的同时也因为其载体大多是手机, 电脑等移动互联网设备导致现代社会低头族等现象更加严重,危害青少年的身 体健康…

ThreeJS-3D教学五-材质

我们在ThreeJS-3D教学二&#xff1a;基础形状展示中有简单介绍过一些常用的材质&#xff0c;这次我们举例来具体看下效果&#xff1a; 代码是这样的&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&…