数据结构学习笔记之哈希表

                                                                    数据结构-哈希表 学习笔记

散列表(又称散列映射,字典,关联数组)是一种用于以常数平均时间执行插入,删除,查找的技术。

应用:常用于查找;做缓存。
 

Java代码实现:


/**
 * 非线性存储结构: 哈希表
 * 
 * @see java.util.Hashtable
 * @see java.util.HashMap
 * 
 */
public class HashTable<E> {

	/** 默认容量 */
	private static final int DEFAULT_CAPACITY = 1 << 4;

	/** 最大容量 */
	private static final int MAX_CAPACITY = 1 << 16;

	/** 负载因子 */
	private static final double DEFAULT_LOAD_FACTOR = 0.75;

	/** 内部链表数组 */
	private Node<E>[] table;

	/** 负载因子 */
	private final double loadFactor;

	/** 触发表重算的阈值(threshold = capacity * loadfactor) */
	private int threshold;

	/** 哈希表的大小 */
	private int size = 0;

	/** 构造 */
	@SuppressWarnings("unchecked")
	public HashTable(int initialCapacity, double loadFactor) {
		if (initialCapacity < 0)
			throw new IllegalArgumentException("Illegal initial capacity:" + initialCapacity);
		if (initialCapacity > MAX_CAPACITY)
			initialCapacity = MAX_CAPACITY;
		if (loadFactor <= 0 || Double.isNaN(loadFactor))
			throw new IllegalArgumentException("Illegal load factor:" + loadFactor);
		int capacity = 1;
		while (capacity < initialCapacity)
			capacity <<= 1;

		this.loadFactor = loadFactor;
		threshold = (int) (capacity * loadFactor);
		table = new Node[threshold]; //
	}

	/** 构造 */
	public HashTable(int initialCapacity) {
		this(initialCapacity, DEFAULT_LOAD_FACTOR);
	}

	/** 构造 */
	@SuppressWarnings("unchecked")
	public HashTable() {
		this.loadFactor = DEFAULT_LOAD_FACTOR;
		threshold = (int) (DEFAULT_CAPACITY * DEFAULT_LOAD_FACTOR);
		table = new Node[DEFAULT_CAPACITY]; //
	}

	/** 添加数据 */
	public boolean add(E e) {
		int pos = hash(e) % table.length;
		Node<E> b = table[pos];
		if (b == null) {
			table[pos] = new Node<>(hash(e), e, null);
		} else {
			while (b.next != null)
				b = b.next;
			b.next = new Node<>(hash(e), e, null);
		}
		if (size++ >= threshold) //
			resize(table.length * 2);
		return true;
	}

	/** 删除数据 */
	public boolean remove(Object o) {
		int h = hash(o) % table.length;
		Node<E> b = table[h];
		if (b == null)
			return false;
		if (b.value.equals(o)) {
			if (b.next == null) {
				table[h] = null;
			} else {
				table[h] = b.next;
			}
			size--;
			return true;
		} else {
			while (b.next != null) {
				Node<E> c = b;
				b = b.next;
				if (b.value.equals(o)) {
					c.next = b.next;
					size--;
					return true;
				}
			}
		}
		return false;
	}

	/** 查找数据 */
	public boolean contains(Object e) {
		int p = hash(e) % table.length;
		Node<E> o = table[p];
		if (o == null)
			return false;
		if (!o.value.equals(e)) {
			while (o.next != null) {
				o = o.next;
				if (o.value.equals(e))
					return true;
			}
		} else {
			return true;
		}
		return false;
	}

	/** 重算内部链表数组的大小,完成扩容 */
	@SuppressWarnings("unchecked")
	void resize(int newCapacity) {
		Node<E>[] old = table;
		int oldCapacity = old.length;
		if (oldCapacity == MAX_CAPACITY) {
			threshold = MAX_CAPACITY;
			return;
		}
		threshold = (int) (newCapacity * loadFactor);
		Node<E>[] newTable = new Node[newCapacity];
		transfer(newTable);
		table = newTable;
	}

	/** 将扩容前表的数据 复制到新表中 */
	void transfer(Node<E>[] newTable) {
		Node<E>[] src = table;
		int newCapacity = newTable.length;
		for (int n = 0; n < src.length; n++) {
			Node<E> e = src[n];
			if (e != null) {
				src[n] = null;
				do {
					Node<E> next = e.next;
					int i = e.hash % newCapacity; // 扩容后获得数据在哈希表中新的存储位置
					e.next = newTable[i];
					newTable[i] = e;
					e = next;
				} while (e != null);
			}
		}
	}

	/* 链表实现 */
	static final class Node<E> {

		final int hash; // 哈希值
		final E value; // 数据
		Node<E> next; // 上一个节点

		Node(int hash, E value, Node<E> next) {
			this.hash = hash;
			this.next = next;
			this.value = value;
		}

		@Override
		public int hashCode() {
			return Objects.hashCode(value);
		}

		@Override
		public boolean equals(Object o) {
			if (o == this)
				return true;
			if (o instanceof Node) {
				Node<?> b = (Node<?>) o;
				if (Objects.equals(value, b.value))
					return true;
			}
			return false;
		}

		public String toString() {
			return value.toString();
		}

	}

	/** 迭代器 */
	class HashIterator implements Iterator<Node<E>> {
		Node<E> next; // 下一个
		int index; // 位置
		Node<E> current; // 当前节点

		HashIterator() {
			if (size > 0) {
				Node<E>[] t = (Node<E>[]) table;
				while (index < t.length && (next = t[index++]) == null)
					;
			}
		}

		@Override
		public boolean hasNext() {
			return next != null;
		}

		@Override
		public Node<E> next() {
			Node<E> e = next;
			if (e == null)
				throw new NoSuchElementException();

			if ((next = e.next) == null) {
				Node<E>[] t = (Node<E>[]) table;
				while (index < t.length && (next = t[index++]) == null)
					;
			}
			current = e;
			return e;
		}

	}

	/** 获得迭代器 */
	public Iterator<Node<E>> iterator() {
		return new HashIterator();
	}

	/**  */
	static final class HashSpliterator<E> implements Spliterator<E> {

		HashSpliterator() {
			
		}

		@Override
		public boolean tryAdvance(Consumer<? super E> action) {

			return false;
		}

		@Override
		public Spliterator<E> trySplit() {

			return null;
		}

		@Override
		public long estimateSize() {

			return 0;
		}

		@Override
		public int characteristics() {

			return 0;
		}

	}

	@Override
	public int hashCode() {
		int h = 0;
		Iterator<Node<E>> i = iterator();
		while (i.hasNext())
			h += Objects.hashCode(i.next().value);
		return h;
	}

	@Override
	public boolean equals(Object o) {
		if (o == this)
			return true;
		if (!(o instanceof HashTable))
			return false;
		HashTable<?> t = (HashTable<?>) o;
		if (t.size() != size())
			return false;
		Iterator<?> i = t.iterator();
		while (i.hasNext()) {
			Node<?> n = (Node<?>) i.next();
			if (!contains(n.value))
				return false;
		}
		return true;
	}

	/** 哈希函数:确定数据在HashTable数组中的位置 */
	public static final int hash(Object o) {
		return o == null ? 0 : Objects.hashCode(o);
	}
	
	/** 返回哈希表的大小 */
	public int size() {
		return size;
	}

	/** 字符串输出 */
	public String toString() {
		StringBuilder s = new StringBuilder();
		s.append('{');
		for (int a = 0; a < table.length; a++) {
			if (table[a] != null) {
				s.append(table[a].value).append(',');
				Node<E> e = table[a].next;
				while (e != null) {
					s.append(e.value).append(',');
					e = e.next;
				}
			}
		}
		int len = s.length();
		if (s.lastIndexOf(",") == len - 1)
			s.deleteCharAt(len - 1);

		return s.append('}').toString();

		// Iterator<E> i = iterator();
		// if (!i.hasNext())
		// return "{}";
		// StringBuilder s = new StringBuilder();
		// s.append('{');
		// for (;;) {
		// s.append(i.next());
		// if (!i.hasNext())
		// return s.append('}').toString();
		//
		// s.append(',').append(' ');
		// }
	}

}

注:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光明矢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值