zoukankan      html  css  js  c++  java
  • 算法介绍(直接寻址表、hash,MD5,贪心算法、动态规划)

    直接寻址表

    • 直接寻址表,定义了一个所有关键字的域集合U,根据这个U生成一个包含所有域值的列表T
    • 直接寻址技术优点:
      • 当数据量较小时,相对简单有效
    • 直接寻址技术缺点:
      • 当U很大时,建立列表T,所消耗的内存空间非常大
      • 如果U非常大,而实际出现的key非常少,这样就对空间造成了极大的浪费
      • 当关键字key不是数字的时候就无法处理了

    hash(哈希)

    • 基本概念:hash,也称作散列、杂凑或者哈希,是一种线性表的存储结构。哈希表由一个直接寻址表和一个哈希函数组成,哈希函数h()将元素的关键字k处理得到唯一的存储元素的位置信息。能把任意长度的输入,通过hash算法转化为固定长度的输出,是一种压缩映射。最大的特点就是从无法从结果推算出输入内容,所以称之为不可逆算法。本质上是通过哈希函数计算数据存储位置的数据结构。
    • hash表示对直接寻址表的改进,具体的
      • 构建大小为m的寻址表T,[0,1,2,3,……,m-1]
      • 将关键字为k的元素,放置在T中的h(k)所指定的位置上
      • h() 是哈希函数,将U中的key映射到寻址表T中
    • 哈希特性:
      • 过程不可逆,即拿到结果也不能反解出输入值是多少
      • 计算速度极快
    • 哈希表存在的问题:
      • 哈希冲突
        • 由于关键字的数量是无限的,而hash创建的寻址表T是有限的,所以必定会出现存储位置冲突或重复,即当h(k)和h(k1)的值相同时,两个值的存储位置是冲突的。
        • 哈希冲突的解决方式:
          • 方式一:开放寻址法,如果哈希函数返回的位置已经有值,则继续向后探寻新的位置来存储这个值。而继续向下探寻位置的方法有
            • 线性探查,如果位置i被占用,则向下探查i+1,i+2 ……直至空位置
            • 二次探查,如果位置i被占用,则依次探查i+1^2,i+2^2……直至空位置
            • 二度哈希:有n个哈希函数,等使用第一个哈希函数h1,发生冲突时,依次尝试使用h2,h3……
          • 方式二:拉链法,哈希表每个位置都链接一个链表,当冲突发生时,冲突的元素被加到该位置链表后面
    • 常见的哈希函数:
      • 除法哈希:  h(k)=k%m
      • 乘法哈希:h(k) = floor(m*(A*key%1))   
      • 全域哈希:h(k) = ((a*key+b) mod p) mod m    a,b =1,2,……p-1
    • hash表的基本操作:
      • insert(key,value) 插入键值对
      • get(key) 根据键取值
      • delete(key)  删除键值对
    • 主要的应用方向:
      • python等语言的字典、集合等数据类型就是基于hash实现的
      • 密码,很多密码都是基于hash构造出来的
      • 可以用于检测文件的一致性
      • 用于数字签名
      • MD5,SHA-1,SHA-2
    • hash表的简单实现(拉链法,单链表)
      •   1 """
          2 使用链表,实现hash。构建一个类似于集合的hash表
          3 """
          4 class LinkList(object):
          5     """
          6     对链表的进一步封装
          7     """
          8     class Node(object):
          9         """
         10         链表的节点类
         11         """
         12         def __init__(self,item):
         13             self.item = item
         14             self.next = None
         15 
         16     class LinkListIterator(object):
         17         """
         18         将链表转为迭代器类
         19         """
         20         def __init__(self,node):
         21             self.node = node
         22 
         23         def __next__(self):
         24             if self.node:
         25                 cur_node = self.node
         26                 self.node = cur_node.next
         27                 return cur_node.item
         28             else:
         29                 raise StopIteration
         30 
         31         def __iter__(self):
         32             return self
         33 
         34     def __init__(self,iterable = None):
         35         self.head = None
         36         self.tail = None
         37         if iterable:
         38             self.extend(iterable)
         39 
         40     def extend(self,iterable):
         41         for obj in iterable:
         42             self.append(obj)
         43 
         44     def append(self,obj):
         45         """
         46         使用尾插法,进行插入
         47         :param obj:
         48         :return:
         49         """
         50         s = LinkList.Node(obj)  # 链表节点创建
         51         if not self.head:
         52             self.head = s
         53             self.tail = s
         54         else:
         55             self.tail.next = s
         56             self.tail = s
         57 
         58     def find(self,obj):
         59         for val in self:
         60             if val == obj:
         61                 return True
         62         else:
         63             return False
         64 
         65     def __iter__(self):
         66         return self.LinkListIterator(self.head)
         67 
         68     def __repr__(self):
         69         return "<<"+",".join(map(str,self)) +">>"
         70 
         71 
         72 class HashTable(object):
         73     """
         74     实现集合的部分功能,不可重复,可查询
         75     """
         76     def __init__(self,size=101):
         77         self.size = size
         78         self.T = [LinkList() for _ in range(self.size)]  # 创建寻址表
         79 
         80     def h_func(self,k):
         81         """
         82         哈希函数
         83         :param k:
         84         :return:
         85         """
         86         return k%self.size
         87 
         88     def find(self,k):
         89         """
         90         根据给定的k值在现有的范围中查找是否存在
         91         :param k:
         92         :return:
         93         """
         94         hash_num = self.h_func(k) # 获取给定数值的hash值
         95         return self.T[hash_num].find(k)
         96 
         97 
         98     def insert(self,k):
         99         """
        100         实现插入前去重
        101         :param k:
        102         :return:
        103         """
        104         if self.find(k):
        105             print('element is exist')
        106         else:
        107             hash_num = self.h_func(k)  # 获取插入的值的hash值
        108             self.T[hash_num].append(k)
        109 
        110 
        111 my_set = HashTable()
        112 my_set.insert(1)
        113 my_set.insert(2)
        114 my_set.insert(102)
        115 print(my_set.T)
        116 print(my_set.find(2))
        View Code
    • Python中hash的使用,通过调用hashlib模块实现

      • 通过hashlib调用不同的hash函数,实现不同数据的不同处理。

        • 实例化hash对象,hash_obj = hash.hash函数类型()   ,实例化过程中,可以通过添加参数,实现加盐操作

        • 常见的hash函数类型有md5,sha1,sha224,sha256,sha384,sha512等 

        • hash_obj.update( 处理内容 ) 注意,需要进行处理的内容必须是bytes类型
        • hash_obj.digest()  ,返回当前已处理内容的hash值(内容摘要),返回值二进制数据
        • hash_obj.hexdigest(),返回当前已处理内容的hash值(内容摘要),返回值是十六进制数据

      

     MD5

    • 曾是密码学中常用的hash函数
    • 主要特点:
      • 同样的消息MD5相同
      • 可以快速计算出任意长度的消息的MD5
      • 除非暴力美剧,否则基本不能从哈希值反推出消息本身
      • 两条消息之间,即使是只有微笑差别,其MD5应该是完全不同,不相关的
      • 在有限时间内,无法人工构建出MD5值相同的两个不同的信息
    • 应用举例:
      • 验证文件,例如是否是相同的文件,上传下载文件的完整性、云盘秒传等

     SHA-1,SHA-2

    • SHA-1和MD5都是曾经在密码学上经常用到的hash算法,但是目前,较为常用的是SHA-2
    • SHA-2算法包含,SHA-224,SHA-256,SHA-384,SHA-512,SHA-512/224,SHA-512/256等算法,穷224,256,384与512代表的是哈希值的长度

    贪心算法

    • 贪心算法也叫做贪婪算法,基本思路是在求解过程中,只考虑当前步骤的最优选择,不从整体上进行考虑。贪心算法重点是放在了求解局部最优解,但是,很多情况下,贪心算法执行出来的结果也是整体上的最优解。
    • 特点:解决的是部分最优化问题
    • 实例:
      • 找零问题
      • 背包问题
      • 数字拼接问题
      • 活动选择问题

    动态规划

    • 动态规划关键点是找到关系到最优子结构的递推式,最优子结构
    • 最优子结构,如果可以将最优解的规模为n的问题,划分为规模更小的最优解问题,这些子问题是独立求解的,通过组合子问题的最优解可以得到原整体问题的最优解,就可以称之为最优子结构。
    • 动态规划特征
      • 最优子结构,最优解问题中,原问题的最优解中涉及到多个子问题
      • 重叠子问题
    • 实例:
      • 钢条切割问题
      • 最长公共子序列
        • 子序列与子串,子序列是在某个序列中删除若干元素后得到的序列,与子串的区别是,子序列的元素在原序列中,不一定是相邻的,而子串的元素在原序列中一定是相邻的
        • 应用场景
          • 字符串相似度(模糊查询)
          • 内容相似比对
          • 基因测序等

      

  • 相关阅读:
    当前日期减去TIMESTAMP(6)日期
    java 对象之间的复制
    根据用户编码分组。根据日期倒序排序只取其中一条
    最大权闭合子图
    CodeForces-1082E Increasing Frequency
    CodeForces-1082D Maximum Diameter Graph
    HDU 6446 -- Tree and Permutation
    python学习之函数(二)
    python学习之函数(一)
    python学习之文件操作
  • 原文地址:https://www.cnblogs.com/jesse1/p/11057016.html
Copyright © 2011-2022 走看看