zoukankan      html  css  js  c++  java
  • 哈希表

    看一个实际需求

    google公司的一个上机题:

    有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址..),当输入该员工的id,要求查找到该员工的所有信息.

    要求: 不使用数据库,尽量节省内存,速度越快越好=>哈希表(散列)

    哈希表的基本介绍

    散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

    应用实例

    • google公司的一个上机题:

    有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址..),当输入该员工的id,要求查找到该员工的所有信息.

    • 要求:
    1. 不使用数据库,,速度越快越好=>哈希表(散列)
    2. 添加时,保证按照id从低到高插入 [课后思考:如果id不是从低到高插入,但要求各条链表仍是从低到高,怎么解决?]
    3. 使用链表来实现哈希表, 该链表不带表头
          [
      : 链表的第一个结点就存放雇员信息]
    • 思路分析并画出示意图

    代码实现[增删改查(显示所有员工,按id查询)]

    • 代码实现

    package com.atguigu.chapter18.hashtab

     

    import scala.io.StdIn

    import util.control.Breaks._

     

    object HashTabDemo {

    def main(args: Array[String]): Unit = {

    //创建HashTab

    val hashTab = new HashTab(7)

    //写一个简单菜单

    var key = " "

    while (true) {

    println("add: 添加雇员")

    println("list: 显示雇员")

    println("find: 查找雇员")

    println("exit: 退出系统")

     

    key = StdIn.readLine()

    key match {

    case "add" => {

    println("输入id")

    val id = StdIn.readInt()

    println("输入名字")

    val name = StdIn.readLine()

    val emp = new Emp(id, name)

    hashTab.add(emp)

    }

    case "find" => {

    println("输入要查找的雇员的id")

    val id = StdIn.readInt()

    hashTab.findEmpById(id)

    }

    case "list" => {

    hashTab.list()

    }

    }

     

    }

    }

    }

     

    //创建Emp

    class Emp(eId: Int, eName: String) {

    val id = eId

    var name = eName

    var next: Emp = null

    }

     

    //创建EmpLinkedList

    class EmpLinkedList {

    //定义头指针, 这里head 我们直接回指向一个雇员

    var head: Emp = null

     

    //添加雇员方法

    //假定,添加的雇员的id是自增的,即雇员分配的id总是从小到大

    //找到链表的最后加入即可

    def add(emp: Emp): Unit = {

     

    //如果是第一个雇员

    if (head == null) {

    head = emp

    return

    }

    //定义辅助指针

    var cur = head

     

    breakable {

    while (true) {

    if (cur.next == null) {

    break()

    }

    cur = cur.next

    }

    }

    //这时cur 指向了链表的最后

    cur.next = emp

     

    }

     

    //遍历链表的方法

    def list(i: Int): Unit = {

    if (head == null) {

    println(s"${i}条链表为空")

    return

    }

     

    print(s"${i}条链表信息为 ")

    //定义辅助指针

    var cur = head

    breakable {

    while (true) {

    if (cur == null) {

    break()

    }

    //输出雇员信息

    printf(" => id=%d name=%s ", cur.id, cur.name)

    cur = cur.next //

    }

    }

    println()

    }

     

    //如果有,返回emp ,没有返回null

    def findEmpById(id: Int): Emp = {

    //遍历

    if (head == null) {

    println("链表为空,没有数据~~")

    return null

    }

     

    var cur = head

     

    breakable {

    while (true) {

    if (cur == null) {

    break()

    }

    if (cur.id == id) {

    break()

    }

    cur = cur.next

    }

    }

    return cur

    }

    }

     

    //size = 700

    class HashTab(val size: Int) { //size 会称为只读属性

    val empLinkedListArr: Array[EmpLinkedList] = new Array[EmpLinkedList](size)

    //初始化我们的empLinkedListArr 的各个元素

    for (i <- 0 until size) {

    empLinkedListArr(i) = new EmpLinkedList

    }

     

    def add(emp: Emp): Unit = {

    //返回该员工,应该加入到那条链表

    val empLinkedListNo = hashFun(emp.id)

    empLinkedListArr(empLinkedListNo).add(emp)

    }

     

    def list(): Unit = { //遍历整个hash

    for (i <- 0 until size) {

    empLinkedListArr(i).list(i)

    }

    }

     

    //编写一个findEmpById

    def findEmpById(id:Int): Unit = {

    //返回该员工,应该加入到那条链表

    val empLinkedListNo = hashFun(id)

    val emp = this.empLinkedListArr(empLinkedListNo).findEmpById(id)

    if (emp!=null) {

    printf(s"在第 $empLinkedListNo 找到id=%d name=%s ", id, emp.name)

    }else{

    printf("没有找到id %d ", id)

    }

    }

    //散列函数, 可以定制

    def hashFun(id: Int): Int = {

    id % size

    }

    }

     

    • 晚上完成的任务
    1. 能够写出一个hashtab
    2. 解决插入的雇员id 的顺序是从小到大, 而且不能重复

       

       

       

  • 相关阅读:
    CentOS中用top命令CPU负载
    Oracle文档阅读指南
    修改oracle用户密码永不过期
    让secureCRT以命令行方式启动图形界面
    .NET 2.0 SQL依赖注意事项(转载:原文《使用SQL Server 2005 Query Notification的几个注意事项》)
    SQL Server 2005服务状态管理工具
    一个常用的正则表达验证类
    解决TFS中MSBuild开发项目和开发编译中一些冲突(小技巧)
    ASP.NET 2.0 WebService中传递DataTable参考
    LightningFramework系列(各层详细设计类图)
  • 原文地址:https://www.cnblogs.com/shuzhiwei/p/11210072.html
Copyright © 2011-2022 走看看