使用哈希表实现节点的相关操作

1.哈希表的优势

		使用数组和链表实现,数组的每个元素是一个单链表

2.代码实现

1.数组节点
package hashTable;

import java.util.HashSet;

public class EmployeeArray {
    private EmployeeLinked[] employeeLinked; // 管理链表的数组
    private int size; // 链表的个数(数组长度)

    // 构造方法
    public EmployeeArray(int size) {
        this.size = size;
        this.employeeLinked = new EmployeeLinked[size];
        // 初始化每个链表
        for (int i = 0; i < size; i++) {
            employeeLinked[i] = new EmployeeLinked();
        }
    }

    /**
     * 根据节点的散列地址,将其添加到对应的链表中
     * id计算方法:散列函数
     * 添加雇员(节点)
     *
     * @param employees 要添加的节点
     */
    public void add(Employees employees) {
        // 得到节点的散列地址
        int address = HashFun(employees.id);
        // 根据散列地址将其加入到对应的链表中
        employeeLinked[address].AddEmployees(employees);
    }

    /**
     * 散列函数 ---> 计算节点散列地址的一种函数
     *
     * @param id 传入的节点的id
     * @return 对应节点的散列地址
     */
    public int HashFun(int id) {
        return id % size;
    }

    /**
     * 遍历哈希表中所有的链表
     */
    public void ShowHashTable() {
        for (int i = 0; i < size; i++) {
            employeeLinked[i].show(i);
        }
    }
    /**
     * 根据id查找节点的位置
     *
     * @param id 传入的节点id
     */
    public void FindNode(int id) {
        // 得到节点的散列地址
        int address = HashFun(id);
        // 根据散列地址查找对应的链表中
        Employees employees = employeeLinked[address].findNode(id);
        if (employees != null) {
            System.out.printf("id为%d的节点在第%d条链表上", id, address);
        }
    }
}
2.链表节点
public class EmployeeLinked {
    private Employees head; // 链表的头指针,指向第一个节点

    /**
     * 添加节点到链表中
     *
     * @param newEmployee 要添加的节点
     */
    public void AddEmployees(Employees newEmployee) {
        // 如果是添加第一个节点(雇员)
        if (head == null) {
            head = newEmployee; // 直接指向第一个节点
            return;
        } else {
            // 需要一个辅助指针
            Employees temp = head; // 从头指针开始
            while (true) {
                // 最后一个节点
                if (temp.next == null) {
                    break;
                }
                // 指针后移
                temp = temp.next;
            }
            // 循环结束后,将指针指向新添加的节点(添加成功)
            temp = newEmployee;
        }
    }

    /**
     * 遍历链表元素
     *
     * @param o 链表的编号
     */
    public void show(int o) {
        // 空链表
        if (head == null) {
            System.out.println("第" + (o += 1) + "条链表为空");
            return;
        }
        System.out.print("第" + (o += 1) + "条链表信息为:");
        // 需要一个辅助指针
        Employees temp = head;
        while (true) {
            System.out.printf("=>%d,%s\t", temp.id, temp.name);
            // 最后一个节点
            if (temp.next == null) {
                break;
            }
            // 指针后移
            temp = temp.next;
        }
        System.out.println();
    }
    /**
     * 根据id查找节点的位置
     * @param id 传入的节点id
     * @return 如果找到,返回这个节点,否则返回null
     */
    public Employees findNode(int id) {
        // 空链表
        if (head == null) {
            System.out.println("链表为空");
            return null;
        }
        // 需要一个辅助指针
        Employees temp = head;
        while (true) {
            // 找到
            if (temp.id == id) {
                break;
            }
            // 没有找到
            if (temp.next == null) {
                temp = null;
            }
            // 指针后移
            temp = temp.next;
        }
        return temp;
    }
}
3.入口
package hashTable;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 创建一个哈希表
        EmployeeArray hashTable = new EmployeeArray(9);
        // 接收用户输入
        String str = "";
        while (true) {
            System.out.println("请您输入功能序号:");
            System.out.println("add--------------->添加节点");
            System.out.println("show-------------->显示节点");
            System.out.println("find-------------->查找节点");
            System.out.println("exit-------------->退出系统");
            str = scanner.nextLine();
            switch (str) {
                case "add":
                    System.out.println("请输入Id:");
                    int id = scanner.nextInt();
                    System.out.println("请输入姓名:");
                    String name = scanner.next();
                    Employees employees = new Employees(id, name);
                    hashTable.add(employees);
                    break;
                case "show":
                    hashTable.ShowHashTable();
                    break;
                case "find":
                    System.out.println("请输入要查找的节点的id:");
                    int idFind = scanner.nextInt();
                    hashTable.FindNode(idFind);
                case "exit":
                    scanner.close();
                    System.exit(0);
                default:
                    break;
            }
        }
    }
}
#include #include #include using namespace std; #define NULL 0 unsigned int key; //用来输入/输出文件流类 unsigned int key2; //key和key2分别是用做了电话号码和姓名的关键字 int *p; struct node //新建节点(用户姓名、地址、电话号码、指向下一个结点的指针 ) { char name[8],address[20]; char num[11]; node * next; }; typedef node* pnode; typedef node* mingzi; //声明了名字和电话两个指针 node **phone; node **nam; node *a; void hash(char num[11]) //以电话号码为关键字建立哈希函数 { int i = 3; key=(int)num[2]; while(num[i]!=NULL) { key+=(int)num[i]; i++; } key=key%20; } void hash2(char name[8]) //姓名为关键字建立哈希函数 { int i = 1; key2=(int)name[0]; while(name[i]!=NULL) { key2+=(int)name[i]; i++; } key2=key2%20; } //强制类型转换,将用户名的每一个字母的ASCLL码值相加并且除以20后的余数 node* input() //输入节点信息 ,建立结点,并将结点的next指针指空 { node *temp; temp = new node; temp->next=NULL; cout<<"输入姓名:"<>temp->name; cout<<"输入地址:"<>temp->address; cout<<"输入电话:"<>temp->num; return temp; } //对于指针类型返回的是地址 int apend() //添加节点 { node *newphone; node *newname; newphone=input(); newname=newphone; newphone->next=NULL; newname->next=NULL; hash(newphone->num); //利用哈希函数计算出对应关键字的存储地址 hash2(newname->name); newphone->next = phone[key]->next; //利用电话号码为关键字插入 phone[key]->next=newphone; //是采用链地址法,拉链法处理冲突的散列表结构 newname->next = nam[key2]->next; //利用用户名为关键字插入 nam[key2]->next=newname; return 0; } void create() //新建节点 { int i; phone=new pnode[20]; //动态创建对象数组,C++课本P188页 for(i=0;inext=NULL; } } void create2() //新建节点 { int i; nam=new mingzi[20]; for(i=0;inext=NULL; } } void list() //显示列表 { int i; node *p; for(i=0;inext; while(p) { cout<name<<'_'<address<<'_'<num<next; } } } void list2() //显示列表 { int i; node *p; for(i=0;inext; while(p) { cout<name<<'_'<address<<'_'<num<next; } } } void find(char num[11]) //在以电话号码为关键字的哈希表中查找用户信息 { hash(num); node *q=phone[key]->next; while(q!= NULL) { if(strcmp(num,q->num)==0) break; q=q->next; } if(q) cout<name<<"_" <address<<"_"<num<<endl; else cout<<"无此记录"<next; while(q!= NULL) { if(strcmp(name,q->name)==0) break; q=q->next; } if(q) cout<name<<"_" <address<<"_"<num<<endl; else cout<<"无此记录"<<endl; } void save() //保存用户信息 { int i; node *p; for(i=0;inext; while(p) { fstream iiout("out.txt", ios::out); //创建一个文件流对象:iiout iiout<name<<"_"<address<<"_"<num<next; } } } void menu() //菜单 { cout<<" 哈希表通讯录"<<endl; cout<<" 0.添加记录"<<endl; cout<<" 2.姓名散列"<<endl; cout<<" 3.查找记录"<<endl; cout<<" 4.号码散列"<<endl; cout<<" 5.清空记录"<<endl; cout<<" 6.保存记录"<<endl; cout<<" 7.退出系统"<>sel; if(sel==3) { cout<<"8姓名查询" <<endl;cout<<"9号码查询"<>b; if(b==9) {cout<<"请输入电话号码:"<>num; cout<<"输出查找的信息:"<<endl; find(num); } else {cout<<"请输入姓名:"<>name; cout<<"输出查找的信息:"<<endl; find2(name);}} if(sel==2) {cout<<"姓名散列结果:"<<endl; list2();} if(sel==0) {cout<<"请输入要添加的内容:"<<endl; apend();} if(sel==4) {cout<<"号码散列结果:"<<endl; list(); } if(sel==5) {cout<<"列表已清空:"<<endl; create();create2();} if(sel==6) { cout<<"通信录已保存:"<<endl; save();} if(sel==7) return 0; } return 0; }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值