算法导论11.2散列表Hash tables链式法解决碰撞

/*
 * IA_11.2ChainedHash.cpp
 *
 *  Created on: Feb 12, 2015
 *      Author: sunyj
 */

#include <stdint.h>
#include <iostream>
#include <string.h>
// CHAINED-HASH-INSERT(T, x)
// insert x at the head of list T[h(x.key)]

// CHAINED-HASH-SEARCH(T, k)
// search for an element with key k in list T[h(k)]

// CHAINED-HASH-DELETE(T, x)
// delete x from the list T[h(x.key)]

class ListNode {
public:
    ListNode() : key(0), data(0), prev(nullptr), next(nullptr)
    {
    	std::cout << "ListNode()" << std::endl;
    }
    ListNode(int64_t const k, int64_t d) : key(k), data(d), prev(nullptr), next(nullptr) { }

    int64_t key;
    int64_t data;
    ListNode* prev;
    ListNode* next;
};

// LIST-SEARCH(L, k)
// x = L.nil.next
// while ( x != L.nil and x.key != k)
//     x = x.next
// return x

// LIST-INSERT(L, x)
// x.next = L.nil.next
// L.nil.next.prev = x
// L.nil.next = x
// x.prev = L.nil

// LIST-DELETE(L, x)
// x.prev.next = x.next
// x.next.prev = x.prev

class LinkedList {
public:
    LinkedList() : nil(&m_nil)
    {
    	std::cout << "LinkedList()" << std::endl;
        nil->prev = nil;
        nil->next = nil;
        nil->data = -1; //
    }
    ListNode* search(int64_t const k)
    {
        ListNode* x = nil->next;
        while (x != nil && k != x->key)
        {
            x = x->next;
        }
        return x;
    }
    void insert(ListNode* x)
    {
        x->next         = nil->next;
        nil->next->prev = x;
        nil->next       = x;
        x->prev         = nil;
    }
    void del(ListNode* x)
    {
        x->prev->next = x->next;
        x->next->prev = x->prev;
    }
    void print()
    {
        ListNode* x = nil->next;
        while (nil != x)
        {
            std::cout << x->key << " ";
            x = x->next;
        }
        std::cout << std::endl;
    }
private:
    ListNode  m_nil; // empty list has noe node, pointer nill points to it.
    ListNode* nil;
};

class ChainedHashTable {
public:
	ChainedHashTable(int64_t const n) : size(n)
    {
        data = new LinkedList[n]();
    }
    ~ChainedHashTable() {}
    int64_t HashFunc(int64_t const key)
    {
    	return key % size;
    }
    ListNode* search(int64_t const key)
    {
    	return data[HashFunc(key)].search(key);
    }
    void insert(ListNode* x)
    {
    	(data[HashFunc(x->key)]).insert(x);
    }
    void del(ListNode* x)
    {
    	data[HashFunc(x->key)].del(x);
    }
    void print(int64_t key)
    {
    	data[HashFunc(key)].print();
    }
private:
    LinkedList* data;
    int64_t size;
};

int main()
{
	LinkedList a;
	/*
	 * A prime not too close to an exact power of 2 is often a good choice for m. For
example, suppose we wish to allocate a hash table, with collisions resolved by
chaining, to hold roughly n = 2000 character strings, where a character has 8 bits.
We don‘t mind examining an average of 3 elements in an unsuccessful search, and
so we allocate a hash table of size m = 701. We could choose 701 because
it is a prime near 2000=3 but not near any power of 2.
	 */
    ChainedHashTable table(701); // The division method,

    ListNode node1(1, 100);
    ListNode node4(4, 400);
    ListNode node16(16, 1600);
    ListNode node9(9, 900);
    table.insert(&node1);
    table.insert(&node4);
    table.insert(&node16);
    table.insert(&node9);
    table.print(4);
    ListNode node25(25, 2500);
    table.insert(&node25);
    table.print(16);
    table.del(&node1);
    table.print(9);
    ListNode* tmp;
    tmp = table.search(9);
    table.del(tmp);
    table.print(9);
    return 0;
}
 

时间: 2024-10-10 02:37:36

算法导论11.2散列表Hash tables链式法解决碰撞的相关文章

【算法导论】学习笔记——第11章 散列表

11.1 直接寻址表当关键字的全域U很小,可采用直接寻址的方式.假设动态集合S的元素都取自全域U={0, 1, ..., m-1}的一个关键字,并且没有两个元素具有相同的关键字.为表示动态集合,使用直接寻址表(diret-address table),记为T[0...m-1],其中的每个位置称为槽(slot).直接寻找表就是按照数组索引,缺点明显.基本操作如下: 1 DIRECT-ADDRESS-SEARCH(T, k) 2 return T[k] 3 4 DIRECT-ADDRESS-INSE

散列表(Hash table)及其构造

散列表(Hash table) 散列表,是根据关键码值(Key value)而直接进行访问的数据结构.它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. 已知的查找方法: 1.顺序查找 O(N) 2.二分查找(静态查找) O(log2N) 3.二叉搜索树 O(h) h为二叉树的高度 平衡二叉树 O(log2N) Q:如何快速搜索到需要的关键字?如果关键字不方便比较怎么办? 查找的本质:已知对象找位置 有序安排对象:全序.半序 直接

Java 散列表 hash table

Java 散列表 hash table @author ixenos hash table, HashTable, HashMap, HashSet hash table 是一种数据结构 hash table 为每个对象计算一个整数,该整数被称为散列码 hash code hash code 是由对象的实例域产生的一个整数,具有不同的数据域的对象将产生不同的hash code 如果自定义类,就要负责实现这个类的hashCode方法,注意要与equals方法兼容,即如果a.equals(b)为tr

算法导论-散列表(Hash Table)

目录 引言 直接寻址 散列寻址 散列函数 除法散列 乘法散列 全域散列 完全散列 碰撞处理方法 链表法 开放寻址法 线性探查 二次探查 双重散列 随机散列 再散列问题 完整源码(C++) 参考资料 内容 1.引言 如果想在一个n个元素的列表中,查询元素x是否存在于列表中,首先想到的就是从头到尾遍历一遍列表,逐个进行比较,这种方法效率是Θ(n):当然,如果列表是已经排好序的话,可以采用二分查找算法进行查找,这时效率提升到Θ(logn);  本文中,我们介绍散列表(HashTable),能使查找效率

《算法导论》读书笔记之第11章 散列表

本章介绍了散列表(hash table)的概念.散列函数的设计及散列冲突的处理.散列表类似与字典的目录,查找的元素都有一个key与之对应,在实践当中,散列技术的效率是很高的,合理的设计散函数和冲突处理方法,可以使得在散列表中查找一个元素的期望时间为O(1).散列表是普通数组概念的推广,在散列表中,不是直接把关键字用作数组下标,而是根据关键字通过散列函数计算出来的.书中介绍散列表非常注重推理和证明,看的时候迷迷糊糊的,再次证明了数学真的很重要.在STL中map容器的功能就是散列表的功能,但是map

散列表(hash table)&mdash;&mdash;算法导论(13)

1. 引言     许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表     在介绍散列表之前,我们前介绍直接寻址表.     当关键字的全域U(关键字的范围)比较小时,直接寻址是一种简单而有效的技术.我们假设某应用要用到一个动态集合,其中每个元素的关键字都是取自于全域U={0,1,-,m-1},其中m不是一个很大的数.另外,假设每个元素的关键字都不同.    为表示动

算法导论 第11章 散列表

散列表是主要支持动态集合的插入.搜索和删除等操作,其查找元素的时间在最坏情况下是O(n),但是在是实际情况中,散列表查找的期望是时间是O(1),散列表是普通数组的推广,因为可以通过元素的关键字对数组进行直接定位,所以能够在O(1)时间内访问数组的任意元素. 1.直接寻址表 当关键字的全域较小,即所有可能的关键字的量比较小时,可以建立一个数组,为所有可能的关键字都预留一个空间,这样就可以很快的根据关键字直接找到对应元素,这就是直接寻址表,在直接寻址表的查找.插入和删除操作都是O(1)的时间.. 2

散列表(hash表)

1. hash表: 又称散列表,以key-value的形式存储数据,能够由key快速定位到其指定的value,而不经过查找.它采用了函数式的映射思想,将记录的存储位置与关键词相关联,从而快速定位进行查找,复杂度为O(1). 2. hash函数: key和value的映射关系称为HASH函数,通过该函数可以计算key所对应的存储位置(表中存储位置,不是实际物理地址),即HASH地址. 构造HASH地址的方法有: (1)直接定址法:取关键词或关键词的某个线性函数为hash地址. (2)平方取中法:关

《算法图解》chap5 散列表

线索Cues 笔记Notes 散列表的内部机制(实现,冲突,散列函数) 应用案例 一.散列表=散列函数+数组 散列函数特点: 将相同的输入映射到相同的数字 将不同的输入映射到不同的数字,但其实这样的函数几乎不会存在.所以会有冲突的存在:两个键分配的位置相同. 知道数组有多大,只返回有效的索引 散列表是由键和值组成的. 冲突的处理方式,当两个键映射到同一个位置,就在这个位置存储一个链表. 二. 查找某人的电话号码 投票,一人只能投一次.如果没有投过票就投票成功并且保存.投过就不让投 缓存:网站将数