堆和前缀树

1 堆

1.1 堆结构
  1. 堆是用数组实现的完全二叉树结构
  2. 完全二叉树中如果每棵树的最大值都在顶部就是大根堆,最小值在顶部就是小根堆
  3. 堆结构的heapInsert就是插入操作,heapify是取出数组后进行堆结构调整的操作
  4. 优先级队列结构就是堆结构
public class Heap {// 大根堆结构public static class MyMaxHeap {private int[] heap;private final int limit;private int heapSize;public MyMaxHeap(int limit) {heap = new int[limit];this.limit = limit;heapSize = 0;}public boolean isEmpty() {return heapSize == 0;}public boolean isFull() {return heapSize == limit;}public void push(int value) {if(heapSize == limit) {throw new RuntimeException("Heap is full!");}heap[heapSize] = value;heapInsert(heap, heapSize++);}public int pop() {if(heapSize == 0) {throw new RuntimeException("Heap is empty!");}int ans = heap[0];swap(heap, 0, --heapSize);heapify(heap, 0, heapSize);return ans;}private void heapify(int[] heap, int index, int heapSize) {int left = index * 2 + 1;while (left < heapSize) {int largest = left + 1 > heapSize ? left : (heap[left] > heap[left + 1] ? left : left + 1);largest = heap[largest] > heap[index] ? largest : index;if (largest == index) {return;}swap(heap, index, largest);index = largest;left = index * 2 - 1;}}private void heapInsert(int[] heap, int index) {while (heap[index] > heap[(index - 1) / 2]) {swap(heap, index, (index - 1) / 2);index = (index - 1) / 2;}}private void swap(int[] heap, int i, int j) {int temp = heap[i];heap[i] = heap[j];heap[j] = temp;}}// 参照组:暴力public static class RightMaxHeap {private int[] heap;private final int limit;private int heapSize;public RightMaxHeap(int limit) {heap = new int[limit];this.limit = limit;heapSize = 0;}public boolean isEmpty() {return heapSize == 0;}public boolean isFull() {return heapSize == limit;}public void push(int value) {if(heapSize == limit) {throw new RuntimeException("Heap is full!");}heap[heapSize++] = value;}public int pop() {if(heapSize == 0) {throw new RuntimeException("Heap is empty!");}int maxIndex = 0;for (int i = 1; i < heap.length; i++) {if(heap[maxIndex] < heap[i]) {maxIndex = i;}}int ans = heap[maxIndex];heap[maxIndex] = heap[--heapSize];return ans;}}public static void main(String[] args) {// 写对数器验证堆结构int value = 1000;int limit = 100;int testTimes = 1000000;for (int i = 0; i < testTimes; i++) {int curLimit = (int)(Math.random() * limit) + 1;RightMaxHeap test = new RightMaxHeap(curLimit);MyMaxHeap my = new MyMaxHeap(curLimit);int curOpTimes = (int)(Math.random() * limit);for (int j = 0; j < curOpTimes; j++) {if (my.isEmpty() != test.isEmpty()) {System.out.println("Oops!");}if (my.isFull() != test.isFull()) {System.out.println("Oops!");}if (my.isEmpty()) {int curValue = (int)(Math.random() * value);my.push(value);test.push(value);}else if (my.isFull()) {if(my.pop() != test.pop()) {System.out.println("Oops!");}}else {if(Math.random() < 0.5) {int curValue = (int)(Math.random() * value);my.push(value);test.push(value);}else {if(my.pop() != test.pop()) {System.out.println("Oops!");}}}}}System.out.println("Finish!");}
}
1.2 改进的堆结构

为什么要改进?

  • 原始堆,传进去的东西比如Student类,我不修改这个类的任何值,用原始堆没问题。
  • 但是要是想把传进去的Student类修改一下,比如修改年龄或者id,那么就必须要使用改进的堆。
  • 改进的堆增加resign方法,可以在修改已经在堆里面的值之后还能形成堆结构。

改进的堆:

public class MyHeap<T> {private ArrayList<T> heap;private HashMap<T, Integer> indexMap;private int heapSize;private Comparator<? super T> comparator;public MyHeap(Comparator<? super T> comparator) {heap = new ArrayList<>();indexMap = new HashMap<>();heapSize = 0;this.comparator = comparator;}public boolean isEmpty() {return heapSize == 0;}public int getHeapSize() {return heapSize;}public void push(T value) {heap.add(value);indexMap.put(value, heapSize);heapInsert(heapSize++);}public T poll() {T ans = heap.get(0);int end = heapSize - 1;swap(0, end);heap.remove(end);indexMap.remove(ans);heapify(0, --heapSize);return ans;}public void resign(T value) {int valueIndex = indexMap.get(value);heapify(valueIndex, heapSize);heapInsert(valueIndex);}private void heapify(int index, int heapSize) {int left = index * 2 + 1;while (left < heapSize) {int largest = (left + 1 < heapSize) && (comparator.compare(heap.get(left + 1), heap.get(left)) < 0) ? left + 1 : left;largest = (comparator.compare(heap.get(largest), heap.get(index)) < 0) ? largest : index;if (largest == index) {return;}swap(largest, index);index = largest;left = index * 2 + 1;}}private void heapInsert(int index) {while (comparator.compare(heap.get(index), heap.get((index - 1) / 2)) < 0) {swap(index, (index - 1) / 2);index = (index - 1) / 2;}}private void swap(int i, int j) {T o1 = heap.get(i);T o2 = heap.get(j);heap.set(i, o2);heap.set(j, o1);indexMap.put(o1, j);indexMap.put(o2, i);}
}

学生类:

public class Student {private int id;private String name;private int age;private String address;public Student() {}public Student(int id, String name, int age, String address) {this.id = id;this.name = name;this.age = age;this.address = address;}/*** 获取* @return id*/public int getId() {return id;}/*** 设置* @param id*/public void setId(int id) {this.id = id;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}/*** 获取* @return address*/public String getAddress() {return address;}/*** 设置* @param address*/public void setAddress(String address) {this.address = address;}public String toString() {return "Student{id = " + id + ", name = " + name + ", age = " + age + ", address = " + address + "}";}
}

测试:

public class test {public static void main(String[] args) {Student s1 = new Student(1, "张三", 18, "西安");Student s2 = new Student(2, "李四", 20, "重庆");Student s3 = new Student(3, "王五", 19, "成都");Student s4 = new Student(4, "赵六", 22, "深圳");Student s5 = new Student(5, "钱七", 21, "北京");MyHeap<Student> myHeap = new MyHeap<>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o2.getId() - o1.getId();}});myHeap.push(s1);myHeap.push(s2);myHeap.push(s3);myHeap.push(s4);myHeap.push(s5);System.out.println(myHeap.isEmpty());System.out.println(myHeap.getHeapSize());System.out.println("====================");s1.setId(15);myHeap.resign(s1);while (!myHeap.isEmpty()) {System.out.println(myHeap.poll().toString());}}
}

2 前缀树

可以完成前缀相关的查询

2.1 前缀树的结构
  1. 单个字符串中的字符从前到后加到一颗多叉树上
  2. 字符放在路上,节点上有专属的数据项(常见的是pass和end)
  3. 所有样本都这样添加,如果没有路就新建,如果有路就复用
  4. 沿途所有的经过的节点的pass值加1,每个字符串结束时来到的节点的end值加1
// Node和TrieTree结合使用,Node2和TrieTree2结合使用。
// TrieTree2只能加入小写字符组成的字符串,有局限性
// TrieTree可以都加入
public class TrieTreeSearch {public static class Node {public int pass;public int end;public HashMap<Integer, Node> next;public Node() {pass = 0;end = 0;next = new HashMap<>();}}public static class TrieTree {private final Node root;public TrieTree() {root = new Node();}public void insert(String word) {if (word == null) {return;}Node node = root;node.pass++;char[] chars = word.toCharArray();int index = 0;for (char aChar : chars) {index = aChar;if (!node.next.containsKey(index)) {node.next.put(index, new Node());}node = node.next.get(index);node.pass++;}node.end++;}public void delete(String word) {if (search(word) != 0) {Node node = root;node.pass--;int index = 0;char[] chars = word.toCharArray();for (char aChar : chars) {index = aChar;if (node.next.containsKey(index)) {node = node.next.get(index);}node.pass--;}node.end--;}}public int search(String word) {return research(word).end;}public int prefixNum(String word) {return research(word).pass;}private Node research(String word) {if (word == null) {return new Node();}Node node = root;char[] chars = word.toCharArray();int index = 0;for (char aChar : chars) {index = aChar;if (!node.next.containsKey(index)) {return new Node();}node = node.next.get(index);}return node;}}public static class Node2 {public int pass;public int end;public Node2[] next;public Node2() {pass = 0;end = 0;next = new Node2[26];}}public static class TrieTree2 {private final Node2 root;// 无参构造public TrieTree2() {root = new Node2();}// 添加字符串public void insert(String word) {if (word == null) {return;}char[] chars = word.toCharArray();Node2 node = root;node.pass++;int index = 0;for (char aChar : chars) {index = aChar - 'a';if (node.next[index] == null) {node.next[index] = new Node2();}node = node.next[index];node.pass++;}node.end++;}// 查找字符串有多少个public int search(String word) {if (word == null) {return 0;}char[] chars = word.toCharArray();Node2 node = root;int index = 0;for (char aChar : chars) {index = aChar - 'a';if (node.next[index] == null) {return 0;}node = node.next[index];}return node.end;}// 删除字符串public void delete(String word) {if (search(word) != 0) {Node2 node = root;node.pass--;int index = 0;char[] chars = word.toCharArray();for (char aChar : chars) {index = aChar - 'a';if (--node.next[index].pass == 0) {node.next[index] = null;return;}node = node.next[index];}node.end--;}}// 有几个字符串前缀是wordpublic int prefixNum(String word) {if (word == null) {return 0;}char[] chars = word.toCharArray();Node2 node = root;int index = 0;for (char aChar : chars) {index = aChar - 'a';if (node.next[index] == null) {return 0;}node = node.next[index];}return node.pass;}}public static String generateRandomString(int strLen) {char[] ans = new char[(int) (Math.random() * strLen) + 1];for (int i = 0; i < ans.length; i++) {int value = (int) (Math.random() * 26);ans[i] = (char) (value + 97);}return String.valueOf(ans);}public static String[] generateRandomString(int arrLen, int strLen) {String[] ans = new String[(int) (Math.random() * arrLen) + 1];for (int i = 0; i < ans.length; i++) {ans[i] = generateRandomString(strLen);}return ans;}// 写对数器进行测试public static void main(String[] args) {int strLen = 20;int arrLen = 100;int testTimes = 1000000;for (int i = 0; i < testTimes; i++) {String[] strings = generateRandomString(arrLen, strLen);TrieTree my = new TrieTree();TrieTree2 test = new TrieTree2();for (String word : strings) {double decide = Math.random();if (decide < 0.25) {my.insert(word);test.insert(word);} else if (decide < 0.5) {my.delete(word);test.delete(word);} else if (decide < 0.75) {int ans1 = my.search(word);int ans2 = test.search(word);if(ans1 != ans2) {System.out.println("Oops!");}}else {int ans1 = my.prefixNum(word);int ans2 = test.prefixNum(word);if (ans1 != ans2) {System.out.println("Oops!");}}}}System.out.println("Finish!");}
}

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

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

相关文章

通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示(三)

通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示(三) 不使用base64编码方式传递 #include <ros/ros.h> #include <signal.h> #include <sensor_msgs/Image.h> #include <message_filters/subscriber.h> #include <message_filter…

【正点原子STM32连载】第五十九章 T9拼音输入法实验(Julia分形)实验 摘自【正点原子】APM32F407最小系统板使用指南

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

关于 token 和证书

关于 token 和证书 在网络检测中&#xff0c;Token通常是指一种特殊的令牌&#xff0c;用于在分布式系统中进行资源控制和访问管理。Token可以用于验证客户端的身份、限制客户端的访问权限以及控制客户端对某些资源的使用。 在网络检测中&#xff0c;Token通常用于以下几个方…

uniapp IOS从打包到上架流程(详细简单) 原创

​ 1.登入苹果开发者网站&#xff0c;打开App Store Connect ​ 2.新App的创建 点击我的App可以进入App管理界面&#xff0c;在右上角点击➕新建App 即可创建新的App&#xff0c;如下图&#xff1a; ​ 3.app基本信息填写 新建完App后&#xff0c;需要填写App的基本信息&…

SOLIDWORKS 2024新功能之CAM篇

SOLIDWORKS 2024 新功能 CAM篇目录概述 • 附加探测周期参数 • 反转切割的固定循环螺纹加工 • 包含装配体的零件的正确进给/速度数据 • Heidenhain 探测类型 • 2.5 轴特征向导中岛屿的终止条件 • 链接轮廓铣削操作的切入引导和切出引导参数 • 螺纹铣削操作的最小孔…

网络工程师眼中的网站安全:应对攻击的综合措施

作为一名专业的网络工程师&#xff0c;我们深知网站面临各种攻击威胁的现实。在构建网站安全的同时&#xff0c;综合运用技术手段和管理策略是至关重要的。在这篇文章中&#xff0c;我们将从网络工程师的视角出发&#xff0c;介绍如何解决网站被攻击的问题&#xff0c;并在其中…

飞凌嵌入式受邀参加「2023年电子工程师大会」并做主旨演讲

11月23日&#xff0c;华秋电子发烧友在深圳总部举办了「2023年电子工程师大会暨第三届社区年度颁奖」活动&#xff0c;邀请到了高校教授、企业创始人及高管、行业技术专家、电子工程师等众多嘉宾到场&#xff0c;呈现并传播了电子产业动态、最新技术、应用案例及开源硬件项目。…

C#FlaUI.UIA实现发送微信消息原理

一 准备 .NetFramework 4.8 FlaUI.UIA3 4.0.0 FlaUInspect V1.3.0 1下载FlaUInspect https://github.com/FlaUI/FlaUInspect FlaUInspect V1.3.0 百度网盘下载 2 NuGet 引用 flaUI.UIA3 4.0.0 二代码部分 1 引用FlaUI using FlaUI.Core; using FlaUI.Core.Automatio…

安防系统智能视频监控中出现画面异常该如何自检?

大家都知道&#xff0c;在当今社会&#xff0c;摄像头无处不在&#xff0c;除了常见的生活与工作场景中&#xff0c;在一些无法人员无法长期驻点场景&#xff0c;如野生动物监测、高空作业监控、高压电缆监控等场景&#xff0c;在这些地方安装摄像头就是为方便日常监控。但是由…

Odoo:行业领先的免费开源生产制造管理系统

产品生命周期管理 用 Odoo 产品数据管理解决方案加速产品开发 研究、开发和设计新产品或者重新设计现有产品是所有制造企业的活力之源&#xff0c;但很多企业的设计部门和工程部门却完全脱离 ERP 系统。这导致工程师需要耗费大量时间来回答企业中其他部门就产品状态、修改级别…

递归和动态规划的区别

时间复杂度方面&#xff1a; 递归会导致指数级别的时间复杂度&#xff0c;因为它会计算许多重复的子问题。 动态规划会存储子问题的结果&#xff0c;来降低复杂度&#xff0c;使其变成多项式级别。 自顶向下VS自底向上 递归采用自顶向下的方式&#xff0c;从原问题出发&#xf…

Course1-Week2-多输入变量的回归问题

Course1-Week2-多输入变量的回归问题 文章目录 Course1-Week2-多输入变量的回归问题1. 向量化和多元线性回归1.1 多维特征1.2 向量化1.3 用于多元线性回归的梯度下降法 2. 使梯度下降法更快收敛的技巧2.1 特征缩放2.2 判断梯度下降是否收敛2.3 如何设置学习率 3. 特征工程3.1 选…

看图说话:对脏读、不可重复度、幻读进行总结

1、脏读 「事务B」将 id 为 1 的用户 name 修改为“小卡”&#xff0c;事务未提交。「事务A」查询 id 为 1 的用户数据&#xff0c;此时 name 已为“小卡”。 2、不可重复度 「事务A」第一次读取 id 为 1 的用户&#xff0c;name 是 “卡卡”。「事务B」将 id 为 1 的用户 nam…

Sectigo

随着互联网的普及和技术的飞速发展&#xff0c;网络安全问题引起重视。这时&#xff0c;有一家名为Sectigo(原Comodo CA)的公司应运而生&#xff0c;致力于为企业和个人提供最先进、最可靠的网络安全解决方案。 Sectigo(原Comodo CA) 成立于2008年&#xff0c;总部位于美国加利…

数据分析策略

文章目录 我想对比不同完整度40%&#xff0c;50%&#xff0c;60%抽样计算来10min的TI序列&#xff0c;它们的差异与完整率的关系&#xff0c;告诉我怎么对比即可 了解您的分析目标后&#xff0c;我可以提供一个比较不同完整度&#xff08;40%&#xff0c;50%&#xff0c;60%&am…

启发式算法

什么是启发式算法&#xff1f;他们都有什么特点&#xff1f; 启发式算法是一类用于在大规模问题上寻找近似解的搜索算法。这些算法不保证找到全局最优解&#xff0c;但通常能够在合理的时间内找到一个较好的解决方案。启发式算法常用于解决组合优化问题&#xff0c;其中目标是…

《使用Python将Excel数据批量写入MongoDB数据库》

在数据分析及处理过程中&#xff0c;我们经常需要将数据写入数据库。而MongoDB作为一种NoSQL数据库&#xff0c;其具有强大的可扩展性、高性能以及支持复杂查询等特性&#xff0c;广泛用于大规模数据存储和分析。在这篇文章中&#xff0c;我们将使用Python编写一个将Excel数据批…

dos 命令移到文件夹

SET GenFolder C:\Users\administered\Desktop\t2\old_file set path1C:\Users\administered\Desktop\t1\crontab_master set path2C:\Users\administered\Desktop\t2\old_file if not exist %GenFolder% ( echo %GenFolder%目录不存在&#xff0c;已创建该目录&#x…

Linux python安装 虚拟环境 virtualenv,以及 git clone的 文件数据, 以及 下资源配置

根目录创建 venvs 文件夹 sudo mkdir /venvs 进入 /venvs 目录 cd /venvsp 创建虚拟环境&#xff0c;前提要按照 python3 安装 的 命令 sudo apt install python3 sudo python3 -m venv 虚拟环境名 激活虚拟环境 source /venvs/zen-venv/bin/activate 安装flask pip install fl…

探究Kafka原理-2.Kafka基本命令实操

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44…