【时空权衡】

目录

  • 知识框架
  • No.0 时空权衡
    • 一、基本思想
  • No.1 计数排序
    • 一、比较计数
    • 二、分布计数
  • No.2 散列法
    • 一、开散列(分离链)
    • 二、闭散列(开式寻址)

知识框架

No.0 时空权衡

一、基本思想

其实时空权衡:是指在算法的设计中,对算法的时间和空间作出权衡。

本文主要是是用空间来换时间的。(应该是这样吧)

  1. 对问题的部分或全部输入预处理,然后对获得的额外信息进行存储,以加速后面问题的求解——输入增强
  2. 使用额外空间来实现更快和(或)更方便的数据存取——预构造。(感觉像是存放脑信息)

以常见的以空间换取时间的方法有:主要是两个方法:然后代表。

  1. 输入增强
    1. 计数排序
    2. 字符串匹配中的输入增强技术
  2. 预构造
    1. 散列法
    2. B树

那面是计数排序和散列法的详细介绍:

No.1 计数排序

一、比较计数

针对待排序列表中的每个元素,算出列表中小于该元素的元素个数,并把结果记录在一张表中。

  1. 这个“个数”指出了元素在有序列表中的位置(小于的个数也差不多就是前面有几个咯)
  2. 可以用这个信息列表的元素排序,这个算法称为“比较计数”

步骤:思路:针对待排序列表中的每一个元素,算出列表中小于该元素的元素个数,把结果记录在一张表中。

拿数组中的62来说,比之小的有3个,那么其就在数组的3位置;。

在这里插入图片描述

代码如下:

{	//用比较计数法对数组排序	
	for(i=0;i < n;i++)    Count[i]=0;
	for(i=0;i < n-1;i++) 
        for(j=i+1;j < n; j++)
			if(A[i]<A[j]) Count[j]++;
			else  Count[i]++;
   for(i=0;i < n;i++) S[Count[i]] = A[i];
	return  S;
}	

复杂度效率问题:O(n^2)

  1. 该算法执行的键值比较次数和选择排序一样多,
  2. 并且还占用了线性数量的额外空间,所以几乎不能来做实际的应用
  3. 但在一种情况下还是卓有成效的——待排序的元素值来自一个已知的小集合
    1.

二、分布计数

分布计数是一种特殊方法,用来对元素取值来自于一个小集合的列表排序。

待排序的数组元素有一些其他信息和键值相关(不能改写列表的元素)

因为这种频率的累积和在统计中称为分布,这个方法也称为“分布计数”。

这是一个线性的算法,它的时间效率类型比合并排序、快速排序、堆排序等基于比较的排序算法都要好。

由于分布计数排序要使用一个额外的数组D,而数组D的长度取决于待排序数组中数据的范围,

因此分布计数排序对于数据范围很大的数组,需要大量的内存。

  1. 将A数组元素复制到一个新数组S[0…n-1]中
  2. A中元素的值如果等于最小的值L,就被复制到S的前D[0]个元素中,即位置0到D[0]-1中
  3. 值等于L+1的元素被复制到位置D[0]至(D[0]+D[1])-1,以此类推。

步骤:

  1. 比如数据是: 13 11 12 13 12 12 它们的值从11到13,因此需要一个额外的数组D[0…2],用来存放分布值。

  2. 首先需要整理表格内容:首先计算出频率值,就是每个元素重复的次数。

  3. 然后计算出分布值,分布值指出了在最后的有序数组中,它们的元素最后一次出现时的正确位置

  4. 如果从0到n-1建立数组下标,为了得到相应的元素位置,分布值必须减1。当然表格里面的分布值还是没有-1的。

  5. 分布值表示的是最后一次出现的正确位置,11的个数是一个,因为11是第一个元素,那么11的分布值就等于频率。12的个数有三个,那么它最后出现的位置就是它前面一个数的分布值加上自己出现的频率,也就是3+1=4。而13的分布值就等于12的分布值加上自己出现的频率,就是4+2=6。

    1. 数组值111213
      频率132
      分布值146
  6. 得到分布值后,就可以对下面的数组进行排序了,为方便处理,我们从数组的最后一个元素开始

  7. 最后的值是12,而它的分布值是4,我们就把这个12放在数组S的第4个位置上,也就是S[3],(数组从0开始编号)。然后把12的分布值减1,代表下次再遇到12,就只能放在第三个位置上面了。依次类推。得到下面的内容。

  8. 然后处理数组的下一个元素(从右边数),再碰到12,此时12的分布值是3,于是把12放到S的第3个位置上,再将分布值减1。

  9. 接着遇到的13,它的分布值是6,于是将13放在数组S的最后一个位置,再将分布值减1.

  10. 直到循环n次后,算法结束,排序完成

  11. 得到这样的内容

在这里插入图片描述

代码:

{	//分布计数法对有限范围整数的数组排序
	for(j=0;j <= u-L ;++i)  D[j]=0;//初始化频率数组
	for(i=0;i < n; ++i)      D[A[i]-L]++;//计算频率值
	for(j=1;j <= u-L ; ++j)  D[j]+=D[j-1];//重用分布
   for(i=n-1;i>=0;--i){
		j = A[i] – L ;
		S[D[j]-1] = A[i];
		D[j]--;
	}   
	return  S;
}	

效率分析

  1. 假设数组值的范围是固定的,那么这是一个线性效率的算法
  2. 但重点是:除了空间换时间之外,分布技术排序的这种高效是因为利用了输入列表独特的自然属性!

No.2 散列法

散列是一种非常高效的实现字典的方法,分为开散列和闭散列,其中必须采用碰撞解决机制。

  1. 一种非常高效的实现字典的方法

    1. 字典是一种抽象数据类型,即一个在其元素上定义了查找、插入和删除操作的元素集合
    2. 集合的元素可以是容易类型的,一般为记录
  2. 散列法的基本思想是:把分布在一个称为散列表的一维数组H[0…m-1]中。

    1. 可以通过对每个键计算某些被称为“散列函数”的预定义函数h的值,来完成这种发布
    2. 该函数为每个键指定一个称为“散列地址”的位于0到m-1之间的整数
  3. 散列函数:散列函数需要满足两个要求:

  4. 散列函数需要把键在散列表的单元格中尽可能均匀地分布(所以m常被选定为质数,甚至必须考虑键的所有比特位)

  5. 散列函数必须容易计算

  6. 散列的主要版本:

    1. 开散列(分离链)
    2. 闭散列(开式寻址)

一、开散列(分离链)

  1. 键被存储在附着于散列表单元格上的链表中,散列地址相同的记录存放于同一单链表中
  2. 查找时:首先根据键值求出散列地址,然后在该地址所在的单链表中搜索;

查找效率分析:

  1. 查找效率取决于链表的长度
  2. 而这个长度又取决于字典和散列表的长度以及散列函数的质量(双方的长度和散列函数的选取)
  3. 若散列函数大致均匀地将n个键分布在散列表的m个单元格中,每个链表的长度大约相当于n/m个
  4. 比率α=n/m称为散列表的负载因子
    1. 一般我们希望负载因子不要和1差太远。
    2. 如果太小就意味着有很多空链表;如果太大就使链表太长;
    3. 如果和1相差无几的话就能到达惊人的效率:平均只要一两次比较就能完成查找
  5. 成功查找和不成功查找中平均需检查的个数S和U:S≈1+α/2;U=α;
  6. 之所以能得到这样卓越的效率,不仅是因为这个方法本身就非常精巧,而且也是以额外的空间为代价的
  7. 插入和删除在平均情况下都是属于Θ(1)

形式展示:在开散列中,键被存放于散列表单元的链表中。

比如:如下的键值A,FOOL,AND,HIS,MONEY,ARE,SOON,PARTED

AFOOLANDHISMONEYARESOONPARTED
散列地址196107111112

在这里插入图片描述

二、闭散列(开式寻址)

如下:

  1. 所有的键值都存储在散列表本身中,而没有使用链表(这表示表的长度m至少必须和键的数量一样大)
  2. 解决碰撞:有多种方法,例如线性探测
  3. 插入和查找:简单而直接
  4. 删除操作:“延迟删除”,用一个特殊的符号来标记曾被占用过的位置,以把它们和那些从未被只用过的位置区别开来
  5. 成功查找和不成功查找中平均需检查的个数S和U:S≈(1+1/(1-α))/2;U=(1+1/();
  6. 解决冲突:

形式展示:在闭散列中,所有键都存储在散列表本身,

采用线性探查解决冲突,即碰撞发生时,如果下一个单元格空,则放下一个单元格,如果不空,则继续找到下一个空的单元格,如果到了表尾,则返回到表首继续。

比如:如下的键值A,FOOL,AND,HIS,MONEY,ARE,SOON,PARTED

AFOOLANDHISMONEYARESOONPARTED
散列地址196107111112
0123456789101112
AFOOL
AFOOL
AANDFOOLHIS
AANDFOOLHIS
AANDMONEYFOOLHIS
AANDMONEYFOOLHISARE
AANDMONEYFOOLHISARESOON
PAETEDAANDMONEYFOOLHISARESOON

闭散列的查找和插入操作是简单而直接的,但是删除操作则会带来不利的后果。

比起分离链,线性探查的数学分析是复杂得多的问题。

对于复杂因子为α的散列表,成功查找和不成功查找必须要访问的次数分别为:

S≈ (1+1/(1- α))/2 U ≈(1+1/(1- α)2)/2

散列表的规模越大,该近似值越精确

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

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

相关文章

进程信号(Linux)

进程信号 信号入门身边的信号进程信号 产生信号终端按键产生信号调用系统函数向目标进程发信号killraiseabort 硬件异常产生信号由软件条件产生信号 阻塞信号信号其他相关常见概念在内核中的表示sigset_t信号集操作函数sigprocmasksigpending 捕捉信号内核如何实现信号的捕捉si…

分布式简要说明

1.分布式简要说明 《分布式系统原理与范型》定义&#xff1a; 分布式系统是若干独立计算机的集合&#xff0c;这些计算机对于用户来说就像单个相关系统。 分布式系统 (distributed system) 是建立在网络之上的软件系统。 随着互联网的发展&#xff0c;网站应用的规模不断扩…

SAP-QM-物料主数据-质量管理视图字段解析

过账到质检库存&#xff1a;要勾选&#xff0c;否则收货后库存不进入质检库存HU检验&#xff1a;收货到启用HU管理的库位时产生检验批&#xff0c;例如某个成品物料是收货到C002库位&#xff0c;该库位启用了HU管理&#xff0c;那么此处要勾选。但是如果勾选了&#xff0c;却收…

04.hadoop上课笔记之java编程和hbase

1.win查看服务 netstat -an #linux也有#R数学建模语言 SCALAR 2.java连接注意事项,代码要设置用户 System.setProperty("HADOOP_USER_NAME", "hadoop");3.伪分布式的好处(不用管分布式细节,直接连接一台机器…,适合用于学习) 4.官方文档 查看类(static |…

Python期末复习题库(下)——“Python”

小雅兰期末加油冲冲冲&#xff01;&#xff01;&#xff01; 1. (单选题)下列关于文件打开模式的说法,错误的是( C )。 A. r代表以只读方式打开文件 B. w代表以只写方式打开文件 C. a代表以二进制形式打开文件 D. 模式中使用时,文件可读可写 2. (单选题)下列选项中,以追加…

webpack的使用

一、什么是webpack&#xff1f; webpack是一个前端构建工具&#xff0c;目前比较主流的构建工具&#xff0c;自定义的模块比较多。 二、应用场景 vue、react、angular 都可以通过webpack构建全部可供访问的页面数量不超过500个 三、安装 通过npm方式在项目根目录下执行命令…

htmlCSS-----CSS选择器(下)

目录 前言&#xff1a; 2.高级选择器 &#xff08;1&#xff09;子代选择器 &#xff08;2&#xff09;伪类选择器 &#xff08;3&#xff09;后代选择器 &#xff08;4&#xff09;兄弟选择器 相邻兄弟选择器 通用兄弟选择器 &#xff08;5&#xff09;并集选择器 &am…

【JavaSE】Java基础语法(二十六):Collection集合

文章目录 1. 数组和集合的区别2. 集合类体系结构3. Collection 集合概述和使用【应用】4. Collection集合的遍历【应用】5. 增强for循环【应用】 1. 数组和集合的区别 相同点 都是容器,可以存储多个数据不同点 数组的长度是不可变的,集合的长度是可变的 数组可以存基本数据类型…

基于Yarn搭建Flink

基于Yarn搭建Flink 1. 概述 1.1 Yarn 简介 Apache Hadoop YARN是一个资源提供程序&#xff0c;受到许多数据处理框架的欢迎。Flink服务被提交给 YARN 的 ResourceManager&#xff0c;后者再由 YARN NodeManager 管理的机器上生成容器。Flink 将其 JobManager 和 TaskManager…

python爬虫笔记

Python爬虫笔记 一. Urllib 1. 基础请求 指定url请求返回值解码返回结果的一些操作 import urllib.request as req # 定义一个url url http://www.baidu.com# 发送请求获得相应 res req.urlopen(url)# read返回字节形式的二进制数据,需要用指定编码来解码 content res.r…

vue的虚拟DOM

vue的虚拟DOM 什么是虚拟DOM 虚拟DOM提供了一个与平台无关的抽象层&#xff0c;将应用程序的界面表示抽象为一个虚拟的DOM树。这意味着开发人员可以使用相同的代码和逻辑来描述应用程序的用户界面&#xff0c;而不需要关心具体的平台实现细节。虚拟DOM允许开发人员使用一种统…

Linux命令

准备工作 安装centos7 在镜像网下载DVD.iso或者DVD.torrent&#xff08;bit种子&#xff09;。在VMware中配置相应的信息&#xff0c;并引入iso文件&#xff0c;以便后续安装。local中&#xff1a;选择语言和时区上海software中&#xff1a;选择安装软件的内容&#xff0c;可…

基于多动作深度强化学习的柔性车间调度研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

通过location实现几秒后页面跳转

location对象属性 location对象属性 返回值location.href获取或者设置整个URLlocation.host返回主机&#xff08;域名&#xff09;www.baidu.comlocation.port 返回端口号&#xff0c;如果未写返回空字符串location.pathname返回路径location.search返回参数location.hash返回…

Apache网页与安全优化

一、Apache网页优化 在企业中&#xff0c;部署Apache后只采用默认的配置参数&#xff0c;会引发网站很多问题&#xff0c;换言之默认配置是针对以前较低的服务器配置的&#xff0c;以前的配置已经不适用当今互联网时代。为了适应企业需求&#xff0c;就需要考虑如何提升Apache…

遗传算法(Genetic Algorithm)

本文为阅读《遗传算法原理及应用》的笔记和心得 ISBN&#xff1a;7-118-02062-1 遗传算法简介 遗传算法是模拟生物在自然环境中的遗传和进化过程中而形成的一种自适应全局优化概率搜索算法 总的来说&#xff0c;求最优解解或近似最优解的方法主要有三种&#xff1a;枚举法、启…

数据库系统的结构

数据库模式基本概念 1.型与值 型&#xff1a;对某一类数据的结构和属性的说明。值&#xff1a;型的具体赋值。 2.模式和实例 模式&#xff1a; 数据库中全体数据的逻辑结构和特征的描述。简单来说就是数据的定义和描述。模式是元数据&#xff0c;数据是变化的&#xff0c;模…

Linux:/dev/tty、/dev/tty0 和 /dev/console 之间的区别

在Linux操作系统中&#xff0c;/dev/tty、/dev/tty0和/dev/console是三个特殊的设备文件&#xff0c;它们在终端控制和输入/输出过程中扮演着重要的角色。尽管它们看起来很相似&#xff0c;但实际上它们之间存在一些重要的区别。本文将详细介绍这三个设备文件之间的区别以及它们…

【C++系列P3】‘类与对象‘-三部曲——[基础知识](1/3)

前言 大家好吖&#xff0c;欢迎来到 YY 滴 C系列 &#xff0c;热烈欢迎&#xff01; 【 类与对象-三部曲】的大纲主要内容如下&#xff1a; 如标题所示&#xff0c;本章是【 类与对象-三部曲】三章中的第一章节——基础知识章节&#xff0c;主要内容如下&#xff1a; 目录 一.…

如何用Python写个网页爬取程序

如何用Python写个网页爬取程序 准备开发工具安装PythonPython安装pipPip安装爬取插件准备好网页地址代码实现 准备开发工具 额&#xff0c;作者用的是vscode。具体怎么安装自行百度哈&#xff0c;这个都不会建议就不要学爬取了。 不忍心藏着也&#xff0c;给你个方法吧 vsc…
最新文章