当前位置: 首页 > article >正文

《二叉树:二叉树的顺序结构->堆》

二叉树一般可以使用两种结构存储,一种是顺序结构,一种是链式结构。

  • 顺序存储

顺序结构存储是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。实际上使用中只有堆才会使用数组来存储。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

  • 链式存储

用链表来表示一颗二叉树。使用链来指示元素的逻辑关系。链表中每个节点由三个域组成,数据域和左右指针,左右指针分别指向该结点的左孩子和右孩子所在链结点的存储地址。链式结构又分为二叉链和三叉链。本篇内容为二叉链。

二叉树的顺序结构实现

把堆(完全二叉树)使用顺序结构的数组来存储。

大根堆:树中的每个结点,其值都大于或等于其子结点的值。也就是说,在大根堆中,根结点是堆中的最大元素。

小根堆:树中的每个结点,其值都小于或等于其子结点的值。也就是说,在小根堆中,根结点是堆中的最小元素。

堆的性质

  1. 堆中某个结点的值总是不大于或不小于其父结点的值
  2. 堆总是一颗完全二叉树

堆的实现

下面所演示的为一个小堆的实现。

向下调整算法

给出一个数组,逻辑上看作是一颗完全二叉树。通过根结点的向下调整算法可以把它调整为一个小堆/大堆。向下调整算法有一个前提:左右子树必须是一个小堆/大堆,才可以调整

int array[] = {27,15,19,18,28,34,65,49,25,37};

下面我们演示一下小堆的向下调整算法。 

// 小堆向下调整算法 
// 注意:调整的树的左右子树必须为小堆
void AdjustDown(HPDataType* a, int n, int root)
{// 父亲int parent = root;// 1.选出左右孩子较小的孩子跟父亲比较// 默认较小的孩子为左孩子int child = parent * 2 + 1;// 终止条件孩子到叶子结点最后跟父亲比一次while (child < n){// 2.如果右孩子小于左孩子,则较小的孩子为右孩子 if (child + 1 < n && a[child + 1] < a[child]){child++;}// 3.如果孩子小于父亲,则跟父亲交换if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

向下调整算法时间复杂度为O(log(N))。

堆的创建

通过向下调整算法,可以构建一个小堆,但是前提是根的左右子树本来就为小堆。但是如果根结点的左右子树不为小堆,怎么调整呢?

最后一个非叶子结点开始向下调整,一直调整到根,就能构建出一个小堆。最后一个非叶子结点可以看做它的左右子树(叶子结点)就是小堆,所以从这个切入点开始,每次向下调整都能保证左右子树是一个小堆,直到根开始向下调整的时候,它的左右子树此时就已经为一个小堆了。

下面来演示一下这个过程。

void HeapInit(Heap* php,HPDataType* a,int n)
{php->_capacity = n;php->_size = n;php->_a = (HPDataType*)malloc(sizeof(HPDataType) * n);if (php->_a == NULL){perror("HeapInit");return;}memcpy(php->_a, a, sizeof(HPDataType)*n);// 创建小堆// 最后一个非叶子结点下标为(n-1-1)/2for (int i = (n - 1 - 1) / 2; i >= 0; i--){// 从最后一个非叶子结点开始向下调整,一直调整到根,就能保证构建出来的堆是一个小堆AdjustDown(php->_a, php->_size, i);}
}

建堆的时间复杂度

O(N)。

堆的插入

插入一个元素到数组的尾部,再进行向上调整算法,直到满足堆。

向上调整算法

  1. 将元素插入到堆的末尾
  2. 插入之后如果堆结构被破坏,将插入的新结点顺着其双亲向上调整到合适的位置即可。
// 向上调整算法 
void AdjustUp(HPDataType* a, int n,int child)
{assert(a);// 父亲和孩子的关系:parent=(child-1)/2int parent = (child - 1) / 2;// while(parent >= 0)  error,如果最后调整的是根,parent =(1-1)/2=0 条件依然满足,parent = (0-1)/2=0 无限循环while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}// 堆的插入
void HeapPush(Heap* php, HPDataType x)
{assert(php);if (php->_capacity == php->_size){php->_capacity *= 2;HPDataType* tmp = (HPDataType*)realloc(php->_a, sizeof(HPDataType) * php->_capacity);if (tmp == NULL){perror("CheckCapacity");return;}php->_a = tmp;}php->_a[php->_size] = x;php->_size++;// 向上调整算法AdjustUp(php->_a, php->_size, php->_size - 1);
}

向上调整算法时间复杂度为O(log(N))

堆的删除

删除堆,是删除堆顶的数据,不能直接将堆顶的数据直接删除,因为一旦直接删除,堆结构就被破坏了。将堆顶的数据与最后一个数据交换,然后删除数组最后一个数据,再进行堆的向下调整即可。

  1. 将堆顶元素与堆最后一个元素交换
  2. 删除堆最后一个元素
  3. 将堆顶元素向下调整直到满足堆特性
// 堆的删除
void HeapPop(Heap* php)
{assert(php);assert(php->_size > 0);// 交换堆顶与最后一个元素Swap(&php->_a[0], &php->_a[php->_size - 1]);php->_size--;// 堆顶元素向下调整AdjustDown(php->_a, php->_size, 0);
}

堆的应用

堆排序

堆排序利用了堆的思想来排序。

1、建堆

  • 排升序,建大堆
  • 排降序,建小堆

2、利用堆删除思想进行排序

建堆和堆删除都使用了堆的向下调整算法,因此,理解了向下调整算法,就掌握了堆排序。

void HeapSort(int* a, int n)
{assert(a);//建堆 排升序 建大堆for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);}int end = n - 1;while (end >= 1){// 交换堆顶与最后一个元素Swap(&a[0], &a[end]);// 向下调整AdjustDown(a, end, 0);end--;}
}

以排升序为例,建大堆。

堆顶元素是最大的,将堆顶元素与最后一个元素交换,最后一个元素就是最大的元素。

然后堆顶元素再进行向下调整,调整之后,堆顶元素就是除第二大元素,再将堆顶元素与最后倒数第二个元素交换,此时,第二大的元素就在倒数第二个位置了。

以此类推,最后的堆结构就是一个小堆结构,并且是有序的,升序。

堆排序的时间复杂度为:建堆阶段+堆排序阶段时间复杂度=O(N)+O(NlogN)=O(NlogN)

Top-K问题

求数据集合中前K个最大元素或前K个最小元素,一般情况下数据量都比较大。

对于Top-K问题,最先想到的肯定是排序,但是:如果数据量非常大,排序就不太可能了,数据可能不能一下全部都加载到内存中。最好的方式是用堆来解决。

1、用数据集合中前K个元素来建堆。

  • 求前K个最大的元素,则建小堆
  • 求前K个最小的元素,则建大堆

2、用剩余的N-K个元素依次与堆顶元素比较,满足则替换堆顶元素,再进行向下调整。将剩余N-K个元素比较完之后,堆中剩余的就是所求的前K个最大元素或者最小元素。

以求前K个最大元素为例:建小堆,因为小堆的堆顶元素是堆中最小的元素,当后续元素与堆顶元素比较时,如果该元素比堆顶元素大,就可以替换堆顶元素,然后重新调整堆,这样可以保证堆中始终保留当前最大的K个元素。

HPDataType* HeapTopK(Heap* php,int k)
{assert(php);HPDataType* arrk = (HPDataType*)malloc(sizeof(HPDataType) * k);// 前K个元素建堆for (int i = 0; i < k; i++){arrk[i] = php->_a[i];}for (int i = (k-1-1)/2; i >= 0; i--){// 求前K最大元素,向下调整建小堆AdjustDown(arrk, k, i);}// 剩余N-K个数据依次与堆顶比较for (int j = k; j < php->_size; j++){// 如果比堆顶大,则替换,再向下调整if (php->_a[j] > arrk[0]){arrk[0] = php->_a[j];AdjustDown(arrk, k, 0);}}return arrk;
}

全部代码

Heap.h:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>typedef int HPDataType;typedef struct Heap
{HPDataType* _a;int _size;int _capacity;
}Heap;// 堆初始化
void HeapInit(Heap* php,HPDataType* a,int n );// 向下调整
void AdjustDown(HPDataType* a, int n, int root);// 打印堆
void HeapPrint(Heap* php);// 堆的插入
void HeapPush(Heap* php, HPDataType x);// 堆的删除
void HeapPop(Heap* php);// 取堆顶的数据
HPDataType HeapTop(Heap* php);// 取最大的前k个数据
// 1.堆排序
// 2.HeapPop k-1次
// 3.排升序,建k个元素的小堆
HPDataType* HeapTopK(Heap* php,int k);

 Heap.c:

#include"Heap.h"void Swap(HPDataType* p1, HPDataType* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void HeapInit(Heap* php,HPDataType* a,int n)
{php->_capacity = n;php->_size = n;php->_a = (HPDataType*)malloc(sizeof(HPDataType) * n);if (php->_a == NULL){perror("HeapInit");return;}memcpy(php->_a, a, sizeof(HPDataType)*n);// 构建小堆// 最后一个非叶子结点下标为(n-1-1)/2for (int i = (n - 1 - 1) / 2; i >= 0; i--){// 从最后一个非叶子结点开始向下调整,一直调整到根,就能保证构建出来的堆是一个小堆AdjustDown(php->_a, php->_size, i);}
}// 小堆向下调整算法 
// 注意:调整的树的左右子树必须为小堆
void AdjustDown(HPDataType* a, int n, int root)
{// 父亲int parent = root;// 1.选出左右孩子较小的孩子跟父亲比较// 默认较小的孩子为左孩子int child = parent * 2 + 1;// 终止条件孩子到叶子结点最后跟父亲比一次while (child < n){// 2.如果右孩子小于左孩子,则较小的孩子为右孩子 if (child + 1 < n && a[child + 1] < a[child]){child++;}// 3.如果孩子小于父亲,则跟父亲交换if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}// 向上调整算法 
void AdjustUp(HPDataType* a, int n,int child)
{assert(a);// 父亲和孩子的关系:parent=(child-1)/2int parent = (child - 1) / 2;// while(parent >= 0)  error,如果最后调整的是根,parent =(1-1)/2=0 条件依然满足,parent = (0-1)/2=0 无限循环while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HeapPrint(Heap* php)
{assert(php);for (int i = 0; i < php->_size; i++){printf("%d ", php->_a[i]);}printf("\n");
}void HeapPush(Heap* php, HPDataType x)
{assert(php);if (php->_capacity == php->_size){php->_capacity *= 2;HPDataType* tmp = (HPDataType*)realloc(php->_a, sizeof(HPDataType) * php->_capacity);if (tmp == NULL){perror("CheckCapacity");return;}php->_a = tmp;}php->_a[php->_size] = x;php->_size++;AdjustUp(php->_a, php->_size, php->_size - 1);
}void HeapPop(Heap* php)
{assert(php);assert(php->_size > 0);//交换堆顶与最后一个元素Swap(&php->_a[0], &php->_a[php->_size - 1]);php->_size--;AdjustDown(php->_a, php->_size, 0);
}HPDataType HeapTop(Heap* php)
{assert(php);return php->_a[0];
}HPDataType* HeapTopK(Heap* php,int k)
{assert(php);HPDataType* arrk = (HPDataType*)malloc(sizeof(HPDataType) * k);// 前K个元素建堆for (int i = 0; i < k; i++){arrk[i] = php->_a[i];}for (int i = (k-1-1)/2; i >= 0; i--){// 求前K最大元素,向下调整建小堆AdjustDown(arrk, k, i);}// 剩余N-K个数据依次与堆顶比较for (int j = k; j < php->_size; j++){// 如果比堆顶大,则替换,再向下调整if (php->_a[j] > arrk[0]){arrk[0] = php->_a[j];AdjustDown(arrk, k, 0);}}return arrk;
}

Test.c:

#include"Heap.h"void HeapSort(int* a, int n)
{assert(a);//建堆 排降序 建小堆for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);}int end = n - 1;while (end >= 1){// 交换堆顶与最后一个元素Swap(&a[0], &a[end]);// 向下调整AdjustDown(a, end, 0);end--;}
}int main()
{Heap hp;int arry[] = { 27,15,19,18,28,34,69,49,25,37 };int n = sizeof(arry) / sizeof(arry[0]);HeapInit(&hp,arry,n);HeapPrint(&hp);HeapPush(&hp,20);HeapPrint(&hp);// 堆排序arryHeapSort(arry, n);for (int i = 0; i < n; i++){printf("%d ", arry[i]);}printf("\n");// Top前5个最大的元素int* arrk =HeapTopK(&hp,5);int i = 0;for (i = 0; i < 5; i++){printf("%d ", arrk[i]);}return 0;
}

二叉树的链式结构实现

关于二叉树的链式结构实现可以看下篇文章。

【二叉树进阶】二叉搜索树

相关文章:

《二叉树:二叉树的顺序结构->堆》

二叉树一般可以使用两种结构存储&#xff0c;一种是顺序结构&#xff0c;一种是链式结构。 顺序存储 顺序结构存储是使用数组来存储&#xff0c;一般使用数组只适合表示完全二叉树&#xff0c;因为不是完全二叉树会有空间的浪费。实际上使用中只有堆才会使用数组来存储。二叉…...

OpenLayers:封装Overlay的方法

平时在使用OpenLayers的Overlay时常感觉不便&#xff0c;于是最近我便封装了一些Overlay增删改查的方法&#xff0c;以提高可用性。这边文章中我会介绍我封装的方法&#xff0c;同时记录这个过程中踩的一些坑。 添加Overlay /*** abstract 添加overlay* param {*} map* param…...

软件重构与项目进度的矛盾如何解决

软件重构与项目进度之间的矛盾可以通过明确重构目标与范围、采用渐进式重构策略、优化项目管理流程、提高团队沟通效率、建立重构意识文化等方式解决。其中&#xff0c;采用渐进式重构策略尤为关键。渐进式重构是指在日常开发过程中&#xff0c;以小步骤持续进行重构&#xff0…...

Mysql+Demo 获取当前日期时间的方式

记录一下使用Mysql获取当前日期时间的方式 获取当前完整的日期时间有常见的四种方式&#xff0c;获取得到的默认格式(mysql的格式标准)是 %Y-%m-%d %H:%i:%s其它格式 %Y-%m-%d %H:%i:%s.%f方式一&#xff1a;now()函数 select now();mysql> select now(); -------------…...

数智化时代下开源AI大模型驱动的新型商业生态构建——基于AI智能名片与S2B2C商城小程序的融合创新研究

摘要 数字技术的指数级发展推动物理世界向数智化网状结构加速转型&#xff0c;传统商业逻辑面临系统性重构。本文以"开源AI大模型AI智能名片S2B2C商城小程序"为研究主体&#xff0c;采用案例分析与技术验证相结合的方法&#xff0c;揭示技术融合对商业生态的重塑机制…...

Spring Cloud Alibaba 技术全景与实战指南

简介&#xff1a; Spring Cloud Alibaba 是阿里巴巴开源的微服务解决方案&#xff0c;基于 Spring Cloud 标准构建&#xff0c;提供了一站式分布式系统开发能力。它深度整合阿里云生态组件&#xff0c;为企业级微服务架构提供高可用、高性能的技术支撑。 核心特性 全栈微服务能…...

回归预测 | Matlab实现NRBO-Transformer-BiLSTM多输入单输出回归预测

回归预测 | Matlab实现NRBO-Transformer-BiLSTM多输入单输出回归预测 目录 回归预测 | Matlab实现NRBO-Transformer-BiLSTM多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.【JCR一区级】Matlab实现NRBO-Transformer-BiLSTM多变量回归预测&#xf…...

了解 PoE 握手协议在网络配电中的重要性

在现代网络领域&#xff0c;以太网供电(PoE)已成为一项革命性的技术&#xff0c;通过在一根以太网电缆上集成电力和数据传输&#xff0c;简化了网络连接设备的部署和管理。这种无缝操作的核心是 PoE 握手 —— 一个促进支持PoE 的设备之间的通信、确保高效供电和保护网络基础设…...

小智机器人相关函数解析,BackgroundTask::Schedule (***)将一个回调函数添加到后台任务队列中等待执行

以下是对 BackgroundTask::Schedule 函数代码的详细解释&#xff1a; void BackgroundTask::Schedule(std::function<void()> callback) {std::lock_guard<std::mutex> lock(mutex_);if (active_tasks_ > 30) {int free_sram heap_caps_get_free_size(MALLOC_…...

基于Python设计的TEQC数据质量可视化分析软件

标题:基于Python设计的TEQC数据质量可视化分析软件 内容:1.摘要 本文旨在设计一款基于Python的TEQC数据质量可视化分析软件。随着全球导航卫星系统&#xff08;GNSS&#xff09;的广泛应用&#xff0c;数据质量的评估变得至关重要。TEQC&#xff08;TransEditQualityCheck&…...

人月神话:如何有效的避免Bug的产生

bug的来源有很多种&#xff0c;一般的小bug很好修复&#xff0c;最头疼的是哪些致命且难以察觉的Bug。这些bug从哪来的&#xff1f; 在人月神话书中说&#xff1a;假设的不匹配是大多数致命和难以察觉的bug的主要来源。 假设来源于各个组成部分的开发者对概念的理解不一致。 为…...

Git的基础使用方法

本文最终功能&#xff1a; 1.从终端直接传输代码给仓库 2.用终端从仓库克隆文件 基本概念 我们先来理解下 Git 工作区、暂存区和版本库概念&#xff1a; 工作区&#xff1a;就是你在电脑里能看到的目录。 暂存区&#xff1a;英文叫 stage 或 index。一般存放在 .git 目录下的…...

轮胎厂相关笔记

一、术语 图解&#xff1a;https://news.yiche.com/hao/wenzhang/38498703/ 1、胚胎 在轮胎制造行业中&#xff0c;“胎胚”&#xff08;也称“生胎”或“未硫化轮胎”&#xff09;是指轮胎在硫化&#xff08;高温高压固化&#xff09;之前的半成品形态。它是轮胎成型的中间…...

Java常用异步方式总结

使用建议 完整代码见https://gitee.com/pinetree-cpu/parent-demon 提供了postMan调试json文件于security-demo/src/main/resources/test_file/java-async.postman_collection.json 可导入postMan中进行调试 Java异步方式以及使用场景 继承Thread类 新建三个类继承Thread&…...

【Easylive】视频在线人数统计系统实现详解 WebSocket 及其在在线人数统计中的应用

【Easylive】项目常见问题解答&#xff08;自用&持续更新中…&#xff09; 汇总版 视频在线人数统计系统实现详解 1. 系统架构概述 您实现的是一个基于Redis的视频在线人数统计系统&#xff0c;主要包含以下组件&#xff1a; 心跳上报接口&#xff1a;客户端定期调用以…...

tomcat 目录结构组成

文章目录 背景文件结构层级一些常用的路径 背景 现在非常多的 java web 服务部署在 linux 服务器中&#xff0c;我们服务器中的 tomcat 会有各种文件路径&#xff0c;看下它有哪些文件 文件结构层级 ├── bin/ # 核心脚本和启动文件 ├── conf/ # …...

苍穹外卖day12

课程内容 工作台 Apache POI 导出运营数据Excel报表 功能实现&#xff1a;工作台、数据导出 工作台效果图&#xff1a; 数据导出效果图&#xff1a; 在数据统计页面点击数据导出&#xff1a;生成Excel报表 1. 工作台 1.1 需求分析和设计 1.1.1 产品原型 工作台是系统运…...

Unity Final IK:下一代角色动画与物理交互的技术解析

引言&#xff1a;角色动画的范式转移 在传统游戏开发中&#xff0c;角色动画主要依赖于 前向动力学&#xff08;Forward Kinematics, FK&#xff09; 和预烘焙动画。然而&#xff0c;这种方法的局限性在开放世界、物理交互和VR等场景中愈发明显&#xff1a; 环境适应性差&…...

前端开发时的内存泄漏问题

目录 &#x1f50d; 什么是内存泄漏&#xff08;Memory Leak&#xff09;&#xff1f;&#x1f6a8; 常见的内存泄漏场景1️⃣ 未清除的定时器&#xff08;setInterval / setTimeout&#xff09;2️⃣ 全局变量&#xff08;变量未正确释放&#xff09;3️⃣ 事件监听未清除4️⃣…...

【Feign】⭐️使用 openFeign 时传递 MultipartFile 类型的参数参考

&#x1f4a5;&#x1f4a5;✈️✈️欢迎阅读本文章❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;本篇文章阅读大约耗时三分钟。 ⛳️motto&#xff1a;不积跬步、无以千里 &#x1f4cb;&#x1f4cb;&#x1f4cb;本文目录如下&#xff1a;&#x1f381;&#x1f381;&a…...

Linux中动静态库的制作

1.什么是库 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复⽤的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个⼈的代码都从零开始&#xff0c;因此库的存在意义非同寻常。 本质上来说库是⼀种可执⾏代码的⼆进制形式&#xff0c;可以被操作系统…...

Docker部署sprintboot后端项目

创建Docker网络 docker network create icjs 部署Redis docker run -d \--network icjs \--name redis \-p 6379:6379 \redis:latest数据持久化 docker run --restartalways --network icjs -p 6379:6379 --name redis -v /opt/docker/redis/redis.conf:/etc/redis/redis.c…...

forms实现连连看

说明&#xff1a; forms实现连连看 效果图&#xff1a; step1:C:\Users\wangrusheng\RiderProjects\WinFormsApp2\WinFormsApp2\Form1.cs using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms;namespace …...

多视图几何--立体校正--Fusiello方法

1. 坐标系对齐与正交基构造 目标&#xff1a;构建新坐标系基向量 { e 1 , e 2 , e 3 } \{ \mathbf{e}_1, \mathbf{e}_2, \mathbf{e}_3 \} {e1​,e2​,e3​}&#xff0c;使成像平面共面且极线水平对齐。 (1) 基线方向 e 1 \mathbf{e}_1 e1​ 基线向量由左右相机光心平移向量…...

鸿蒙开发踩坑记录 - 2024S2

wrapBuilder如果想View和ObservedV2做绑定 必须要用 ComponentV2 Param 和 区别 退出两层循环 Builder的传入的参数及时是Trace修饰的也无法刷新组件 折叠屏展开后键盘无法点击 vm是公用的&#xff0c;组件生命周期问题导致 监听键盘高度变化失效 原因&#xff1a;分享面…...

【学Rust写CAD】21 2D 点(point.rs)

源码 //matrix/point.rs use std::ops::Mul; use super::algebraic_units::{Zero, One}; use super::generic::Matrix;/// 点坐标结构体 #[derive(Debug, Clone, Copy, PartialEq)] pub struct Point<X, Y>(Matrix<X, Y, One, Zero, Zero, One>);impl<X, Y>…...

0基础入门scrapy 框架,获取豆瓣top250存入mysql

一、基础教程 创建项目命令 scrapy startproject mySpider --项目名称 创建爬虫文件 scrapy genspider itcast "itcast.cn" --自动生成 itcast.py 文件 爬虫名称 爬虫网址 运行爬虫 scrapy crawl baidu(爬虫名&#xff09; 使用终端运行太麻烦了&#xff0c;而且…...

鸿蒙NEXT小游戏开发:井字棋

1. 引言 井字棋是一款经典的两人对战游戏&#xff0c;简单易懂&#xff0c;适合各个年龄段的玩家。本文将介绍如何使用鸿蒙NEXT框架开发一个井字棋游戏&#xff0c;涵盖游戏逻辑、界面设计及AI对战功能。 2. 开发环境准备 电脑系统&#xff1a;windows 10 开发工具&#xff1a;…...

deep-sync开源程序插件导出您的 DeepSeek 与 public 聊天

一、软件介绍 文末提供下载 deep-sync开源程序插件导出您的 DeepSeek 与 public 聊天&#xff0c;这是一个浏览器扩展&#xff0c;它允许用户公开、私下分享他们的聊天对话&#xff0c;并使用密码或过期链接来增强 Deepseek Web UI。该扩展程序在 Deepseek 界面中添加了一个 “…...

4. 理解Prompt Engineering:如何让模型听懂你的需求

引言:当模型变成“实习生” 想象一下,你新招的实习生总把“帮我写份报告”理解为“做PPT”或“整理数据表”——这正是开发者与大模型对话的日常困境。某金融公司优化提示词后,合同审查准确率从72%飙升至94%。本文将用3个核心法则+5个行业案例,教你用Prompt Engineering让…...