编写简易版的单链表和基于单链表数组编写hashset表

本文介绍了一种简易版的LinkedList实现方式,并基于单链表数组实现了Hash表。详细阐述了通过节点形式保存数据的方法及如何利用哈希码确定单链表位置,包括增删改查等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.简易版LinkedList的实现

package com.upupgogogo;

/**
 * Created by upupgogogo on 2018/3/20.下午1:19
 */
public class Node<T> {

    public T data;

    public Node<T> next;

    public Node(T date, Node<T> next){
        this.data = date;
        this.next = next;
    }
    public Node(){
        this(null,null);
    }

}

通过节点的形式保存数据以及下个数据的

package com.upupgogogo;

/**
 * Created by upupgogogo on 2018/3/20.下午1:23
 */
public class SinglyLinkedList<T> implements LList<T> {

    private Node<T> head;

    private int size;

    //初始化节点和保存数据的大小
    public SinglyLinkedList() {
        this.head = new Node<T>();
        this.size = 0;
    }

    public boolean isEmpty() {
        return this.size == 0;
    }

    public int length() {
        return this.size;
    }

    public void add(int index, T x) {
        //1.判参数
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: " +index+ "," +"Size: "+this.size);
        //2.找节点(插入点的前一个节点)
        Node<T> p = this.head;
        for (int j = 0; j < index; j++)
            p = p.next;
        //3.插入节点
        p.next = new Node<T>(x,p.next);
        //size加一
        this.size++;
    }

    public void add(T x) {
        add(this.size,x);
    }

    public T remove(int index) {

        //判断index是否有效
        checkElement(index);

        //得到头结点
        Node<T> p = this.head;

        //找到index节点的前一个节点
        for (int j = 0; j < index; j++)
            p = p.next;

        //得到保存的数据
        T x =(T)p.next.data;

        //让该节点的前节点的next指针指向该节点的下个节点
        p.next = p.next.next;

        //数据长度减一
        this.size--;

        return x;
    }

    public void set(int index, T x) {
        checkElement(index);
        Node<T> p = this.head;
        for (int j = 0; j < index; j++)
            p = p.next;
        p.next.data = x;
    }

    public T get(int index) {
        checkElement(index);
        Node<T> p = this.head;
        for (int j = 0; j < index; j++)
            p = p.next;
        return p.next.data;
    }
    private void checkElement(int index){
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException("Index: " +index+ "," +"Size: "+this.size);
    }
    public int contain(T x){
        Node<T> p = head.next;
        int i = -1;
        while (p != null){
            i++;
            if (p.data .equals(x)){
                p.data = x;
                return i;
            }
            p = p.next;
        }
        return -1;
    }

    public String toString() {
        String str = "";
        Node<T> p = head;
        for (int j = 0; j < size; j++){
            p = p.next;
            str = str + p.data.toString() +",";
        }
        if (str.length() > 0)
            str = str.substring(0,str.length()-1);
        return "["+str+"]";
    }

    public static void main(String[] args) {
        LList lList = new SinglyLinkedList();
        lList.add(19);
        lList.add(20);
        lList.remove(0);
        System.out.println(lList);
    }
}
得到输出结果:
[20]

2.基于单链表数组来实现hash表

package com.upupgogogo;

import java.util.HashSet;

/**
 * Created by upupgogogo on 2018/3/21.上午10:30
 */
public class NoBaseMapHashSet<T> {

    private SinglyLinkedList<T>[] table; //单链表数组来保存数据

    private static final int DEFAULT_VALUE = 16;

    private int size;  //容器所装载的数据大小

    private static final float LOAD_FACTOR = 0.75f;  //加载因子

    private int ciritical_vale;   //容器所装载的临界值

    public NoBaseMapHashSet(){
        //初始化数组
        this.table = new SinglyLinkedList[DEFAULT_VALUE];

        //初始化数组的每个单链表对象
        initSinglyLinkedList(table.length);
        this.size = 0;

        //初始容器所装载的临界值
        this.ciritical_vale = (int)(LOAD_FACTOR*DEFAULT_VALUE);
    }
    private void initSinglyLinkedList(int value){
        for (int i = 0; i < value; i++){
            table[i] = new SinglyLinkedList<T>();
        }
    }


    private int index(T key) {
        //根据key的hashcode和table长度取模计算key在table中的位置
        if (key == null)
            throw new NullPointerException("NO NULL");
        return key.hashCode() % table.length;
    }

    public void add(T key){
        //判断是否包含保存的数据
        if (contain(key) != -1)
            return;

        //判断是否需要扩容
        resize();

        //先通过hash值判断单链表所属数组位置,然后调用单链表的add方法添加数据
        table[index(key)].add(key);

        //数据长度加一
        size++;
    }

    //扩容
    private void resize(){

        //判断数据大小是否已达临界值
        if (this.size >= this.ciritical_vale){
            //申明一个临时变量保存原有的数据
            SinglyLinkedList[] temp = this.table;

            //初始化一个两倍长度的单链表数组
            this.table = new SinglyLinkedList[table.length*2];

            initSinglyLinkedList(table.length);
            for (int j =0; j < temp.length; j++)
                table[j] = temp[j];

            //重新初始化临界值
            ciritical_vale = (int) (table.length * LOAD_FACTOR);
        }
    }

    public void remove(T key){
        //判断是否包含此数据
        if (contain(key) != -1)
            return;
        //通过得到此数据所处单链表的index值,然后调用单链表的remove删除数据
        table[index(key)].remove(contain(key));

        size--;
    }

    public String toString() {
     String str = "";
     for (int j = 0; j < table.length; j++){
         if (table[j] != null){
             for (int i = 0; i < table[j].length(); i++)
                 str = str + table[j].get(i).toString() + ",";
         }
     }
     if (str.length() > 0)
         str = str.substring(0,str.length()-1);
     return "["+str+"]";
    }

    public int contain(T key){
         //1.通过hashcode方法得到所属单链表下标
         //2.通过equals方法判断是否相同
        //3.返回该数据所处单链表的位置,若不存在则返回-1
        return table[index(key)].contain(key);
    }

    public static void main(String[] args) {
        NoBaseMapHashSet hashSet = new NoBaseMapHashSet();
        hashSet.add(19);
        hashSet.add(18);
        hashSet.add(19);
        System.out.println(hashSet);
    }

}
输出结果
[18,19]

处理单链表的关键之处就是在于处理他的头结点,通过头结点得到每个节点从而进行增删改查,以及扩容

而操作hash表的关键就在于通过hashcode来确定单链表,通过equals来确定是否进行添加或者覆盖删除,以及扩容




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值