Python篇——数据结构与算法(第二部分)

news2025/4/14 8:42:51

目录

二、排序算法(承接第一部分)

  1、堆排序算法——树的基础知识补充

   2、树的基本概念

   3、二叉树基础知识

(1)满二叉树

(2)完全二叉树

(3)二叉树的存储方式(表示方式)

 4、堆排序(大根堆、小根堆)

(1)堆排序过程

(2)构造堆

(3)挨个出数

5、堆排序——内置模块

6、堆排序应用——topk问题


二、排序算法(承接第一部分)

  1、堆排序算法——树的基础知识补充

  • 树是一种数据结构    比如:目录结构
  • 树是一种可以递归定义的数据结构
  • 树是由n个节点组成的集合
    • 如果n=0,那这是一颗空树
    • 如果n>0,那存在一个节点作为树的根节点,其他节点可以分为m个集合,每隔几何本身又是一棵树

   2、树的基本概念

  • 根节点、叶子结点(例如:B、C、H、P、Q等 不能分叉的节点)
  • 树的深度(高度):最深有几层,图中为4
  • 树的度(整个树,最大节点的度)、节点的度(F的度为3,分了3个叉)
  • 孩子节点(子节点)、父节点(E为I的父节点、I为E的孩子节点)
  • 子树

   3、二叉树基础知识

  • 度不超过2的树
  • 每个节点最多有两个孩子节点
  • 两个孩子节点被区分为左孩子节点和右孩子节点

(1)满二叉树

  • 一个二叉树,如果每一个层的节点数都达到最大值,则这个二叉树就是满二叉树

(2)完全二叉树

  •  叶节点只能出现在最下层和次下层,并且最下面一层的节点都集中在该层最左边的若干位置的二叉树

 (3)二叉树的存储方式(表示方式)

  • 链式存储
  • 顺序存储(堆排序)

 从图中我们需要找到两个问题:

  • 父节点和左孩子节点的编号下标有什么关系?
    • 0-1 1-3 2-5 3-7 4-9
    • i - 2i+1
  • 父节点和右孩子节点的编号下标有什么关系?
    • 0-2 1-4 2-6 3-8 4-10
    • i - 2i+2

 4、堆排序(大根堆、小根堆)

  • 堆:一种特殊的完全二叉树结构
  • 大根堆:一颗完全二叉树,满足任一节点都比其他孩子节点大
  • 小根堆:一颗完全二叉树,满足任一节点都比其他孩子节点小
  • 复杂度O(nlogn)

 

 

 (1)堆排序过程

  1. 建立堆(构造堆)
  2. 得到堆顶元素,为最大元素
  3. 去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整(向下调整)使堆有序
  4. 堆顶元素为第二大元素
  5. 重复步骤3,直到堆变空

Note:

如果不是取最后一个元素到堆顶,再进行向下调整,将会导致不是完全二叉树

(2)构造堆

 先对最后一个非叶子节点进行调整

 然后依次继续往上进行调整

(3)挨个出数

当堆构造好之后,在进行挨个出数

import random
import numpy as np


def sift(li, low, high):
    '''
    :param li: 列表
    :param low: 堆的第一个元素 (根)
    :param high: 堆的最后一个元素
    '''
    i = low  # 此时i指向第一层
    j = 2 * i + 1  # 左孩子
    temp = li[low]  # 暂存堆顶元素
    while j <= high:  # 只要j没有超过high
        # 有右孩子且与左孩子对比 (j + 1 <= high )表示右孩子没有越界
        if j + 1 <= high and li[j + 1] > li[j]:
            j = j + 1  # j指向右孩子
        if temp < li[j]:
            li[i] = li[j]
            i = j  # 往下走一层
            j = 2 * i + 1
        else:  # temp更大
            li[i] = temp  # 把temp放到某一层根部
            break
    else:
        li[i] = temp  # temp不在根节点,跳出循环后,temp放到叶子结点处


def head_sort(li):
    # 首先建堆
    n = len(li)
    # 寻找父亲节点 i-1//2  i=n-1
    for i in range((n - 2) // 2, -1, -1):
        # i 表示建堆的时候调整的部分根的下标
        sift(li, i, n - 1)
    # 建堆完成
    for i in range(n - 1, -1, -1):
        # i指向当前堆的最后一个元素
        li[0], li[i] = li[i], li[0]  # 堆顶元素和最后一个元素调整
        sift(li, 0, i - 1)  # 调整 (此时最后一个元素是i-1)


li = [i for i in range(100)]
random.shuffle(li)
print(li)
head_sort(li)
print(li)

5、堆排序——内置模块

  • Python内置模块——heapq(q:queue 优先队列)
  • 常用函数
    • heapify(x)(建堆——小根堆)
    • heappush(heap,item)(往里面加元素)
    • heappop(heap)往外弹出一个元素(最小的元素)
import heapq
import random

li = [i for i in range(100)]
random.shuffle(li)

print(li)
heapq.heapify(li)
print(li)

for i in range(100):
    print(heapq.heappop(li), end=',')

6、堆排序应用——topk问题

  • 现在有n个数,设计算法得到前k大的数。(k<n)
  • 解决思路:
    • 排序后切片 O(nlogn)
    • 冒泡、插入、选择排序O(kn)
    • 堆排序 O(nlogk)
  • 取列表前k个元素建立一个小根堆。堆顶就是目前第k大的数
  • 依次向后遍历原列表,对于列表中的元素,如果小于堆顶,则忽略该元素;如果大于堆顶,则将堆顶更换为该元素,并且对堆进行一次调整。
  • 遍历列表所有元素后,倒序弹出堆顶

例如:我们想到找到前5大的数字,我们先取前五个数字建立一个小根堆

 

 发现0不能放进去,只剩下7、2、4、5

 7比1大,所以把1换掉,在进行小根堆调整

 

 以此类推,最后

 

import random


def sift(li, low, high):
    '''
    :param li: 列表
    :param low: 堆的第一个元素 (根)
    :param high: 堆的最后一个元素
    '''
    i = low  # i,j指向层
    j = 2 * i + 1  # 左孩子
    temp = li[low]  # 暂存堆顶元素
    while j <= high:  # 只要j没有超过high
        # 有右孩子且与左孩子对比 (j + 1 <= high )表示右孩子没有越界
        if j + 1 <= high and li[j + 1] < li[j]:
            j = j + 1  # j指向右孩子
        if temp > li[j]:
            li[i] = li[j]
            i = j
            j = 2 * i + 1
        else:
            li[i] = temp  # 把temp放到某一层根部
            break
    else:
        li[i] = temp  # temp不在根节点,跳出循环后,temp放到叶子结点处


def topK(li, k):
    '''前k个元素'''
    heap = li[0:k]
    for i in range(k - 2 // 2, -1, -1):
        sift(heap, i, k - 1)
    # 1.建堆
    for i in range(k, len(li) - 1):
        if li[i] > heap[0]:
            heap[0] = li[i]
            sift(heap, 0, k - 1)
    # 2.遍历
    for i in range(k - 1, -1, -1):
        heap[0], heap[i] = heap[i], heap[0]
        sift(heap, 0, i - 1)
    # 3.返回前k个
    return heap


if __name__ == '__main__':
    li = [i for i in range(100)]
    print(li)
    random.shuffle(li)
    print(li)
    print(topK(li, 10))

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

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

相关文章

Python基础教程:第九章_Python异常模块与包

从现在开始&#xff0c;让我们来进入到新的章节&#xff0c; Python 异常模块与包的内容学习。本章节我们主要分为 6 部分进行讲解&#xff0c;包含了 Python 异常的相关操作以及 Python 的模块操作&#xff0c; Python 的包操作和安装第三方 Python 包的相关操作。 了解异常 …

【Netty】Netty ChannelHandler(四)

文章目录 前言一、ChannelHandler二、ChannelInboundHandler三、ChannelOutboundHandler四、ChannelDuplexHandler总结 前言 前两篇文章我们已经对Netty进行了简单的了解和架构设计原理的剖析。 相关文章链接如下&#xff1a; Netty 概述&#xff08;一&#xff09;Netty 架构…

在互联网寒冬,我们应届生应如何提高竞争力?

前言 在当前就业形势下&#xff0c;如何提高应届生在职场中的竞争力&#xff1f;具有哪些有效的方法和策略可供选择&#xff1f;这是一个备受关注的热点话题。哪些方面会对应届生的职场发展起到关键的推动和支撑作用呢&#xff1f;我也来讲一下我是打算如何提升自己的职场竞争力…

移动应用架构解析:用户界面层、业务逻辑层、数据访问层

移动应用的成功离不开一个良好的架构设计&#xff0c;在移动应用开发过程中&#xff0c;合理的层次结构对于应用的可维护性、可扩展性和可测试性至关重要。 移动应用的常见层次结构包括用户界面层、业务逻辑层、数据访问层&#xff0c;但是随着跨平台开发框架的不断发展&#…

【低压配电漏电继电器660V/LLJ-100H/AC220V 中性点漏电保护 JOSEF】

LLJ-F(S)系列漏电继电器 系列型号&#xff1a; LLJ-10F(S)漏电继电器LLJ-15F(S)漏电继电器LLJ-16F(S)漏电继电器 LLJ-25F(S)漏电继电器LLJ-30F(S)漏电继电器LLJ-32F(S)漏电继电器 LLJ-60F(S)漏电继电器LLJ-63F(S)漏电继电器LLJ-80F(S)漏电继电器 LLJ-100F(S)漏电继电器LLJ-120…

医学影像检测方法(B超、DR、CT、MRI)

医学影像检测方法 当涉及到医学影像学时&#xff0c;B超&#xff08;超声波检查&#xff09;、DR&#xff08;数字X射线摄影&#xff09;、CT&#xff08;计算机断层扫描&#xff09;和MRI&#xff08;磁共振成像&#xff09;是常见的诊断工具。以下是对这四种影像技术的基本概…

智能门锁揭开新方案:NV340D芯片打造更智能安全的语音解锁体验

智能门锁可以实现一键开锁、实时监控等功能&#xff0c;带来了更便捷、智能的门禁管理体验&#xff0c;逐渐成为人们生活中必不可少的一部分。近年来&#xff0c;随着人工智能技术的不断进步&#xff0c;越来越多的智能门锁开始集成语音控制系统&#xff0c;以提供更加方便的门…

人民大学与加拿大女王大学金融硕士项目——职场不会拒绝一个优秀的金融人才

在金融行业摸爬滚打多年的金融人&#xff0c;通过多年的拼搏与积累&#xff0c;已身处于一个相对舒适、从容的阶段&#xff0c;能沉淀下来再学习的金融人更是令人钦佩。在繁忙的工作之余他们依然保持对学业的热情&#xff0c;以应对瞬息万变的环境发展。人民大学与加拿大女王大…

Unity AssetBundle资源热更插件

Unity AssetBundle资源热更插件 CatAssetManager运行模式 - Package Only新建一个AssetBundle更改AssetBundle的Group分类更改AssetBundle的打包方式 构建规则 加密方式输出AssetBundle 运行模式 - Updateable查看我们热更的Bundle输出目录WebServer目录上传到服务器上选择热更…

u盘数据不见了能恢复吗?可以试试这3种方法

U盘通常体积小巧&#xff0c;存储容量较大&#xff0c;在现代社会中广泛使用。用户可以将各种类型的数据存储到U盘中&#xff0c;如照片、音乐、视频、文档等。但是使用过程中U盘数据无故消失了怎么办呢&#xff1f;在未备份u盘数据的情况下&#xff0c;u盘数据不见了能恢复吗&…

Jenkins发送邮件、定时执行、持续部署

集成Allure报告只需要配置构建后操作即可。但如果是web自动化&#xff0c;或是用HTMLTestRunner生成报告&#xff0c;构建后操作要选择Publish HTML reports&#xff0c;而构建中还要添加Execute system Groovy script插件&#xff0c;内容&#xff1a; System.setProperty(&q…

FT2000+ openEuler 20.03 LTS SP3 NUMA关闭 numa=off 对应用程序申请内存大小的影响,NUMA开关作用

测试程序 编写内存消耗程序 eatMemory.c #define _GNU_SOURCE#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <string.h> #include <unistd.h> #include <sys/time.h> #include <sched.h> #include <…

k8s入门实战(Pod-Label-Deployment)

k8s入门实战(Pod-Label-Deployment) Pod Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。 k8s架构图&#xff1a; k8s集群启动后&#xff0c;集群中各个组件也是以pod方式运行 [rootmaster ~]# kubectl get pod -n kube-system NAME …

RAR压缩文件如何转换成ZIP格式?

压缩文件有多种不同的格式&#xff0c;有时候因为需求不同&#xff0c;我们需要把RAR压缩文件转换成ZIP格式&#xff0c;那要如何操作呢&#xff1f;下面小编分享2种简单的方法。 方法一&#xff1a; 如果需要转换的RAR压缩包不是很多&#xff0c;我们可以直接把文件名字后缀“…

Spring Boot日志系统大揭秘:从零开始学习Spring Boot日志:常见问题解答和最佳实践

一. 关于 Spring Boot 日志的使用 Spring Boot 日志机制和工具用于记录应用程序的日志信息和追踪应用程序的执行过程。它集成了常用的日志框架&#xff0c;如 Log4j、logback、Java Util Logging等&#xff0c;并提供简单易用的配置方式&#xff0c;让开发人员可以方便地监控应…

【web基础与HTTP协议】

目录 一、Web基础1、域名1.1、域名的概述1.2、域名空间结构1.3、域名注册 2、网页的概念2.1、网页的概述2.2、网址的概述1、URI和URL的区别 二、HTML概述1、HTML 基本标签2、HTML 文件结构如下3、头标签中常用标签4、内容标签中常用标签 三、静态网页与动态网页3.1、目前常用的…

day4--链表内指定区间反转

迭代方法 1. 第m个节点的前一个节点pre和第n个节点&#xff1b; 2. 将第m个节点到第n个节点的链表部分反转&#xff1b; 3. 将pre节点的next指向反转后链表的头节点&#xff0c;将反转后链表的尾节点的next指向n1节点。 /*** struct ListNode {* int val;* struct ListNode…

hive如何实现oracle中复杂的update sql

hive3.1有update语法&#xff0c;但是目前没用还是采用的非事务表&#xff0c;所以我们用其他的办法来解决hive的update问题 简单的update oracle update student set namecclovezbf where id1 hive insert overwrite table student select id, if(id1,cclovezbf,name) n…

【正点原子STM32连载】 第十九章 窗口门狗(WWDG)实验摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十九…

Unreal Niagara粒子入门2

本次学习一下如何将Niagara参数暴露给蓝图、材质编辑器。 1.暴露参数给蓝图 首先在左侧Parmeters参数面板的User Exposed处创建参数&#xff1a; 然后将参数拖入到想要绑定的粒子字段上&#xff0c;例如这里绑定给粒子发射数&#xff1a; 在调用粒子时&#xff0c;可通过Se…