15.链地址法

同样是为了解决哈希表中索引重复问题的算法,基本思路为将哈希表中维护的数组改成存储链表的数组,将数据存在链表中。也可以用数组但是数组的插入和删除的效率较低,故采用链表。

实现:

链表的实现:

/*
 * 链结点,相当于是车厢
 */
public class Node {
	//数据域
	public Info info;
	//指针域
	public Node next;
	
	public Node(Info info) {
		this.info = info;
	}
	
}
/*
 * 链表,相当于火车
 */
public class LinkList {
	//头结点
	private Node first;
	
	public LinkList() {
		first = null;
	}
	
	/**
	 * 插入一个结点,在头结点后进行插入
	 */
	public void insertFirst(Info info) {
		Node node = new Node(info);
		node.next = first;
		first = node;
	}
	
	/**
	 * 删除一个结点,在头结点后进行删除
	 */
	public Node deleteFirst() {
		Node tmp = first;
		first = tmp.next;
		return tmp;
	}
	
	
	/**
	 * 查找方法
	 */
	public Node find(String key) {
		Node current = first;
		while(!key.equals(current.info.getKey())) {
			if(current.next == null) {
				return null;
			}
			current = current.next;
		}
		return current;
	}
	
	/**
	 * 删除方法,根据数据域来进行删除
	 */
	public Node delete(String key) {
		Node current = first;
		Node previous = first;
		while(!key.equals(current.info.getKey())) {
			if(current.next == null) {
				return null;
			}
			previous = current;
			current = current.next;
		}
		
		if(current == first) {
			first = first.next;
		} else {
			previous.next = current.next;
		}
		return current;
		
	}
}

哈希表的实现:

public class HashTable {
	private LinkList[] arr;
	
	/**
	 * 默认的构造方法
	 */
	public HashTable() {
		arr = new LinkList[100];
	}
	
	/**
	 * 指定数组初始化大小
	 */
	public HashTable(int maxSize) {
		arr = new LinkList[maxSize];
	}
	
	/**
	 * 插入数据
	 */
	public void insert(Info info) {
		//获得关键字
		String key = info.getKey();
		//关键字所自定的哈希数
		int hashVal = hashCode(key);
		if(arr[hashVal] == null) {
			arr[hashVal] = new LinkList();
		}
		arr[hashVal].insertFirst(info);
	}
	
	/**
	 * 查找数据
	 */
	public Info find(String key) {
		int hashVal = hashCode(key);
		return arr[hashVal].find(key).info;
	}
	
	/**
	 * 删除数据
	 * @param key
	 * @return
	 */
	public Info delete(String key) {
		int hashVal = hashCode(key);
		return arr[hashVal].delete(key).info;
	}
	
	public int hashCode(String key) {
		BigInteger hashVal = new BigInteger("0");
		BigInteger pow27 = new BigInteger("1");
		for(int i = key.length() - 1; i >= 0; i--) {
			int letter = key.charAt(i) - 96;
			BigInteger letterB = new BigInteger(String.valueOf(letter));
			hashVal = hashVal.add(letterB.multiply(pow27));
			pow27 = pow27.multiply(new BigInteger(String.valueOf(27)));
		}
		return hashVal.mod(new BigInteger(String.valueOf(arr.length))).intValue();
	}
}

所存储的实体类:

/**
 * 员工信息类
 * @author Administrator
 *
 */
public class Info {
	private String key;
	private String name;
	
	public Info(String key, String name) {
		this.key = key;
		this.name = name;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public String getName() {
		return name;
	}

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

 

转载于:https://my.oschina.net/helloXia/blog/1922548

### 数据结构 哈希查找 链地址法 实现与原理 #### 定义与基本概念 哈希法,亦称散列法、杂凑法或关键字地址计算法等,在元素的关键字 \( \text{Key} \) 和元素的存储位置 \( p \) 之间建立一个对应关系 \( H \),使得 \( p = H(\text{Key}) \)[^3]。此函数 \( H \) 被称为哈希函数(散列函数),其作用在于提供一种压缩映像机制。 #### 链地址法概述 当多个不同的关键字被同一个哈希函数映射到了相同的存储位置上时,这种情况被称为冲突。为了处理这些冲突,链地址法应运而生。这种方法允许任意数量的数据项共享同一索引位置,并通过链接的方式形成一条单向链表[^1]。因此,即使存在大量可能引起冲突的情况,也能确保每一个新加入的数据都能找到合适的存放地点。 #### 查找过程分析 尽管采用链地址法可以有效解决因哈希碰撞而导致无法定位的问题,但在实际操作过程中确实会带来额外的时间开销。每当执行一次查询请求时,程序不仅需要依据给定的关键字快速定位至相应桶位,还需沿着该处挂接起来的一系列节点逐个比较直至发现目标对象为止。 #### C++实现案例 下面给出一段简单的C++代码片段用于展示如何基于上述理论构建并管理一个简易版的支持链地址策略的哈希表: ```cpp #include <iostream> #include <vector> using namespace std; struct Node { int key; string value; Node* next; }; class HashTable { private: vector<Node*> table; // 存储指针数组 public: HashTable(int size):table(size, nullptr){} void insert(int k, const string& v){ unsigned long index = hash<int>{}(k)%table.size(); auto newNode = new Node{k,v,nullptr}; if (!table[index]) { table[index]=newNode; } else{ newNode->next=table[index]; table[index]=newNode; } } bool find(int k,string &result)const{ unsigned long index = hash<int>{}(k)%table.size(); for (auto curr = table[index];curr!=nullptr ;curr=curr->next ) { if(curr->key==k){ result=curr->value; return true; } } return false; } ~HashTable(){ for(auto& node : table){ while(node != nullptr){ Node *temp=node; node=node->next; delete temp; } } } }; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值