7、力扣刷题心得(五)哈希表

关于哈希表的一些基础概念就不过多赘述,有意向者自行查阅相关资料!下面说一些注意事项。

1、三种哈希结构:数组、集合(set)、映射(map)

        其中集合中没有相同的元素,所以将数据填入集合中有去重的效果。

        映射分为<key,value>,由key映射到value,key和value的类型根据需要自行定义。

2、当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。

3、一些需要快速插入和搜索,可以考虑使用哈希表。

4、下面是根据《java数据结构与算法》一书中对哈希表进行的实现。(并不是很重要,因为现在实现都已经提供了具体的方法)


// 为防止冲突有两种方法解决,,这个是开放地址法
class Solution {
	
    public static void main (String[] args) {
    	Data aData = new Data(33);
    	HashTable aHashTable = new HashTable(10);
    	aHashTable.insert(aData);
    	Data atData = aHashTable.find(33);
    	System.out.println(atData.getValue());
    }
}
class Data {
	int val;
	public Data(int v) {
		this.val = v;
	}
	public int getValue() {
		return val;
	}
}

class HashTable {
	// 哈希表大小、哈希表、删除数据时填入的数据
	private int tableSize;
	private Data[] hashDatas;
	private Data noData;
	
	public HashTable(int size) {
		tableSize = size;
		hashDatas = new Data[tableSize];
		noData = new Data(-1);
	}
	
	public int hashFuc(int key) {
		return key % tableSize;
	}
	
	public int hashFuc2(int key) {
		return 5 - key % 5;
	}
	
	public void insert(Data val) {
		int key = val.getValue();
		int hashVal = hashFuc(key);
		int step = hashFuc2(key);
		while (hashDatas[hashVal] != null && hashDatas[hashVal].getValue() != -1) {
			key += step;
			hashVal = hashFuc(key);
		}
		hashDatas[hashVal] = val;
	}
	
	public void delete(int key) {
		int hashVal = hashFuc(key);
		int step = hashFuc2(key);
		while (hashDatas[hashVal] != null) {
			if (hashDatas[hashVal].getValue() == key) {
				hashDatas[hashVal] = noData;
				return;
			}
			key += step;
			hashVal = hashFuc(key);
		}
	}
	
	public Data find(int key) {
		int hashVal = hashFuc(key);
		int step = hashFuc2(key);
		while (hashDatas[hashVal] != null) {
			if (hashDatas[hashVal].getValue() == key) {
				return hashDatas[hashVal];
			}
			key += step;
			hashVal = hashFuc(key);
		}
		return null;
	}
}

// 为防止冲突有两种方法解决,,这个是链地址法

class Solution {
	
    public static void main (String[] args) {
    	HashTable aHashTable = new HashTable(10);
    	aHashTable.insert(33);
    	aHashTable.insert(34);
    	Link aLink = aHashTable.find(34);
    	System.out.println(aLink.val);
    }
}
class Link {
	int val;
	Link next;
	
	Link () {}
	public Link(int v) {
		this.val = v;
	}
	public int getValue() {
		return val;
	}
}

class LinkedList {
	Link head;
	// 记录链表的大小
	int size;
	
	LinkedList() {
		size = 0;
		// 创建一个虚拟头结点
		head = new Link(0);
	}
	
	public int get(int index) {
		if (index < 0 || size <= index) {
			return -1;
		}
		Link currentLink = head;
		for (int i = 0; i <= index; i++) {
			currentLink = currentLink.next;
		}
		return currentLink.val;
	}
	public void addAtIndex(int index, int val) {
		// 其实只需要定位要插入节点的前一个就行了
		if (index > size)
			return;
		else if (index <= 0) {
			index = 0;
		}
		
		Link insertNode = new Link(val);
		Link preLink = head;
		for (int i = 0; i < index; i++) {
			preLink = preLink.next;
		}
		insertNode.next = preLink.next;
		preLink.next = insertNode;
		
		// 注意这个不能忘记
		size++;
	}
	public void addAtHead(int val) {
		addAtIndex(0, val);
	}
	public void addAtTail(int val) {
		addAtIndex(size, val);
	}
	public void deleteAtKey(int key) {
		Link preLink = head;
		Link currentLink = preLink.next;
		while (currentLink != null) {
			if (currentLink.val == key) {
				preLink.next = currentLink.next;
				return;
			}
			preLink = preLink.next;
			currentLink = currentLink.next;
		}
		// 这个东西总是容易遗忘
		size--;
	}
	public Link findTheKey(int key) {
		Link preLink = head;
		Link currentLink = preLink.next;
		while (currentLink != null) {
			if (currentLink.val == key) {
				return currentLink;
			}
			preLink = preLink.next;
			currentLink = currentLink.next;
		}
		return null;
	}
	public void display() {
		head = head.next;
		while (head != null) {
			System.out.printf("%d  ", head.val);
			head = head.next;
		}
	}
}

class HashTable {
	// 哈希表大小、哈希表、删除数据时填入的数据,,,每一个单元由链表组成
	private int tableSize;
	private LinkedList[] hashDatas;
	
	public HashTable(int size) {
		tableSize = size;
		hashDatas = new LinkedList[tableSize];
		
		// 这个不要忘记,定义完链表类型的数组要进行单独的初始化
		for (int i = 0; i < tableSize; i++) {
			hashDatas[i] = new LinkedList();
		}
	}
	
	public int hashFuc(int key) {
		return key % tableSize;
	}
	
	public void insert(int key) {
		int hashVal = hashFuc(key);
		hashDatas[hashVal].addAtIndex(0, key);
	}
	
	public void delete(int key) {
		int hashVal = hashFuc(key);
		hashDatas[hashVal].deleteAtKey(key);
	}
	
	public Link find(int key) {
		int hashVal = hashFuc(key);
		return hashDatas[hashVal].findTheKey(key);
	}
}

5、接下来非常的重要,几乎在编程时就用到了下面的东西。

// 哈希集合的用法
// "static void main" must be defined in a public class.
public class Main {
    public static void main(String[] args) {
        // 1. initialize the hash set
        Set<Integer> hashSet = new HashSet<>();     
        // 2. add a new key
        hashSet.add(3);
        hashSet.add(2);
        hashSet.add(1);
        // 3. remove the key
        hashSet.remove(2);        
        // 4. check if the key is in the hash set
        if (!hashSet.contains(2)) {
            System.out.println("Key 2 is not in the hash set.");
        }
        // 5. get the size of the hash set
        System.out.println("The size of has set is: " + hashSet.size());     
        // 6. iterate the hash set
        for (Integer i : hashSet) {
            System.out.print(i + " ");
        }
        System.out.println("are in the hash set.");
        // 7. clear the hash set
        hashSet.clear();
        // 8. check if the hash set is empty
        if (hashSet.isEmpty()) {
            System.out.println("hash set is empty now!");
        }
    }
}
//哈希映射
// "static void main" must be defined in a public class.
public class Main {
    public static void main(String[] args) {
        // 1. initialize a hash map
        Map<Integer, Integer> hashmap = new HashMap<>();
        // 2. insert a new (key, value) pair
        hashmap.putIfAbsent(0, 0);
        hashmap.putIfAbsent(2, 3);
        // 3. insert a new (key, value) pair or update the value of existed key
        hashmap.put(1, 1);
        hashmap.put(1, 2);
        // 4. get the value of specific key
        System.out.println("The value of key 1 is: " + hashmap.get(1));
        // 5. delete a key
        hashmap.remove(2);
        // 6. check if a key is in the hash map
        if (!hashmap.containsKey(2)) {
            System.out.println("Key 2 is not in the hash map.");
        }
        // 7. get the size of the hash map
        System.out.println("The size of hash map is: " + hashmap.size()); 
        // 8. iterate the hash map
        for (Map.Entry<Integer, Integer> entry : hashmap.entrySet()) {
            System.out.print("(" + entry.getKey() + "," + entry.getValue() + ") ");
        }
        System.out.println("are in the hash map.");
        // 9. clear the hash map
        hashmap.clear();
        // 10. check if the hash map is empty
        if (hashmap.isEmpty()) {
            System.out.println("hash map is empty now!");
        }
    }
}

一些相关的知识

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值