模拟hashtable表

简介

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

涉及的方法

add :普通添加节点的方法
sadd:顺序添加的方法
List: 显示全部节点信息
remove:根据id删除某个节点
find:查找某个节点 exit:退出程序

散列函数

在这里插入图片描述HashFind:因为hash表使用数组和链表来实现的,数组里面维护了几个链表,而我们添加节点的时候如何来确定添加都能链表上呢 这就用到了散列函数 ,这个散列函数就是用取模的方式实现的用id号模数组的大小(size)这样就可以分散在某个链表上了

源码

package 哈希表;

import java.util.Scanner;

/**
 * @author 一介草莽子
 * version 1.0
 */
@SuppressWarnings({
    
    "all"})
public class HashTabDemo {
    
    
    public static void main(String[] args) {
    
    
        //创建hashTab
        HashTab hashTab = new HashTab(6);

        Scanner scanner = new Scanner(System.in);
        String key = "";//选择
        boolean loop = true;
        int id = 0;
        String name = "";
        while (loop) {
    
    

            System.out.println("==========add:添加节点emp =========");
            System.out.println("==========sadd:顺序添加节点emp =========");
            System.out.println("==========List:显示所有数据=========");
            System.out.println("==========find:查找某个数据=========");
            System.out.println("==========remove:删除节点 =========");
            System.out.println("==========exit:退出       =========");
            System.out.println("请输入你的选择:");
            key = scanner.next();

            switch (key) {
    
    
                case "add":
                    System.out.println("请输入id,姓名:");
                    id = scanner.nextInt();
                    name = scanner.next();
                    hashTab.add(new Emp(id, name));
                    break;
                case "sadd":
                    System.out.println("请输入id,姓名:");
                    id = scanner.nextInt();
                    name = scanner.next();
                    hashTab.SortAdd(new Emp(id, name));
                    break;
                case "List"://显示所有数据
                    hashTab.List();
                    break;
                case "find"://显示所有数据
                    System.out.println("请输入要查找的id: ");
                    id = scanner.nextInt();
                    hashTab.findEmpById(id);
                    break;
                case "remove":
                    System.out.println("请输入要删除的id:");
                    id = scanner.nextInt();
                    hashTab.remove(id);
                    break;
                case "exit":
                    loop = false;
                    break;

                default:
                    break;
            }
        }
        System.out.println("程序退出。。。");
    }
}

//管理链表
class HashTab {
    
    
    //设置一个管理链表的数组
    private EmpLinkedList empLinkedList[];
    private int size;//数组大小 可以有几个链表

    public HashTab(int size) {
    
    
        this.size = size;
        empLinkedList = new EmpLinkedList[size];
        //为每个链表赋值,初始化链表
        for (int i = 0; i < size; i++) {
    
    
            empLinkedList[i] = new EmpLinkedList();
        }
    }

    //hashtab里面维护里一个数组,数组里面有一个链表 链表有一个个的emp对象
    //链表完成本质上的节点添加 而暴露在外面的是hashtab 因此hashtab里面也有一个add


    //add方法
    public void add(Emp emp) {
    
    
        //选择要添加到那个节点上
        int no = HashFind(emp.getId());
        empLinkedList[no].add(emp);//添加到某个数组链表上
    }

    //显示List() 遍历所有链表
    public void List() {
    
    
        for (int i = 0; i < size; i++) {
    
    
            empLinkedList[i].List(i);
        }
    }

    //查找某个节点,通过id号
    public void findEmpById(int id) {
    
    
        //通过散列函数来判断这个id是哪条链表上的
        int no = HashFind(id);
        //得到了这个no代表的是哪条链表的起始节点,在通过这个no来找这条链表里面的节点
        Emp empById = empLinkedList[no].findEmpById(id);
        if (empById == null) {
    
    
            System.out.println("没有找到...");
        } else {
    
    
            System.out.println("找到了:id=" + empById.getId() + "   name=" + empById.getName());
        }

    }

    //散列函数 用来把要添加的节点分散到某个链表上  用一个取模的方法
    public int HashFind(int no) {
    
    
        return no % size;
    }


    public void remove(int id) {
    
    
        //通过散列函数找到某条链表
        int no = HashFind(id);
        //no来找的那一条链表
        empLinkedList[no].remove(id);

    }

    public void SortAdd(Emp emp) {
    
    
        //选择要添加到那个节点上
        int no = HashFind(emp.getId());
        empLinkedList[no].SortAdd(emp);
    }
}

//存放雇员的链表
class EmpLinkedList {
    
    
    //头指针用来指向第一个元素 头指针就是第一个元素
    private Emp head;

    //默认添加到最后面
    public void add(Emp emp) {
    
    
        //判断是不是空链表是就添加到头结点里面
        if (head == null) {
    
    
            head = emp;
            return;
        }//否则就用辅助指针来遍历
        Emp curEmp = head;
        while (true) {
    
    
            if (curEmp.next == null) {
    
    
                break;
            }
            //遍历
            curEmp = curEmp.next;
        }
        //找到了最后一个的next来指向新的
        curEmp.next = emp;
        System.out.println("添加成功..............................");
    }

    //显示链表信息  no 代表的是那一条链表
    public void List(int no) {
    
    
        if (head == null) {
    
    
            System.out.println("第" + (no + 1) + "条链表为空...");
            return;
        }

        System.out.println("第" + (no + 1) + "条链表内容为: ");

        //否则就遍历打印
        Emp curEmp = head;
        while (true) {
    
    
            if (curEmp == null) {
    
    
                break;
            }
            System.out.printf("编号是%d,名字是%s  ", curEmp.getId(), curEmp.getName());
            curEmp = curEmp.next;//遍历

        }
        //换行
        System.out.println();
    }

    //查找函数
    public Emp findEmpById(int id) {
    
    
        //head 不能动用临时指针来遍历寻找
        Emp curEmp = head;

        boolean flag = true;
        while (true) {
    
    
            if (curEmp == null) {
    
    
                flag = false;
                break;
            }
            if (curEmp.getId() == id) {
    
    
                break;
            }
            curEmp = curEmp.next;//遍历
        }
        if (flag) {
    
    
            return curEmp;
        } else {
    
    

            return null;
        }
    }


    public void remove(int id) {
    
    
        //head不能动 设置一个临时变量 curEmp
        //找到被删除对象的前一个对象

        //判断是不是空链表
        if (head == null) {
    
    
            System.out.println("空链表...");
            return;
        }
        //判断链表的第一个节点是不是删除的对象
        if (head.getId() == id) {
    
    
            head = null;
            System.out.println("删除成功...");
            return;
        } else {
    
    //否则第一个节点就不是
            Emp curEmp = head;
            boolean flag = true;
            while (true) {
    
    
                if (curEmp.next == null) {
    
    
                    flag = false;//没找的的情况
                    break;
                }
                if (curEmp.next.getId() == id) {
    
    
                    //找到的情况
                    break;
                }
            }
            if (flag) {
    
    
                curEmp.next = curEmp.next.next;
                System.out.println("删除成功...");
            } else {
    
    
                System.out.println("删除失败没找的该元素....");
            }
        }
    }

    public void SortAdd(Emp emp) {
    
    
        //顺序添加链表  1 2 3  5 6 插入4
        //这是没有头结点的 所以要判断头结点的内容是空还是这个链表就有一个元素
        if (head == null) {
    
    
            head = emp;//空链表直接插入
        } else if (head.getId() >= emp.getId()) {
    
    
            //待插入元素小于head里的id的情况  要是插入的节点id小于头结点id就插入到头几点前面
            //让emp.next指向head 在让head指向新的 emp
            emp.next = head;
            head = emp;
            System.out.println("顺序添加 成功...");

        } else if (head.getId() < emp.getId() && head.next == null) {
    
    
            //找到一个的情况 待插入元素小大于head里的id的情况
            //直接插入在head后面
            head.next = emp;
            System.out.println("顺序添加 成功...");

        } else {
    
    
            //一个以上的情况
            Emp curEmp = head;
            while (true) {
    
    
                if (curEmp.next == null) {
    
    
                    //插入的数比所有的都大的情况
                    curEmp.next = emp;
                    break;
                }
                //找到首次大于待插入节点的id 的那个节点

                if (curEmp.next.getId() >= emp.getId()) {
    
    
                    emp.next = curEmp.next;//新emp指向首次大于的节点
                    curEmp.next = emp;//让前一个的curEmp.next存emp地址
                    System.out.println("顺序添加 成功...");
                    break;
                }
                curEmp = curEmp.next;
            }
        }

    }
}

//雇员的类
class Emp {
    
    
    private int id;
    private String name;
    public Emp next;//指向下一个


    public Emp(int id, String name) {
    
    
        this.id = id;
        this.name = name;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    @Override
    public String toString() {
    
    
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}


猜你喜欢

转载自blog.csdn.net/m0_56398287/article/details/127220961