数据结构——堆的实现

堆的实现-----C语言版

  • 目录:
  • 一、堆的实现
    • 1.1堆的定义
    • 1.2堆的实现
      • 1.2.1堆的各个接口
      • 1.2.2堆的向上调整
      • 1.2.3堆的向下调整
      • 1.2.4堆的定义声明和初始化
      • 1.2.5堆的数据处理
      • 1.2.6堆的判空和堆的数据个数以及堆销毁
      • 1.2.7堆的代码实现
  • 二、TOP—K问题

目录:

一、堆的实现

1.1堆的定义

(heap)是特殊的数据结构。堆通常是一个可以被看做一棵完全二叉树(逻辑层面上)的数组对象(物理层面上),常用来在一组变化频繁(发生增删查改的频率较高)的数据中寻找最值.将根结点最大的堆叫做最大堆或大根堆,这样可以找到堆中的最大值(根节点的值);根结点最小的堆叫做最小堆或小根堆,这样可以找到堆中的最小值。

其中堆不一定是完全二叉树,只是为了方便存储索引,我们通常用完全二叉树的形式来表示堆而已。
二叉堆:是一个数组,它可以被看成是一个近似的完全二叉树。

最大堆,最小堆如图:
在这里插入图片描述

最大堆:根结点大于左右子树结点的值,左右子树结点的值大于它自己左右子树结点的值,一种重复下去;最小堆:根结点小于左右子树结点的值,左右子树结点的值小于它自己左右子树结点的值,一种重复下去。

1.2堆的实现

用数组实现一个堆

1.2.1堆的各个接口

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* _a;//动态数组
	int _size;//存储数据的下标
	int _capacity;//动态数组的容量
}Heap;
//堆的初始化
void HeapInit(Heap* hp);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataTypeHeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
int HeapEmpty(Heap* hp);

1.2.2堆的向上调整

//向上调整算法
void HeapJustUp(HPDataType a[], HPDataType child)
{
    int parsent;
    parsent = (child - 1) / 2;//找到孩子的父亲
    while (child > 0)
    {
        int tmp = 0;
        if (a[parsent] < a[child])//孩子比父亲的值大,
        {
            tmp = a[child];
            a[child] = a[parsent];
            a[parsent] = tmp;
        }
        else
            break;
        child = parsent;
        parsent = (parsent - 1) / 2;//找到孩子的父亲
    }
}

对于向上调整,我们把它看做是数组结构,逻辑上看做一颗完全二叉树。我们只要将要插入堆的数据通过向上调整就可以把它调整成一个大堆。向上调整算法有一个前提:除了要插入的数据,其它的数据已经构成了一个大堆,这样才能调整。

1.2.3堆的向下调整

void HeapJustDown(Heap* hp)
{
    //先假设当前待调整结点的左孩子结点存在
        //并且是待调整结点的左右孩子结点(不管右孩子结点存不存在,都这样假设)中值最大的
    int parent = 0;//根节点
    int child = parent * 2 + 1;//孩子结点
        while (child < hp->_size)
        {
            //child+1 < hp->_size说明右孩子结点确实存在
            //如果hp->_a[child] < hp->_a[child+1]也成立,那说明左右孩子结点中值最大的是右孩子结点
            if ((child + 1 < hp->_size) && hp->_a[child] < hp->_a[child + 1])
            {
                child = child + 1;
            }
            //如果a[child]>a[parent],则说明父节点比比左右孩子节点的值都要小,要置换
            if (hp->_a[child] > hp->_a[parent])
            {
                int tmp = hp->_a[parent];
                hp->_a[parent] = hp->_a[child];
                hp->_a[child] = tmp;
                parent = child;
                child = child * 2 + 1;
            }
            //如果a[child] <= a[parent],那就不需要进行调整
            else
            {
                break;
            }
        }
}

对于向下调整,我们把它看成是一个数组结构,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个大堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

1.2.4堆的定义声明和初始化

1.堆的声明

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* _a;//动态数组
	int _size;//存储数据的下标
	int _capacity;//动态数组的容量
}Heap;

创建一个构成动态数组的结构体

2.堆的初始化

// 堆的初始化
void HeapInit(Heap* hp)
{
    hp->_a = (HPDataType*)malloc(sizeof(HPDataType) * 4);
    if (hp->_a == 0)
    {
        printf("malloc is error\n");
        exit(-1);
    }
    hp->_capacity = 4;
    hp->_size = 0;
}

开空间,进行初始化

1.2.5堆的数据处理

1.堆的插入

// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
    //数据满了,需要扩容
    if (hp->_capacity == hp->_size)
    {
        HPDataType* tmp = (HPDataType*)realloc(hp->_a, sizeof(HPDataType)*hp->_capacity * 2);
        if (tmp == NULL)
        {
            printf("realloc is error");
            exit(-1);
        }
        hp->_a = tmp;
        hp->_capacity = hp->_capacity * 2;
    }
    //不需要扩容
    hp->_a[hp->_size++] = x;//插入数据,然后_size+1
    //一般数据都是放到数组尾得,建堆,向上调整,这里我们建大堆
    HeapJustUp(hp->_a, hp->_size - 1);
}

1.容量不够就扩容
2.扩容足够就插入数据
3.然后向上调整建大堆,直到满足堆

2.堆的删除

// 堆的删除,从堆顶开始删
void HeapPop(Heap* hp)
{
assert(hp);//断言为空为假的话就报错
assert(!HeapEmpty(hp));//断言如果不是空为真就执行
//首元素的的值与尾元素交换,然后删除尾元素
int tmp = hp->_a[0];
hp->_a[0] = hp->_a[hp->_size - 1];
hp->_a[hp->_size - 1] = tmp;
hp->_size--;
//堆顶元素进行向下调整
HeapJustDown(hp);
}

1.挪动覆盖删除堆顶元素,重新建堆
2.尽量保证关系不变(首尾数据交换,再删除尾部数据,向下调整建堆)

3.获取堆顶数据

// 取堆顶的数据
HPDataTypeHeapTop(Heap* hp)
{
    assert(hp->_a);
    assert(!HeapEmpty(hp));//断言如果不是空为真就执行
    return hp->_a[0];
}

堆顶数据就是第一个元素

1.2.6堆的判空和堆的数据个数以及堆销毁

1.堆的数据个数

// 堆的数据个数
int HeapSize(Heap* hp)
{
    assert(hp);
    return hp->_size;
}

堆的数据个数就是_size的个数

2.堆的判空

// 堆的判空
int HeapEmpty(Heap* hp)
{
    assert(hp);
    return hp->_size == 0;
}

_size为0,说明堆为空

3.堆销毁

// 堆的销毁
void HeapDestory(Heap* hp)
{
    assert(hp);
    free(hp->_a);
    hp->_a = NULL;
    hp->_capacity = hp->_size = 0;
}

开一块空间(malloc),程序结束之前要释放空间(free)

1.2.7堆的代码实现

.h头文件(声明)

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* _a;//动态数组
	int _size;//存储数据的下标
	int _capacity;//动态数组的容量
}Heap;
//堆的初始化
void HeapInit(Heap* hp);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataTypeHeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
int HeapEmpty(Heap* hp);

.c源文件(定义)

#include "Heap.h"
// 堆的构建
void HeapInit(Heap* hp)
{
    hp->_a = (HPDataType*)malloc(sizeof(HPDataType) * 4);
    if (hp->_a == 0)
    {
        printf("malloc is error\n");
        exit(-1);
    }
    hp->_capacity = 4;
    hp->_size = 0;
}
//向上调整算法
HeapJustUp(HPDataType a[], HPDataType child)
{
    int parsent;
    parsent = (child - 1) / 2;//找到孩子的父亲
    while (child > 0)
    {
        int tmp = 0;
        if (a[parsent] < a[child])//孩子比父亲的值大,
        {
            tmp = a[child];
            a[child] = a[parsent];
            a[parsent] = tmp;
        }
        else
            break;
        child = parsent;
        parsent = (parsent - 1) / 2;//找到孩子的父亲
    }
}
// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
    //数据满了,需要扩容
    if (hp->_capacity == hp->_size)
    {
        HPDataType* tmp = (HPDataType*)realloc(hp->_a, sizeof(HPDataType)*hp->_capacity * 2);
        if (tmp == NULL)
        {
            printf("realloc is error");
            exit(-1);
        }
        hp->_a = tmp;
        hp->_capacity = hp->_capacity * 2;
    }
    //不需要扩容
    hp->_a[hp->_size++] = x;//插入数据,然后_size+1
    //一般数据都是放到数组尾得,建堆,向上调整,这里我们建大堆
    HeapJustUp(hp->_a, hp->_size - 1);
}
// 堆的判空
int HeapEmpty(Heap* hp)
{
    assert(hp);
    return hp->_size == 0;
}
//堆顶元素进行向下调整
void HeapJustDown(Heap* hp)
{
    //先假设当前待调整结点的左孩子结点存在
        //并且是待调整结点的左右孩子结点(不管右孩子结点存不存在,都这样假设)中值最大的
    int parent = 0;//根节点
    int child = parent * 2 + 1;//孩子结点
        while (child < hp->_size)
        {
            //child+1 < hp->_size说明右孩子结点确实存在
            //如果hp->_a[child] < hp->_a[child+1]也成立,那说明左右孩子结点中值最大的是右孩子结点
            if ((child + 1 < hp->_size) && hp->_a[child] < hp->_a[child + 1])
            {
                child = child + 1;
            }
            //如果a[child]>a[parent],则说明父节点比比左右孩子节点的值都要小,要置换
            if (hp->_a[child] > hp->_a[parent])
            {
                int tmp = hp->_a[parent];
                hp->_a[parent] = hp->_a[child];
                hp->_a[child] = tmp;
                parent = child;
                child = child * 2 + 1;
            }
            //如果a[child] <= a[parent],那就不需要进行调整
            else
            {
                break;
            }
        }
}
// 堆的删除,从堆顶开始删
void HeapPop(Heap* hp)
{
assert(hp);//断言为空为假的话就报错
assert(!HeapEmpty(hp));//断言如果不是空为真就执行
//首元素的的值与尾元素交换,然后删除尾元素
int tmp = hp->_a[0];
hp->_a[0] = hp->_a[hp->_size - 1];
hp->_a[hp->_size - 1] = tmp;
hp->_size--;
//堆顶元素进行向下调整
HeapJustDown(hp);
}
// 取堆顶的数据
HPDataTypeHeapTop(Heap* hp)
{
    assert(hp->_a);
    assert(!HeapEmpty(hp));//断言如果不是空为真就执行
    return hp->_a[0];
}
// 堆的数据个数
int HeapSize(Heap* hp)
{
    assert(hp);
    return hp->_size;
}
// 堆的销毁
void HeapDestory(Heap* hp)
{
    assert(hp);
    free(hp->_a);
    hp->_a = NULL;
    hp->_capacity = hp->_size = 0;
}

.c源文件(测试)

#include "Heap.h"
int main()
{
    Heap hp;
    HeapInit(&hp);//初始化
    HeapPush(&hp, 2);//插入数据
    HeapPush(&hp, 3);
    HeapPush(&hp, 4);
    HeapPush(&hp, 5);
    HeapPush(&hp, 6);
    HeapPush(&hp, 1);
    HeapPush(&hp, 66);
    HeapPush(&hp, 62);
    HeapPush(&hp, 4);
    HeapPush(&hp, 6);
    HeapPop(&hp);//删除数据,从堆顶开始删
   int tmp= HPDataTypeHeapTop(&hp);//取堆顶元素
    // 堆的数据个数
   int num = HeapSize(&hp);
   printf("建大堆,栈顶元素为:%d,堆的数据个数:%d\n", tmp,num);
    for (int i = 0; i < num; i++)
        printf("%d ", hp._a[i]);
    HeapDestory(&hp);// 堆的销毁
    return 0;
}

二、TOP—K问题

TOP—K问题:求数据集合中前k个最大的元素和最小的元素,一般情况数据非常大。
如:专业前10,世界500强,游戏中前100的活跃玩家,各种榜单等等。

1.用数据集合中前k个元素来建堆
求前k个最大的元素,建小堆
求前k个最小的元素,建大堆
2.用剩余的N—K个元素依次与堆顶元素来比较,根据规则替换堆顶元素,N—K个元素依次与堆顶元素比较完成后,堆里的K个元素就是所求的最小或者最大的元素。

例子:

问题:假设1亿个数,内存存不下,数据在文件中找出最大的前k个数。
1.读取文件的前10个数据,在内存数组中建立一个小堆。
2.在依次读取剩下数据,跟堆顶元素比较,大于堆顶的数据就替换它,然后向下调整。
3.所有数据读完,堆里面数据就是最大的前10个数。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define n 100000000
void  WeinteData()//写入1亿数据
{
    
FILE* fp = fopen("top.txt", "w");//打开文件,只写
if (fp == NULL)
{
    perror("fopen error");
    exit(-1);
}
srand((unsigned)time(0));
int arr[100] = { 0 };
for (int i = 0; i < n; i++)
{
    int x = rand() % 10000 + 1;
    fprintf(fp, "%d\n", x);
}
fclose(fp);//关闭文件
}
//两个数交换
void Swap(int* p, int* q)
{
    int tmp;
    tmp = *q;
    *q = *p;
    *p = tmp;
}
//向下调整算法
void JustDown(int* arr,int k,int parent)
{
    int child = parent * 2 + 1;//左孩子结点
    while (child < k)
    {
        if ((child + 1 < k) && arr[child] > arr[child + 1])//找到最小值的孩子结点
            child += 1;
        //如果arr[child]<arr[parent],则说明父节点比比左右孩子节点的值都要大,要置换
        if (arr[child] < arr[parent])
        {
            Swap(&arr[child], &arr[parent]);
           //让孩子结点为父节点,并且更新它的儿子结点
            parent = child;
            child = child * 2 + 1;
        }
        //如果a[child] <= a[parent],那就不需要进行调整
        else
        {
            break;
        }
    }
}
//建小堆
void HeapCreate(int* arr,int k)
{
    //最后一个结点的父亲结点开始向下调整
    for (int i = (k - 2) / 2; i >= 0; --i)
    {
        //向下调整算法
        JustDown(arr, k, i);
    }
}
void  FileTakeK()
{
    int k = 10;//10个数
    int* a = (int*)malloc(sizeof(int) * k);//开辟一块空间用来建堆
    if (a == NULL)
    {
        perror("malloc error:");
        exit(-1);
    }
    FILE* file = fopen("top.txt", "r");//打开top.txt文件,只读模式
    if (file == NULL)
    {
        perror("fopen error:");
        exit(-1);
    }
    for (int i = 0; i < k; i++)
    {
        fscanf(file, "%d", &a[i]);
    }
    printf("前10个数:\n");
    for (int i = 0; i < k; i++)
        printf("%d ", a[i]);
    //建小堆
    HeapCreate(a, k);
    printf("\n建完小堆里面的数:\n");
    for (int i = 0; i < k; i++)
        printf("%d ", a[i]);
    //把剩余的n-k个数与小堆的堆顶比较,比较完成后,堆里的数就是文件里最大的10个数
    int x = 0;
    while (fscanf(file, "%d", &x) != EOF)
    {
        //比堆顶数大,把这个数赋值给堆顶,然后向下调整
        if (x > a[0])
            a[0] = x;
        JustDown(a, k, 0);
    }
    printf("\n取最大的10个数:\n");
    for (int i = 0; i < k; i++)
        printf("%d ", a[i]);
    free(a);//释放内存
    fclose(file);//关闭文件
}
int main()
{
    //写入1亿数据
   WeinteData();
       //从文件中取出k个数,建小堆
    FileTakeK();
    return 0;
}

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

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

相关文章

网络互联与IP地址

目录 网络互联概述网络的定义与分类网络的定义网络的分类 OSI模型和DoD模型网络拓扑结构总线型拓扑结构星型拓扑结构环型拓扑结构 传输介质同轴电缆双绞线光纤 介质访问控制方式CSMA/CD令牌 网络设备网卡集线器交换机路由器总结 IP地址A、B、C类IP地址特殊地址形式 子网与子网掩…

2023.11.24 海豚调度,postgres库使用

目录 海豚调度架构dolphinscheduler DAG(Directed Acyclic Graph)&#xff0c; 个人自用启动服务 DS的架构(海豚调度) 海豚调度架构dolphinscheduler 注:需要先开启zookeeper服务,才能进行以下操作 通过UI进行工作流的配置操作, 配置完成后, 将其提交执行, 此时执行请求会被…

RHCE8 资料整理(八)

RHCE8 资料整理 第 8 篇 容器管理第 27 章 使用podman管理容器27.1 安装及配置podman27.2 镜像管理27.2.1 镜像的命名27.2.2 对镜像重新做标签27.2.3 删除镜像27.2.4 查看镜像的层结构27.2.5 导出和导入镜像 27.3 创建容器27.3.1 创建容器27.3.2 容器的生命周期27.3.3 创建临时…

web静态网页设计与制作-基于HTML+CSS+JS实现旅游摄影网站

web静态网页设计与制作&#xff0c;基于HTMLCSSJS实现精美的旅游摄影网站&#xff0c;拥有极简的设计风格&#xff0c;丰富的交互动效&#xff0c;让人眼前一亮&#xff0c;享受视觉上的体验。 我使用了基本的HTML结构来构建网页&#xff0c;并使用CSS样式进行美化设计&#xf…

【JavaWeb】HTMLCSSJavaScript

HTML&CSS&JavaScript 文章目录 HTML&CSS&JavaScript一、开发工具及在线帮助文档二、 HTML2.1 HTML&CSS&JavaScript的作用2.2 HTML基础结构2.3 HTML概念词汇解释2.4 HTML的语法规则2.5 常用标签 三、CSS3.1 引入方式3.2 CSS选择器3.3 CSS浮动3.4 CSS定位…

【电路笔记】-分压器

分压器 文章目录 分压器1、概述2、负载分压器3、分压器网络4、无功分压器4.1 电容分压器4.2 感应分压器 5、总结 有时&#xff0c;需要精确的电压值作为参考&#xff0c;或者仅在需要较少功率的电路的特定阶段之前需要。 分压器是解决此问题的一个简单方法&#xff0c;因为它们…

抽象类, 接口, Object类 ---java

目录 一. 抽象类 1.1 抽象类概念 1.2 抽象类语法 1.3 抽象类特性 1.4 抽象类的作用 二. 接口 2.1 接口的概念 2.2 语法规则 2.3 接口的使用 2.4 接口间的继承 2.5 抽象类和接口的区别 三. Object类 3.1 toString() 方法 3.2 对象比较equals()方法 3.3 hash…

人工智能-注意力机制之注意力提示

注意力提示 自经济学研究稀缺资源分配以来&#xff0c;人们正处在“注意力经济”时代&#xff0c; 即人类的注意力被视为可以交换的、有限的、有价值的且稀缺的商品。 许多商业模式也被开发出来去利用这一点&#xff1a; 在音乐或视频流媒体服务上&#xff0c;人们要么消耗注意…

【C语言】qsort的秘密

一&#xff0c;本文目标 qsort函数可以对任意类型数据甚至是结构体内部的数据按照你想要的规则排序&#xff0c;它的功能很强大&#xff0c;可是为什么呢&#xff1f; 我将通过模拟实现qsort函数来让你对这整个过程有一个清晰的深刻的理解。 二&#xff0c;qsort函数原型 v…

5-11一个球从100米自由落下

#include<stdio.h> int main(){double down100;double back down/2;int n;//次数for(n2;n<10;n){downdownback*2;backback/2; }printf("第10次落地经过%f米\n",down);printf("第10次反弹%f米\n",back);return 0;}

ArkTS-自定义组件学习

文章目录 创建自定义组件页面和自定义组件生命周期自定义组件和页面的区别页面生命周期(即被Entry修饰的组件)组件生命周期(即被Component修饰的组件) Builder装饰器&#xff1a;自定义构建函数按引用传递参数按值传递参数 BuilderParam装饰器&#xff1a;引用Builder函数 这个…

ruoyi-plus-vue部署

安装虚拟机 部署文档 安装docker 安装docker 安装docker-compose 可能遇到的错误 Failed to deploy ruoyi/ruoyi-server:5.1.0 Dockerfile: ruoyi-admin/Dockerfile: Cant retrieve im age ID from build stream 安装 vim 命令 yum install vim -y 修改文件 vim /etc/re…

Matlab通信仿真系列——离散信号和系统

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 本节目录 一、离散信号 1、离散信…

pairplot

Python可视化 | Seaborn5分钟入门(七)——pairplot - 知乎 (zhihu.com) Seaborn是基于matplotlib的Python可视化库。它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matplotlib的基础上进行了更高级的API封装&#xff0c;从而使得作图更加容易&#xff0c;不需…

喜报|AIRLOOK荣获“创客北京2023”创新创业大赛企业组三等奖

“创客北京2023”创新创业总决赛圆满落幕&#xff0c;埃洛克航空科技&#xff08;北京&#xff09;有限公司&#xff0c;&#xff08;以下统称AIRLOOK&#xff09;首次参赛即从几千家企业中脱颖而出&#xff0c;荣获大赛企业组三等奖。 自2016年开始&#xff0c;“创客北京”大…

U-Boot 之九 详解 Pinctrl 子系统、命令、初始化流程、使用方法

嵌入式芯片中,引脚复用是一个非常常见的功能,U-Boot 提供一个类似 Linux Kernel 的 Pinctrl 子系统来处理引脚复用功能。正好最近用到了这部分功能,需要移植 Pinctrl 驱动,特此记录一下学习过程。 架构 U-Boot 提供一个类似 Linux Kernel 的 Pinctrl 子系统,用来统一各芯…

内测分发平台如何保护用户隐私?

大家好&#xff0c;我是咕噜-凯撒&#xff0c;在软件开发的早期阶段&#xff0c;内测是一个至关重要的步骤。通过内测&#xff0c;开发者可以在产品正式上市前发现并修复bug&#xff0c;获取用户反馈优化用户体验。但是内测过程中往往会处理大量用户的敏感信息&#xff0c;尤其…

文献速递:非专业任务医生在审查X光片时受益于正确的可解释人工智能建议

非专业任务医生在审查X光片时受益于正确的可解释人工智能建议 01****文献速递介绍 本文主要探讨了人工智能&#xff08;AI&#xff09;在放射学中的应用&#xff0c;特别是在胸部X光片的诊断中AI临床决策支持系统&#xff08;AI-CDSS&#xff09;的作用。研究发现&#xff0c…

Java核心知识点整理大全10-笔记

往期快速传送门&#xff1a; Java核心知识点整理大全-笔记_希斯奎的博客-CSDN博客文章浏览阅读9w次&#xff0c;点赞7次&#xff0c;收藏7次。Java核心知识点整理大全https://blog.csdn.net/lzy302810/article/details/132202699?spm1001.2014.3001.5501 Java核心知识点整理…

多模态——使用stable-video-diffusion将图片生成视频

多模态——使用stable-video-diffusion将图片生成视频 0. 内容简介1. 运行环境2. 模型下载3. 代码梳理3.1 修改yaml文件中的svd路径3.2 修改DeepFloyDataFiltering的vit路径3.3 修改open_clip的clip路径3.4 代码总体结构 4. 资源消耗5. 效果预览 0. 内容简介 近期&#xff0c;…