数据结构哈希查找源代码
c语言开源hash项目——uthash
c语言开源 hash项目 ——uthash
1 //------------------------------------------
2 // c语言 开源hash项目 —— uthash
3 //
4 //
5 //eg: 对 字符串进行查找和删除 字符指针
6 //
7 // warning: uthash 对 字符指针和字符数组,
8 //
插入的函数是不一样的,查找的函数是一致的
9 //
对所有的类型,删除的操作
10 //-------------------------------------------
21 UT_hash_handle hh;
22 }uthash_int;
23
24 // 查找
25 uthash_int *find_uthash_int(uthash_int *g_users, int ikey)
26 {
27 uthash_int *s = NULL;
28 HASH_FIND_INT(g_users, &ikey, s);
11
12 #include "gtest/gtest.h"
13 #include <iostream>
14 using namespace std;
15
16 #include"uthash/uthash.h"
17
18 typedef struct {
数据结构与算法实验源代码(2023最新版)
数据结构与算法实验源代码本文档为数据结构与算法实验源代码的范本,旨在帮助读者深入理解和实践数据结构和算法的相关知识。
下文将详细介绍各个章节的内容。
⒈引言- 简要介绍数据结构与算法的重要性和应用场景。
- 说明本文档的结构和目的。
⒉数据结构概述- 介绍数据结构的基本概念和分类。
- 详细介绍各种常见数据结构,如数组、链表、栈、队列、树等。
- 提供每种数据结构的定义、操作和应用示例。
⒊算法基础- 介绍算法的基本思想和特性。
- 详细讲解常见的算法设计方法,如递归、分治、贪心、动态规划等。
- 提供每种算法的原理、示例和分析。
⒋排序算法- 介绍各种排序算法的原理和实现方式。
- 包括冒泡排序、选择排序、插入排序、归并排序、快速排序等。
- 提供每种排序算法的时间复杂度和空间复杂度分析。
⒌查找算法- 介绍常用的查找算法,如顺序查找、二分查找、哈希查找等。
- 提供每种查找算法的原理和实现方式。
- 分析每种查找算法的时间复杂度和空间复杂度。
⒍图算法- 介绍图的基本概念和表示方法。
- 详细讲解图的遍历算法,如深度优先搜索和广度优先搜索。
- 介绍最短路径算法,如Dijkstra算法和Floyd-Warshall算法。
- 提供每种图算法的实现示例和应用场景。
⒎高级数据结构与算法- 介绍高级数据结构,如堆、红黑树、AVL树等。
- 详细讲解高级算法,如动态规划、并查集等。
- 提供每种高级数据结构和算法的原理、实现方式和应用示例。
⒏结语- 对数据结构与算法的重要性进行总结。
- 强调学习和实践的重要性。
本文档涉及附件:⒈源代码示例附件,包含了本文中提到的各种数据结构和算法的实现代码。
法律名词及注释:⒈数据结构:指一组数据的存储结构和相应的操作。
⒉算法:指解决特定问题的一系列有序步骤或规则。
⒊时间复杂度:用来度量算法执行时间随输入规模增长时的增长率。
⒋空间复杂度:用来度量算法执行过程中所需存储空间随输入规模增长时的增长率。
SHA1算法源代码
SHA1算法源代码SHA-1(Secure Hash Algorithm 1)是一种常见的哈希算法,用于生成哈希值,常用于密码学和安全领域。
下面是SHA-1算法的详细源代码:```pythonimport struct#初始化常数h1=0xEFCDAB89h2=0x98BADCFEh4=0xC3D2E1F0def sha1(message):"""输入:字符串message输出:字符串的SHA-1哈希值"""#补位original_length = len(message) * 8message += b'\x80'while (len(message) + 8) % 64 != 0:message += b'\x00'message += struct.pack('>Q', original_length)#分组blocks = []for i in range(0, len(message), 64):block = message[i:i+64]blocks.append(block)#处理每个分组for block in blocks:w = list(struct.unpack('>16I', block))#扩展消息for i in range(16, 80):w.append(left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1))#初始化哈希值a=h0b=h1c=h2d=h3e=h4#执行80轮循环for i in range(0, 80):if 0 <= i < 20:f=(b&c),((~b)&d)elif 20 <= i < 40:f=b^c^dk=0x6ED9EBA1elif 40 <= i < 60:f=(b&c),(b&d),(c&d)k=0x8F1BBCDCelse:f=b^c^dk=0xCA62C1D6temp = (left_rotate(a, 5) + f + e + k + w[i]) & 0xffffffff e=dd=cc = left_rotate(b, 30)b=aa = temp#更新哈希值h0 = (h0 + a) & 0xffffffffh1 = (h1 + b) & 0xffffffffh2 = (h2 + c) & 0xffffffffh3 = (h3 + d) & 0xffffffffh4 = (h4 + e) & 0xffffffff#输出哈希值digest = struct.pack('>5I', h0, h1, h2, h3, h4)return digest.hexdef left_rotate(n, b):"""左旋转n"""return ((n << b) , (n >> (32 - b))) & 0xffffffff```上面的代码实现了SHA-1算法的核心部分。
c实现的hash表-概述说明以及解释
c实现的hash表-概述说明以及解释1.引言1.1 概述在计算机科学中,哈希表(Hash Table),又被称为散列表,是一种常用的数据结构。
它能够以常数时间复杂度(O(1))来实现插入、删除和查找等操作,因此具有高效的特性。
哈希表通过哈希函数将键(key)映射到一个固定大小的数组(通常称为哈希表)。
通过这种映射关系,我们可以在数组中快速访问到对应的值(value)。
常见的应用场景包括缓存系统、数据库索引、编译器符号表等。
相对于其他数据结构,哈希表具有以下优点:1. 高效的插入、删除和查找操作:哈希表在插入、删除和查找数据时以常数时间复杂度进行操作,无论数据量大小,都能快速地完成操作。
2. 高效的存储和检索:通过哈希函数的映射关系,哈希表能够将键值对存储在数组中,可以通过键快速地找到对应的值。
3. 空间效率高:哈希表通过哈希函数将键映射到数组下标,能够充分利用存储空间,避免冗余的存储。
然而,哈希表也存在一些局限性:1. 冲突问题:由于哈希函数的映射关系是将多个键映射到同一个数组下标上,可能会导致冲突。
解决冲突问题的常见方法包括链地址法(Chaining)和开放定址法(Open Addressing)等。
2. 内存消耗:由于哈希表需要维护额外的空间来存储映射关系,所以相比于其他数据结构来说,可能会占用较多的内存。
本篇长文将重点介绍C语言实现哈希表的方法。
我们将首先讨论哈希表的定义和实现原理,然后详细介绍在C语言中如何实现一个高效的哈希表。
最后,我们将总结哈希表的优势,对比其他数据结构,并展望哈希表在未来的发展前景。
通过本文的学习,读者将能够深入理解哈希表的底层实现原理,并学会如何在C语言中利用哈希表解决实际问题。
1.2 文章结构本文将围绕C语言实现的hash表展开讨论,并按照以下结构进行组织。
引言部分将对hash表进行概述,介绍hash表的基本概念、作用以及其在实际应用中的重要性。
同时,引言部分还会阐述本文的目的,即通过C语言实现的hash表,来探讨其实现原理、方法以及与其他数据结构的对比。
数据结构的查找算法
数据结构的查找算法在计算机科学中,数据结构是用于组织和存储数据的一种方式。
查找算法是数据结构中的重要部分,它用于在数据集合中搜索特定元素或信息。
本文将介绍几种常见的数据结构查找算法,包括线性查找、二分查找、哈希查找以及树结构的查找算法。
1. 线性查找线性查找是一种简单直观的查找方法,适用于无序的数据集合。
其基本思想是从数据集合的第一个元素开始逐个比较,直到找到目标元素或者遍历完整个数据集合。
由于线性查找需要遍历所有元素,所以时间复杂度为O(n),其中n为数据集合的大小。
2. 二分查找二分查找是一种高效的查找算法,但它要求数据集合中的元素必须有序。
具体实现方式是将数据集合分为两半,然后与目标元素进行比较,不断缩小查找范围,直到找到目标元素或者确定目标元素不存在。
由于每次都将查找范围减小一半,所以时间复杂度为O(log n),其中n为数据集合的大小。
3. 哈希查找哈希查找利用哈希函数将目标元素映射到哈希表中的特定位置,从而快速定位目标元素。
哈希表是一种以键-值对形式存储数据的数据结构,可以快速插入和删除元素,因此在查找时具有良好的性能。
哈希查找的时间复杂度为O(1),但在处理哈希冲突时可能会影响性能。
4. 树结构的查找算法树是一种常见的数据结构,其查找算法主要包括二叉搜索树、平衡二叉搜索树以及B树和B+树。
二叉搜索树是一种有序的二叉树,左子树的所有节点值都小于根节点,右子树的所有节点值都大于根节点。
通过比较目标元素与节点的值,可以快速定位目标元素。
平衡二叉搜索树是为了解决二叉搜索树在某些情况下可能出现的退化情况,通过旋转操作保持树的平衡性。
B树和B+树是一种多路搜索树,它们可以减少磁盘I/O操作,适用于大规模数据的查找。
综上所述,数据结构的查找算法是计算机科学中的重要内容。
不同的查找算法适用于不同的场景,选择合适的算法可以提高查找效率。
在实际应用中,需要根据数据集合的特点及查找需求来选择合适的算法。
数据结构.第9章.查找.4.哈希表
§9.3 哈希表
开放地址法
例:关键码集为 {47,7,29,11,16,92,22,8,3}, 设:哈希表表长为m=11; 哈希函数为Hash(key)=key mod 11; 拟用线性探测法处理冲突。建哈希表: 0 1
11 22
2
3
4
5
6
3
7
7
8
29
9
8
10
47 92 16
§9.3 哈希表
开放地址法
选用关键字的某几位组合成哈希地址。
选用原则应当是:各种符号在该位上出现的频率大致
相同。
适于关键字位数比哈希地址位数大,且可能出现的关 键字事先知道的情况。
§9.3 哈希表
数字分析法
例:有一组(例如80个)关键码,其样式如下: 讨论: 3 4 7 0 5 2 4 ① 第1、2位均是“3和4”,第3位也只有 3 4 9 1 4 8 7 3 4 8 2 6 9 6 “ 7、8、9”,因此,这几位不能用,余 3 4 8 5 2 7 0 下四位分布较均匀,可作为哈希地址选用。 3 4 8 6 3 0 5 ② 若哈希地址取两位(因元素仅80个), 3 4 9 8 0 5 8 则可取这四位中的任意两位组合成哈希地 3 4 7 9 6 7 1 址,也可以取其中两位与其它两位叠加求 3 4 7 3 9 1 9 和后,取低两位作哈希地址。 位号:① ② ③ ④ ⑤ ⑥ ⑦
拟用二次探测法处理冲突。建哈希表如下: Hi = ( H(K)+di ) mod m 其中di =12, -12, 22,-22,…, j2, -j2 ( j≤m/2)。
0 1
11 22
2
3
3
4
5
6
7
数据结构常考的5个算法
数据结构常考的5个算法1. 递归算法递归是一种将问题分解为相同或相似的子问题解决的方法。
在递归算法中,一个函数可以调用自己来解决更小规模的问题,直到遇到基本情况,然后递归返回并解决整个问题。
递归算法通常用于解决需要重复执行相同操作的问题,例如计算斐波那契数列、计算阶乘、树和图的遍历等。
递归算法的主要特点是简洁、易理解,但在大规模问题上可能效率较低。
以下是一个使用递归算法计算斐波那契数列的示例代码:def fibonacci(n):if n <= 1:return nelse:return fibonacci(n-1) + fibonacci(n-2)2. 排序算法排序算法用于将一组数据按照一定顺序进行排列。
常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。
•冒泡排序逐渐交换相邻的元素,将较大的元素逐渐“冒泡”到最后的位置。
•选择排序每次选择最小(或最大)的元素,并将其放置在已排序部分的末尾。
•插入排序通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
•快速排序通过选择一个基准元素,将数组分割为左右两部分,对左右两部分分别递归地进行快速排序。
•归并排序将数组分成两个子数组,分别对两个子数组进行排序,然后将两个有序子数组合并为一个有序数组。
以下是一个使用快速排序算法对数组进行排序的示例代码:def quick_sort(arr):if len(arr) <= 1:return arrpivot = arr[len(arr)//2]left = [x for x in arr if x < pivot]middle = [x for x in arr if x == pivot]right = [x for x in arr if x > pivot]return quick_sort(left) + middle + quick_sort(right)3. 查找算法查找算法用于在数据集合中查找特定元素的位置或存在性。
c语言 hash查找算法
c语言 hash查找算法Hash查找算法(Hash Search Algorithm)是一种通过哈希函数将键映射到特定位置的查找算法。
哈希查找算法的核心思想是将关键字通过哈希函数转化为数组的索引,从而实现快速的查找和存储。
一、哈希函数的作用哈希函数是哈希查找算法的核心组成部分,它将关键字映射到数组的特定位置。
哈希函数的设计需要满足以下两个条件:1. 确定性:对于相同的输入,哈希函数应该返回相同的输出;2. 均匀性:哈希函数应该尽量将关键字均匀地分布到数组的不同位置。
二、哈希表的实现哈希表是哈希查找算法的基础数据结构,它由一个固定大小的数组和一个哈希函数组成。
数组的每个位置称为一个槽位(Slot),每个槽位可以存储一个关键字。
当插入或查找一个关键字时,通过哈希函数将关键字映射到数组的特定位置,实现快速的插入和查找操作。
三、哈希冲突的处理由于哈希函数的映射是有限的,不同的关键字可能映射到数组的同一个位置,这就导致了哈希冲突(Hash Collision)的问题。
哈希冲突会使得不同的关键字存储在同一个槽位中,因此需要一种策略来解决冲突。
常见的解决冲突的方法有以下几种:1. 链地址法(Chaining):将冲突的关键字存储在同一个槽位中的一个链表中;2. 开放地址法(Open Addressing):当发生冲突时,通过探测序列的方法找到下一个可用的槽位;3. 再哈希法(Rehashing):当发生冲突时,通过应用另一个哈希函数来寻找下一个可用的槽位。
四、哈希查找的优势和应用场景相比于其他的查找算法,哈希查找算法具有以下几个优势:1. 时间复杂度较低:在理想情况下,哈希查找的时间复杂度为O(1);2. 适用于大规模数据:哈希查找算法适用于大规模数据的查找和存储;3. 支持高效的插入和删除操作:哈希查找算法可以在常数时间内完成插入和删除操作。
哈希查找算法常被应用于以下场景:1. 数据库索引:哈希查找算法可以用于数据库查询的索引结构,提高查询效率;2. 缓存系统:哈希查找算法可以用于缓存系统中的数据存储和查找,提高缓存的访问速度;3. 路由表查找:哈希查找算法可以用于路由器中的路由表查找,快速定位目标地址。
哈希表的c语言实现
下面是一个简单的C语言实现哈希表的代码示例:#include <stdio.h>#include <stdlib.h>#include <string.h>#define TABLE_SIZE 100#define DEFAULT_LOAD 0.7typedef struct {char *key;int value;} Element;typedef struct {Element *table[TABLE_SIZE];int count;double load;} HashTable;void createHashTable(HashTable *ht, int size) {for (int i = 0; i < size; ++i) {ht->table[i] = NULL;}ht->count = 0;ht->load = DEFAULT_LOAD;}void destroyHashTable(HashTable *ht) {for (int i = 0; i < ht->count; ++i) {Element *elem = ht->table[i];while (elem != NULL) {Element *tmp = elem;elem = elem->next;free(tmp);}}ht->count = 0;}Element *hash(HashTable *ht, char *key) {int index = (int)(strlen(key) * ht->load + rand() % ht->count);return ht->table[index] == NULL ? NULL : ht->table[index]->table[index & 0x7f]; }void insert(HashTable *ht, char *key, int value) { Element *elem = hash(ht, key);if (elem == NULL) {elem = (Element *)malloc(sizeof(Element));elem->key = strdup(key);elem->value = value;ht->table[0][0] = elem;ht->count++;if (ht->count > ht->load * ht->count) {double load = ht->load;int i = 0;while (true) {if (ht->table[i] == NULL) {break;}elem = ht->table[i]->table[0];free(ht->table[i]->table[0]);ht->table[i]->table[0] = elem;ht->count--;if (ht->count < load * ht->count) {break;}ht->table[++i] = NULL;}}} else {Element *p = elem;while (p->next != NULL) {p = p->next;}p->next = (Element *)malloc(sizeof(Element));p->next->key = strdup(key);p->next->value = value;}ht->count++;}void remove(HashTable *ht, char *key) {Element *p = ht->table[0];while (p != NULL) {if (strcmp(p->key, key) == 0) {Element *q = p->next;free(p);ht->table[0] = q;ht->count--;return;}p = p->next;}}int main() {HashTable ht = {.table = {0}, .count = 0, .load = DEFAULT_LOAD};createHashTable(&ht, TABLE_SIZE);insert(&ht, "key1", 1);insert(&ht, "key2", 2);insert(&ht, "key3", 3);remove(&ht, "key2");printf("Count: %d\n", ht.count);printf("Value: %d\n", ht.table[0]->value);destroyHashTable(&ht);return 0;}在这个示例中,我们定义了一个哈希表结构体HashTable,其中包含一个元素数组table和一个计数器count,以及一个用于存储当前负载的变量load。
数据结构源代码(全)
/*顺序表的操作#include<iostream>#include<stdlib.h>using namespace std;Release 13.12 rev 9501 (2013/12/25 19:25:45) gcc 4.7.1 Windows/unicode - 32 bit #define MAX_SIZE 100typedef struct{int *emel;int lenth;}Sq;void init(Sq &l);void create(Sq &l);void trval(Sq &l);void find_value(Sq &l);void find_position(Sq &l);void insert(Sq &l);void dele(Sq &l);int main(){Sq l;init(l);create(l);trval(l);find_value(l);find_position(l);insert(l);trval(l);dele(l);trval(l);return 0;}void init(Sq &l){l.emel =new int[MAX_SIZE];if(l.emel ==NULL){cout<<"\t申请空间失败!"<<endl;exit(1);}l.lenth=0;cout<<"\t成功申请空间!该顺序表的长度目前为:"<<l.lenth<<endl; }void create(Sq &l){cout<<"\t请输入你想输入元素的个数:";int x;cin>>x;if((x<1)&&(x>MAX_SIZE)){cout<<"\t你说输入的数不在范围里"<<endl;return;}int i;for(i=0;i<x;i++){cin>>l.emel[i];}l.lenth=x;cout<<"\t成功赋值!"<<endl;}void trval(Sq &l){int i;cout<<"l(";for(i=0;i<l.lenth;i++){cout<<l.emel[i]<<" ";}cout<<")"<<" 该顺序表现在的长度为:"<<l.lenth<<endl;}void find_value(Sq &l){int x,t=0;cout<<"\t请输入你要查找的值:";cin>>x;int i;for(i=0;i<l.lenth;i++){if(l.emel[i]==x){t=1;cout<<"\t成功找到该元素,它是顺序表的第"<<i+1<<"个元素!"<<endl;}}if(t==0){cout<<"\t无该元素!"<<endl;}}void find_position(Sq &l){int x;cout<<"\t请输入你要查找的位置:";cin>>x;int i;if((x<1)||(x>l.lenth)){cout<<"\t输入的值不在范围内!"<<endl;return;}for(i=1;i<=l.lenth;i++){if(i==x){cout<<"\t成功找到该元素,该值是"<<l.emel[i-1]<<endl;}}}void insert(Sq &l){int i,x,y;cout<<"\t请输入你要插入的位置";cin>>x;cout<<"\t请输入你要插入的值";cin>>y;if((x<1)||(x>l.lenth)){cout<<"\t输入的值不在范围内!"<<endl;return;}if(x==l.lenth){l.emel[l.lenth]=y;l.lenth=l.lenth+1;return;}for(i=l.lenth;i>=x;i--){l.emel[i]=l.emel[i-1];}l.emel[x-1]=y;l.lenth=l.lenth+1;}void dele(Sq &l){int i,x;cout<<"\t请输入你要删除位置:";cin>>x;if((x<1)||(x>l.lenth)){cout<<"\t输入的值不在范围内!"<<endl;return;}for(i=x-1;i<=l.lenth;i++){l.emel[i]=l.emel[i+1];}l.lenth=l.lenth-1;}成功申请空间!该顺序表的长度目前为:0请输入你想输入元素的个数:3852成功赋值!l(8 5 2 ) 该顺序表现在的长度为:3请输入你要查找的值:5成功找到该元素,它是顺序表的第2个元素!请输入你要查找的位置:3成功找到该元素,该值是2请输入你要插入的位置3请输入你要插入的值10l(8 5 2 10 ) 该顺序表现在的长度为:4请输入你要删除位置:3l(8 5 10 ) 该顺序表现在的长度为:3--------------------------------Process exited with return value 0Press any key to continue . . .*//*#include<stdio.h>#include<stdlib.h>typedef struct Link{int num;struct Link *next;}L;L* creat(L* head){head=(L *)malloc(sizeof(L));if(head==NULL){printf("头节点申请失败!\n");exit(-1);}head->next=NULL;return head;}void insert(L* head){int x,i;printf("请输入你想输入数据的个数:");scanf("%d",&x);L *p,*q;p=head;for(i=0;i<x;i++){q=(L *)malloc(sizeof(L));if(q==NULL){printf("新点申请失败!\n");exit(-1);}printf("请输入值:");scanf("%d",&q->num);q->next=NULL;p->next=q;p=q;}}void print(L* head){L *p;p=head->next;while(p!=NULL){printf("值为:%d\n",p->num);p=p->next;}}int main(){L *head;head=creat(head);printf("成功创建头节点!!!\n");insert(head);printf("成功输入数据!!!\n");print(head);return 0;}*//*线性表的操作#include<stdio.h>#include<stdlib.h>typedef struct Link{int num;struct Link *next;}L;L* creat(L* head){head=(L *)malloc(sizeof(L));if(head==NULL){printf("头节点申请失败!\n");exit(-1);}head->next=NULL;return head;}void init(L* head){int x,i;printf("请输入你想输入数据的个数:");scanf("%d",&x);L *p,*q;p=head;for(i=0;i<x;i++){q=(L *)malloc(sizeof(L));if(q==NULL){printf("新点申请失败!\n");exit(-1);}printf("请输入值:");scanf("%d",&q->num);q->next=p->next;p->next=q;}}int print(L* head){L *p;int lenth=0;p=head->next;printf("\t\tL(");while(p!=NULL){lenth++;printf("%d ",p->num);p=p->next;}printf(")\n");return lenth;}int insert(L *head,int lenth){printf("\t\t请输入你要插入的元素的位置:");int in;scanf("%d",&in);if(in<1 || in>lenth){printf("\t\t输入值不在范围内!");return -1;}L *p,*q;p=head->next;q=(L *)malloc(sizeof(L));if(q==NULL){printf("新点申请失败!\n");return -1;}printf("\t\t请为新节点输入值:");scanf("%d",&q->num);int i=0;while(p!=NULL){i++;if(i==in-1){q->next=p->next;p->next=q;}p=p->next;}lenth++;return lenth;}int dele(L *head,int lenth){printf("\t\t请输入你要删除的元素的位置:");int out;scanf("%d",&out);if(out<1 || out>lenth){printf("\t\t输入值不在范围内!");return -1;}L *p,*q;p=head->next;q=head;int i=0;while(p!=NULL){i++;if(i==out){q->next=p->next;}q=p;p=p->next;}lenth--;return lenth;}void find(L *head,int lenth){printf("\t\t请输入你要查找的元素的位置:");int finder;scanf("%d",&finder);if(finder<1 || finder>lenth){printf("\t\t输入值不在范围内!");return ;}L *p;p=head->next;int i=0;while(p!=NULL){i++;if(i==finder){printf("\t\t你要找的该位置所对应的值为:%d\n",p->num);}p=p->next;}}int main(){L *head;head=creat(head);printf("成功创建头节点!!!\n");init(head);printf("成功输入数据!!!\n");int len;len=print(head);printf("\t\t该线性表的长度为:%d\n",len);len=insert(head,len);len=print(head);printf("\t\t插入后线性表的长度为:%d\n",len);len=dele(head,len);len=print(head);printf("\t\t删除后该线性表的长度为:%d\n",len);find(head,len);return 0;}*//*顺序表的合并#include<iostream>using namespace std;struct LA{int *pa;int lenth;};struct LB{int *pb;int lenth;};struct LC{int *pc;int lenth;};void mergelist(LA la,LB lb,LC &lc);int main(){int x,y;LA la;LB lb;cout<<"\t\t请给线性表LA和LB指定长度:";cin>>x>>y;la.pa =new int(sizeof(int)*x);lb.pb =new int(sizeof(int)*y);int i;for(i=0;i<x;i++){cout<<"请输入表LA的值:";cin>>la.pa[i];}cout<<endl;la.lenth=x;for(i=0;i<y;i++){cout<<"请输入表LB的值:";cin>>lb.pb[i];}lb.lenth=y;cout<<"LA(";for(i=0;i<x;i++){cout<<la.pa[i]<<" ";}cout<<")"<<endl;cout<<"LB(";for(i=0;i<y;i++){cout<<lb.pb[i]<<" ";}cout<<")"<<endl;LC lc;mergelist(la,lb,lc);return 0;}void mergelist(LA la,LB lb,LC &lc){lc.lenth=la.lenth+lb.lenth;lc.pc=new int(sizeof(int)*lc.lenth);int *pa=la.pa,*pb=lb.pb,*pc=lc.pc;int *pa_last=la.pa+la.lenth-1;int *pb_last=lb.pb+lb.lenth-1;while(pa<=pa_last && pb<=pb_last){if(*pa <= *pb){*pc++=*pa++;}else{*pc++=*pb++;}}while(pa<=pa_last){*pc++=*pa++;}while(pb<=pb_last){*pc++=*pb++;}cout<<"LC(";int i=0;for(i=0;i<lc.lenth;i++){cout<<lc.pc[i]<<" ";}cout<<")"<<endl;}*///栈/*#include<iostream>using namespace std;#include<stdlib.h>#define MAXSIZE 100typedef struct{int *base;int *top;int stacksize;}Sqstack;int Initstack(Sqstack &s);void Push(Sqstack &s,int e);void StackTraverse(Sqstack &s);void Gettop(Sqstack &s);void Pop(Sqstack &s);int main(){Sqstack s;Initstack(s);cout<<"\t\t初始化栈成功!"<<endl;Push(s,2);cout<<"\t\t2入栈成功!"<<endl;Push(s,4);cout<<"\t\t4入栈成功!"<<endl;Push(s,6);cout<<"\t\t6入栈成功!"<<endl;Push(s,8);cout<<"\t\t8入栈成功!"<<endl;cout<<"\n由栈底至栈顶的元素为:";StackTraverse(s);Gettop(s);Pop(s);Gettop(s);return 0;}int Initstack(Sqstack &s){s.base=new int[MAXSIZE];if(s.base==NULL){exit(1);}s.top=s.base;s.stacksize=MAXSIZE;}void Push(Sqstack &s,int e){if(s.top-s.base==s.stacksize){exit(1);}*s.top++=e;}void StackTraverse(Sqstack &s){int *p=s.base,i=0;while(p<s.top){i++;cout<<*p++<<" ";}cout<<"\t\t栈的长度是"<<i<<endl;}void Gettop(Sqstack &s){if(s.base==s.top){exit(1);}cout<<"栈顶元素是:"<<*(s.top-1)<<endl; }void Pop(Sqstack &s){if(s.top==s.base){exit(1);}cout<<"出栈的第一个元素是:";cout<<*--s.top<<" "<<endl;}*///队列例题:/*#include<iostream>#include<stdlib.h>using namespace std;#define MAXQSIZE 100typedef struct{int *base;int front;int rear;}SqQueue;int InitQueue(SqQueue &q);int EnQueue(SqQueue &q,int x);int DeQueue(SqQueue &q);int main(){SqQueue q;InitQueue(q);EnQueue(q,1);EnQueue(q,3);EnQueue(q,5);EnQueue(q,7);DeQueue(q);DeQueue(q);DeQueue(q);DeQueue(q);return 0;}int InitQueue(SqQueue &q){q.base=new int[MAXQSIZE];if(q.base==NULL){exit(1);}q.front=0;q.rear=0;return 0;}int EnQueue(SqQueue &q,int x){if((q.rear+1)%MAXQSIZE==q.front){exit(0);}q.base[q.rear]=x;q.rear=(q.rear+1)%MAXQSIZE;return 0;}int DeQueue(SqQueue &q){if(q.front==q.rear){exit(0);}int x=q.base[q.front];q.front=(q.front+1)%MAXQSIZE;cout<<x<<endl;}*//*#include<iostream>#include<stdlib.h>using namespace std;typedef struct Qnode{int date;struct Qnode *next;}Qnode,*Queueptr;typedef struct{Queueptr front; //队头指针Queueptr rear; //队尾指针}LinkQueue;int InitQueue(LinkQueue &Q);void EnQueue(LinkQueue &Q,int e);void TrvalQueue(LinkQueue Q);void DeQueue(LinkQueue &Q);int main(){LinkQueue Q;InitQueue(Q);EnQueue(Q,1);cout<<"\t元素1入队成功!"<<endl;EnQueue(Q,3);cout<<"\t元素3入队成功!"<<endl;EnQueue(Q,5);cout<<"\t元素5入队成功!"<<endl;EnQueue(Q,7);cout<<"\t元素7入队成功!"<<endl;cout<<"\t队列的元素分别是:"<<endl;TrvalQueue(Q);cout<<"\t第一个出队的元素是:"<<endl;DeQueue(Q);cout<<"\n\t第一个元素出队完成之后队列中从队头至队尾的元素为:";TrvalQueue(Q);return 0;}int InitQueue(LinkQueue &Q){Q.rear=new Qnode;Q.front=Q.rear;if(Q.front==NULL){exit(0);}Q.front->next=NULL;return 0;}void EnQueue(LinkQueue &Q,int e){Qnode *p=new Qnode;if(!p){exit(1);}p->date=e;p->next=NULL;Q.rear->next=p; //连接Q.rear=p; //修改队尾指针}void TrvalQueue(LinkQueue Q){Qnode *p=Q.front->next;//队头元素while(Q.front!=Q.rear){cout <<p->date<<" ";Q.front=p;p=p->next;}cout<<endl;}void DeQueue(LinkQueue &Q){if(Q.front==Q.rear){return;}Qnode *p=Q.front->next;cout<<"\t"<<p->date<<endl;Q.front->next=p->next;if(Q.rear==p){Q.rear=Q.front;delete p;}}*//*//表达式求值#include<iostream>#include<stdlib.h>#include<stdio.h>using namespace std;#define MAXSIZE 100typedef struct{char *base;char *top;char num;}OPND; //数据栈typedef struct{char *base;char *top;char c;}OPTR; //符号栈int Initstack(OPND &op_n,OPTR &op_t);void Pushstack(OPND &op_n,char ch);void Pushstack(OPTR &op_t,char ch);char Popstack(OPND &op_n,char ch);char Popstack(OPTR &op_t,char ch);char Gettop(OPTR op_t);char Gettop(OPND op_n);int In(char ch);char Precede(char x,char y);char operate(char z,char x,char y);int main(){OPND op_n;OPTR op_t;Initstack(op_n,op_t);Pushstack(op_t,'#');char ch;char p;cin>>ch;while(ch!='#' || Gettop(op_t)!='#'){if(!In(ch)){Pushstack(op_n,ch);cin>>ch;}else{switch( Precede(Gettop(op_t),ch) ){case '<':Pushstack(op_t,ch);cin>>ch;break;case '>':char x,y,z;x=Popstack(op_t,x);y=Popstack(op_n,y);z=Popstack(op_n,z);Pushstack(op_n,operate(z,x,y));break;case '=':p=Popstack(op_t,p);cin>>ch;break;}}}cout<<"\t表达式结果是:"<<Gettop(op_n)<<endl;return 0;}int Initstack(OPND &op_n,OPTR &op_t){op_n.base=new char[MAXSIZE];op_t.base=new char[MAXSIZE];if((op_n.base==NULL) || (op_t.base==NULL)){exit(1);}op_n.top=op_n.base;op_t.top=op_t.base;op_n.num=MAXSIZE;op_t.c=MAXSIZE;return 0;}void Pushstack(OPND &op_n,char ch){if(op_n.top-op_n.base==op_n.num){return;}*op_n.top++=ch;cout<<ch<<" 入数字栈"<<endl;}void Pushstack(OPTR &op_t,char ch){if(op_t.top-op_t.base==op_t.c){return;}*op_t.top++=ch;cout<<ch<<" 入操作符"<<endl;}char Popstack(OPND &op_n,char ch)if(op_n.top==op_n.base){exit(1);}ch=*--op_n.top;cout<<ch<<" 出数字栈"<<endl;return ch;}char Popstack(OPTR &op_t,char ch){if(op_t.top==op_t.base){exit(1);}ch=*--op_t.top;cout<<ch<<" 出字符栈"<<endl;return ch;}char Gettop(OPTR op_t){char x;if(op_t.top==op_t.base){exit(1);}x=*(op_t.top-1);cout<<"得到操作符栈顶"<<x<<endl;return x;}char Gettop(OPND op_n){char x;if(op_n.top==op_n.base){exit(1);}x=*(op_n.top-1);cout<<"得到操作数栈顶"<<x<<endl;return x;}int In(char ch)if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#') {return 1;}else{return 0;}}char Precede(char x,char y){if(x=='+' || x=='-'){if(y=='+' || y=='-' || y==')' || y=='#'){return '>';}else{return '<';}}if(x=='*'||x=='/'){if(y=='('){return '<';}else{return '>';}}if(x=='('){if(y==')'){return '=';}else if(y=='+'||y=='-'||y=='*'||y=='/'||y=='('){return '<';}}if(x==')'){if(y!='('){return '>';}}if(x=='#'){if(y=='#'){return '=';}else if(y!=')'){return '<';}}}char operate(char z,char x,char y) {if(x=='+'){return (z-'0') + (y-'0')+48;}if(x=='-'){return (z-'0') - (y-'0')+48;}if(x=='*'){return (z-'0')* (y-'0')+48;}if(x=='/'){return (z-'0')/ (y-'0')+48;}}*//*#include<iostream>using namespace std;int main(){char a[10];char *b[10];char **c[10];return 0;}*//*#include<iostream>using namespace std;char f(char x,char y){return (x-'0') * (y-'0')+48;}int main(){char a='3',b='5';char p=f(a,b);cout<<p<<endl;return 0;}*///数列出队/*#include<iostream>#include<stdlib.h>using namespace std;typedef struct Qnode{int num;struct Qnode *next;}Qnode,*Queueptr;typedef struct{Queueptr front;Queueptr rear;}LinkQueue;int InitQueue(LinkQueue &Q);void EnQueue(LinkQueue &Q,int x); int DeQueue(LinkQueue &Q,int p); int main(){LinkQueue Q;InitQueue(Q);int x,i,y,num=0,e;cout<<"请输入总人数:";cin>>x;for(i=1;i<=x;i++){EnQueue(Q,i);}cout<<"请输入第几个数淘汰:";cin>>y;{for(i=0;i<y;i++){if(i!=y-1){e=DeQueue(Q,e);EnQueue(Q,e);}else{DeQueue(Q,e);num++;}}if(num==x-1){break;}}e=DeQueue(Q,e);cout<<"最后剩下的是:"<<e<<endl;return 0;}int InitQueue(LinkQueue &Q){Q.front=new Qnode;Q.rear=Q.front;if(Q.front==NULL){exit(1);}Q.front->next=NULL;}void EnQueue(LinkQueue &Q,int x){Qnode *p=new Qnode;if(!p){exit(1);}p->num=x;p->next=NULL;Q.rear->next=p;}int DeQueue(LinkQueue &Q,int e) {Qnode *p;if(Q.rear==Q.front){exit(0);}p=Q.front->next;e=p->num;Q.front->next=p->next;if(Q.rear==p){Q.front=Q.rear;}delete p;return e;}*//*二叉树#include<iostream>#include<stdlib.h>using namespace std;typedef struct BiTNode{char date;struct BiTNode *lchild,*rchild; }BiTNode,*BiTree;void CreateBiTree(BiTree &T);int Depth(BiTree T);int NodeCount(BiTree T);int LeavesNodeCount(BiTree T);int PreOrderTraverse(BiTree T);int InOrderTraverse(BiTree T);int PostOrderTraverse(BiTree T); int main(){BiTree T;CreateBiTree(T);cout<<"二叉树的深度为:"<<Depth(T)<<endl;cout<<"二叉树中结点个数为:"<<NodeCount(T)<<endl;cout<<"二叉树中叶子结点个数为:"<<LeavesNodeCount(T)<<endl;cout<<"先序遍历:";PreOrderTraverse(T);cout<<"\n中序遍历:";InOrderTraverse(T);cout<<"\n后序遍历:";PostOrderTraverse(T);cout<<endl;return 0;}void CreateBiTree(BiTree &T){cout<<"请为该节点赋值:";char ch;cin>>ch;if(ch=='#'){T=NULL;}else{T =new BiTNode;T->date=ch;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}}int Depth(BiTree T){int m,n;if(T==NULL){return 0;}else{m=Depth(T->lchild);n=Depth(T->rchild);if(m>n){return m+1;}else{return n+1;}}}int NodeCount(BiTree T){if(T==NULL){return 0;}else{return NodeCount(T->lchild)+NodeCount(T->rchild)+1;}}int LeavesNodeCount(BiTree T){if(T==NULL){return 0;}else if(T->lchild==NULL && T->rchild==NULL){return 1;}else{return LeavesNodeCount(T->lchild)+LeavesNodeCount(T->rchild);}}int PreOrderTraverse(BiTree T){if(T!=NULL){cout<<T->date;PreOrderTraverse(T->lchild);PreOrderTraverse(T->rchild);}}int InOrderTraverse(BiTree T){if(T!=NULL){InOrderTraverse(T->lchild);cout<<T->date;InOrderTraverse(T->rchild);}}int PostOrderTraverse(BiTree T){if(T!=NULL){PostOrderTraverse(T->lchild);PostOrderTraverse(T->rchild);cout<<T->date;}}请为该节点赋值:-请为该节点赋值:+请为该节点赋值:a请为该节点赋值:#请为该节点赋值:#请为该节点赋值:*请为该节点赋值:b请为该节点赋值:#请为该节点赋值:#请为该节点赋值:-请为该节点赋值:c请为该节点赋值:#请为该节点赋值:#请为该节点赋值:d请为该节点赋值:#请为该节点赋值:#请为该节点赋值:/请为该节点赋值:e请为该节点赋值:#请为该节点赋值:#请为该节点赋值:f请为该节点赋值:#请为该节点赋值:#二叉树的深度为:5二叉树中结点个数为:11二叉树中叶子结点个数为:6先序遍历:-+a*b-cd/ef中序遍历:a+b*c-d-e/f后序遍历:abcd-*+ef/-Process returned 0 (0x0) execution time : 76.214 s Press any key to continue.*//*#include<iostream>#include<stdlib.h>#include<string.h>using namespace std;typedef struct{int weiget;int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char** HuffmanCode;void creat(HuffmanTree &HT,int n);void Select(HuffmanTree HT,int k,int &min1,int &min2); void creatcode(HuffmanTree HT,HuffmanCode &HC,int n); int min(HuffmanTree HT,int k);int main(){int n;cout<<"请输入叶子节点的个数:";cin>>n;HuffmanTree HT;creat(HT,n);HuffmanCode HC;creatcode(HT,HC,n);return 0;}void creat(HuffmanTree &HT,int n){if(n<1){exit(1);}int m=2*n-1,i;HT=new HTNode[m+1];for( i=1;i<=m;i++){HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for(i=1;i<=n;i++){cout<<"请输入权值:";cin>>HT[i].weiget;}int s1,s2;for(i=n+1;i<=m;i++) //通过n-1次选择来合并创建{Select(HT,i-1,s1,s2);HT[s1].parent=i; //赋值,作为删除的标记HT[s2].parent=i;cout<<"s1:"<<s1<<" s2:"<<s2<<endl;HT[i].lchild=s1; //生成新节点HT[i].rchild=s2;HT[i].weiget=HT[s1].weiget+HT[s2].weiget;}}void Select(HuffmanTree HT,int k,int &min1,int &min2){min1=min(HT,k);min2=min(HT,k);}int min(HuffmanTree HT,int k){int i=0;int min;//存放weight最小且parent为-1的元素的序号int min_wei;//存放权值while(HT[i].parent!=0){i++;}min_wei=HT[i].weiget;min=i;for(;i<=k;i++){if(HT[i].weiget<min_wei && HT[i].parent==0){min_wei=HT[i].weiget;min=i;}}HT[min].parent=1;return min;}void creatcode(HuffmanTree HT,HuffmanCode &HC,int n){HC =new char *[n+1];char *cd=new char[n];cd[n-1]='\0';int i,start;//start指向最后,即编码结束符的位置int current,father;for(i=1;i<=n;i++){start=n-1;current=i;father=HT[i].parent;while(father!=0){--start;if(HT[father].lchild==current){cd[start]='0';}else{cd[start]='1';}current=father;father=HT[father].parent;}HC[i]=new char[n-start];strcpy(HC[i],&cd[start]);cout<<HT[i].weiget<<"对应的编码是:"<<HC[i]<<endl;}delete cd;}请输入叶子节点的个数:5请输入权值:1请输入权值:2请输入权值:3请输入权值:4请输入权值:5s1:1 s2:2s1:3 s2:6s1:4 s2:5s1:7 s2:81对应的编码是:0102对应的编码是:0113对应的编码是:004对应的编码是:105对应的编码是:11Process returned 0 (0x0) execution time : 4.003 s Press any key to continue.*///折半查找#include<iostream>#include<stdio.h>using namespace std;#define ENDFLAG 10000typedef int KeyType;typedef char* InfoType;typedef struct{KeyType key;InfoType otherinfo;}ElemType;typedef struct{ElemType *R;int length;}SSTable;void CreateSTable(SSTable &ST,int n){int i;ST.R=new ElemType[n+1];for(i=1;i<=n;i++){cout<<"请输入"<<i<<"个测试数据:";cin>>ST.R[i].key;}ST.length=n;}int Search_Bin1(SSTable ST,KeyType key){int low,high,mid;low=1;high=ST.length;while(low<=high){mid=(low+high)/2;if(key==ST.R[mid].key){return mid;}else if(key<ST.R[mid].key){high=mid-1;}else{low=mid+1;}}return 0;}int Search_Bin2(SSTable ST,int low,int high,KeyType key) {int mid;if(low>high){return 0;}mid=(low+high)/2;printf("%d+++++",key==ST.R[mid].key);if(key==ST.R[mid].key){return mid;}else if(key<ST.R[mid].key){return Search_Bin2(ST,low,mid-1,key);}else{return Search_Bin2(ST,mid+1,high,key);}}int main(){int n;KeyType key;SSTable ST;cout<<"请输入静态查找表长:";cin>>n;CreateSTable(ST,n);cout<<"请输入待查记录的关键字:";cin>>key;cout<<"Search_Bin1算法计算的位置为:"<<Search_Bin1(ST,key)<<endl;cout<<"Search_Bin2算法计算的位置为:"<<Search_Bin2(ST,1,ST.length,key)<<endl;return 0;}/*请输入静态查找表长:5请输入1个测试数据:1请输入2个测试数据:2请输入3个测试数据:3请输入4个测试数据:4请输入5个测试数据:5请输入待查记录的关键字:3Search_Bin1算法计算的位置为:3Search_Bin2算法计算的位置为:3Process returned 0 (0x0) execution time : 8.620 sPress any key to continue.*//*#include<iostream>using namespace std;typedef struct{int key;}ElemType;typedef struct BSTNode{ElemType date;struct BSTNode *lchild,*rchild;}BSTNode,*BSTree;void Create(BSTree &T);void Insert(BSTree &T,ElemType e);int InOrderTraverse(BSTree T);int main(){BSTree T;Create(T);InOrderTraverse(T);cout<<"\n中序遍历:";return 0;}void Create(BSTree &T){T=NULL;ElemType e;cout<<"请为节点赋值:(0为结束条件)";cin>>e.key;while(e.key!=0){Insert(T,e);cout<<"请为节点赋值:(0为结束条件)";cin>>e.key;}}void Insert(BSTree &T,ElemType e){if(!T){BSTree S;S=new BSTNode;S->date=e;S->lchild=NULL;S->rchild=NULL;T=S;}else if(e.key<T->date.key){Insert(T->lchild,e);}else{Insert(T->rchild,e);}}int InOrderTraverse(BSTree T){if(T!=NULL){InOrderTraverse(T->lchild);cout<<T->date.key<<" ";InOrderTraverse(T->rchild);}return 0;}请为节点赋值:(0为结束条件)12请为节点赋值:(0为结束条件)7请为节点赋值:(0为结束条件)17请为节点赋值:(0为结束条件)11请为节点赋值:(0为结束条件)16请为节点赋值:(0为结束条件)2请为节点赋值:(0为结束条件)13请为节点赋值:(0为结束条件)9请为节点赋值:(0为结束条件)21请为节点赋值:(0为结束条件)4请为节点赋值:(0为结束条件)02 4 7 9 11 12 13 16 17 21中序遍历:Process returned 0 (0x0) execution time : 23.808 s Press any key to continue.*/。
数据结构 第9章 查找4-哈希表
7、随机数法 Hash(key) = random ( key ) (random为伪随机函数)
适用于:关键字长度不等的情况。造表和查找都很方便。
小结:构造哈希函数的原则:
① ② ③ ④ ⑤ 执行速度(即计算哈希函数所需时间); 关键字的长度; 哈希表的大小; 关键字的分布情况; 查找频率。
三、冲突处理方法
14 H(14)=14%7=0
6个元素用7个 地址应该足够!
1
2
23 9
3
4
39 25 11
5
6
H(25)=25%7=4 H(11)=11%7=4
有冲突!
在哈希查找方法中,冲突是不可能避免的,只能 尽可能减少。
所以,哈希方法必须解决以下两个问题:
1)构造好的哈希函数
(a)所选函数尽可能简单,以便提高转换速度; (b)所选函数对关键码计算出的地址,应在哈希地址集中 大致均匀分布,以减少空间浪费。
讨论:如何进行散列查找?
根据存储时用到的散列函数H(k)表达式,迅即可查到结果! 例如,查找key=9,则访问H(9)=9号地址,若内容为9则成功; 若查不到,应当设法返回一个特殊值,例如空指针或空记录。
缺点:空间效率低!
若干术语
哈希方法 (杂凑法)
选取某个函数,依该函数按关键字计算元素的存储位置, 并按此存放;查找时,由同一个函数对给定值k计算地址, 将k与地址单元中元素关键码进行比较,确定查找是否成 功。
3. 乘余取整法
4. 数字分析法
5. 平方取中法
常用的哈希函数构造方法有:
6. 折叠法
7. 随机数法
1、直接定址法
(a、b为常数) 优点:以关键码key的某个线性函数值为哈希地址, 不会产生冲突. 缺点:要占用连续地址空间,空间效率低。
(数据结构)括号匹配的检验(源代码)
数据结构括号匹配问题#include<stdio.h>#include<stdlib.h>#define TURE 1#define FALSE 0#define OK 1#define ERROR 0#define INEEASLIBE -1#define OVERFLOW -2typedef int status;typedef char elemtype;typedef struct{elemtype *data;int length;elemtype *top;}list;status creat(list &L){L.data=(elemtype*)malloc(2*sizeof(elemtype));if(!L.data){return ERROR;}L.top=L.data;L.length=1;return OK;}status push(list &L,elemtype e){elemtype *dat;dat=(elemtype*)realloc(L.data,(L.length+1)*sizeof(elemtype));if(!dat){return ERROR;}L.data=dat;L.length++;*(L.top)=e;L.top++;return OK;}status pop(list &L,elemtype &e){if(L.top==L.data){printf("\n已是堆低无数据元素\n");return ERROR;}L.top--;e=*(L.top);return OK;}main(){list L;creat(L);char a[20],b;int i=0,m=0;while(i<20){printf("请输入括号序列:('#'表示输入结束)\n");scanf("%c",&a[i]);getchar();if(a[i]=='#'){break;}if(a[i]=='('||a[i]==')'||a[i]=='['||a[i]==']'||a[i]=='{'||a[i]=='}'||a[i]== '<'||a[i]=='>'){i++;}else{printf("输入的不是括号字符\n请重新输入\n");}}m=i;i=0;while(i<m){if(a[i]==']'||a[i]==')'||a[i]=='}'){if(L.top==L.data){printf("括号匹配出错\n");exit(0);}else{pop(L,b);if((a[i]-b)!=2&&(a[i]-b)!=1){printf("括号匹配出错\n");exit(0);}}}elsepush(L,a[i]);i++;}if(L.data!=L.top)printf("括号匹配出错\n");elseprintf("\n\n括号匹配成功\n");}THANKS !!!致力为企业和个人提供合同协议,策划案计划书,学习课件等等打造全网一站式需求欢迎您的下载,资料仅供参考。
哈希表及其常用算法(代码实例)
哈希表及其常⽤算法(代码实例)<hash表的特性>Hash 表是使⽤ O(1) 时间进⾏数据的插⼊删除和查找,但是 hash 表不保证表中数据的有序性,这样在 hash 表中查找最或者最⼩数据的时间是 O(N) 。
<寻址和 hash 函数>理想状态下 hash ⾜够⼤,每⼀数据保存在⼀个 hash 存储单元内,这样对于插⼊删除和查找某⼀个数据就可以直接得到。
但是现实情况下 hash 表不可能⽆限⼤,⽽且理论上保存的数据的个数是没有限制的,这样保存的数据的数量就远远⼤于 hash 表的存储单元的数量。
为了实现在 O(1) 内对数据进⾏插⼊删除和查找,就必须将⼀个数据映射到 hash 表中的固定位置,这个映射函数就是 hash 函数。
Hash 函数通过对数据进⾏计算得到⼀个在 hash 表中的位置地址。
图 1.1 理想的 hash 表要选择较好的 hash 函数,以及 hash 表存储单元的数量,这样才能使保存在 hash 表中的数据均匀分布。
理想状态不太可能实现,由于存储的数据数量远远⼤于 hash 表存储单元的数量,所以再好的 hash 函数也可能使不同的数据得到相同的映射位置,这就造成了冲突。
但是好的 hash 函数可以将这种冲突降到最低。
<分离链接>解决这种冲突的第⼀种⽅法是借助链表来实现,就是将数据实际存放在与 hash 表存储单元相链接的链表中,⽽不是 hash 的存储单元中。
图 2.1 分离链表当产⽣冲突的时候,将两个数据都链接在同⼀ hash 存储单元保存的链表中。
当⼀个存储单元保存的链表中有多个数据的时候,对于链表后⾯的数据的查找添加和删除就是不是严格意义上的 O(1) 了。
⼀个好的 hash 函数可以使得这个链表很短。
最坏情况下,当所有的数据都保存在⼀个 hash 单元指定的链表中的时候,那么这个 hash 就和链表⼀样了。
<开放地址>使⽤开放地址⽅法解决冲突的时候,数据仍然保存在 hash 表的存储单元中,但是当冲突发⽣的时候,要再次计算新的地址。
c语言哈希表
c语言哈希表C语言哈希表是一种高效的数据结构,用于存储和查找数据。
哈希表是由两个基本部分组成的:哈希函数和哈希表。
哈希函数将输入的数据映射到哈希表中的位置,哈希表则将这些位置指向存储数据的桶。
哈希表的查询和插入操作经常介于常数时间和线性时间之间(O(1)到O(n))。
C语言哈希表的优点是:1. 哈希表的查询和插入操作都非常快。
由于哈希表利用哈希函数计算数据在数组中的位置,因此相同的数据总是查询到同一位置,无需比较元素,查询时间相对于其它数据结构较快。
2. 哈希表适合存储大量数据。
由于哈希表的查询和插入操作速度较快,因此适合存储大量数据,如大规模数据存储或快速索引。
3. 哈希表的数据分布随机性较高。
由于哈希函数根据输入值计算哈希地址,因此数据在哈希表中分布较随机,避免了因大量数据存储在同一桶中而导致的哈希冲突,从而提高哈希表的性能。
C语言哈希表的应用:1. 哈希表是编译器中符号表的基础。
编译器将程序源代码转化为汇编语言时,需要维护标识符(如变量、函数、结构体等)的定义和使用,这样运行时才能正确地访问这些标识符。
哈希表是符号表实现的基本数据结构。
2. 哈希表在代码编辑器和IDE工具中得到广泛应用。
当你输入代码后,编辑器将为你提供代码自动补全、方法跳转、代码格式化等功能,这些都需要在代码中查找标识符和用法。
哈希表可以帮助IDE快速索引代码库中的大量标识符。
3. 哈希表在数据库和缓存系统中应用广泛。
数据库需要存储大量数据,并且能够快速地检索、插入和删除数据。
缓存系统需要将数据存储在内存中,以便快速地访问。
在这些情况下,哈希表可以提供最快的访问速度和存储效率。
C语言哈希表的实现:在C语言中,哈希表的实现可以通过使用数组和链表实现桶,然后构造哈希函数来映射关键字到桶中。
具体实现过程如下:1. 定义哈希表结构体,包括总桶数、每个桶的大小、哈希函数等信息。
2. 定义哈希函数。
哈希函数根据输入的关键字生成一个哈希码,这个哈希码将关键字映射到哈希表中的一个位置。
c语言hashmap 查找方法
c语言hashmap 查找方法
在C语言中,实现哈希表(hashmap)的查找方法通常需要经历
以下步骤:
1. 哈希函数设计,首先,你需要设计一个哈希函数,它能够将
输入的键(key)映射到哈希表中的一个位置。
一个好的哈希函数应
该能够尽可能地均匀地将键映射到不同的位置,以减少冲突的发生。
2. 冲突处理,由于哈希函数的映射可能会导致不同的键映射到
同一个位置,因此需要一种方法来处理这种冲突。
常见的冲突处理
方法包括链地址法和开放寻址法。
在C语言中,你需要根据具体情
况选择合适的冲突处理方法,并实现相应的逻辑。
3. 查找操作:一旦哈希表中的数据经过哈希函数映射并存储起来,你就可以通过键来查找对应的数值。
在C语言中,通常可以通
过以下步骤来实现查找操作:
使用哈希函数计算键对应的哈希值。
根据哈希值找到对应的存储位置。
如果使用链地址法,需要遍历对应位置的链表来查找键;如果使用开放寻址法,需要根据特定的规则来寻找下一个位置,直到找到对应的键或者确定该键不存在。
4. 错误处理,在实现查找方法时,需要考虑键可能不存在的情况,因此需要实现相应的错误处理逻辑,以便在查找失败时能够返回适当的错误信息或者值。
总的来说,实现C语言中哈希表的查找方法需要考虑哈希函数设计、冲突处理、具体的查找逻辑以及错误处理。
这些步骤需要根据具体的应用场景和数据特点来进行合理的设计和实现。
希望这些信息能够帮助到你理解C语言中哈希表的查找方法。
详解数据结构之散列(哈希)表
详解数据结构之散列(哈希)表1.散列表查找步骤散列表,最有用的基本数据结构之一。
是根据关键码的值直接进行访问的数据结构,散列表的实现常常叫做散列(hasing)。
散列是一种用于以常数平均时间执行插入、删除和查找的技术,下面我们来看一下散列过程。
我们的整个散列过程主要分为两步:1.通过散列函数计算记录的散列地址,并按此散列地址存储该记录。
就好比麻辣鱼,我们就让它在川菜区,糖醋鱼,我们就让它在鲁菜区。
但是我们需要注意的是,无论什么记录我们都需要用同一个散列函数计算地址,然后再存储。
2.当我们查找时,我们通过同样的散列函数计算记录的散列地址,按此散列地址访问该记录。
因为我们存和取的时候用的都是一个散列函数,因此结果肯定相同。
刚才我们在散列过程中提到了散列函数,那么散列函数是什么呢?我们假设某个函数为f,使得存储位置= f (key) ,那样我们就能通过查找关键字不需要比较就可获得需要的记录的存储位置。
这种存储技术被称为散列技术。
散列技术是在通过记录的存储位置和它的关键字之间建立一个确定的对应关系 f ,使得每个关键字key 都对应一个存储位置f(key)。
见下图这里的 f 就是我们所说的散列函数(哈希)函数。
我们利用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间就是我们本文的主人公------散列(哈希)上图为我们描述了用散列函数将关键字映射到散列表。
但是大家有没有考虑到这种情况,那就是将关键字映射到同一个槽中的情况,即f(k4) = f(k3) 时。
这种情况我们将其称之为冲突,k3 和k4 则被称之为散列函数 f 的同义词,如果产生这种情况,则会让我们查找错误。
幸运的是我们能找到有效的方法解决冲突。
首先我们可以对哈希函数下手,我们可以精心设计哈希函数,让其尽可能少的产生冲突,所以我们创建哈希函数时应遵循以下规则:1.必须是一致的。
假设你输入辣子鸡丁时得到的是在看,那么每次输入辣子鸡丁时,得到的也必须为在看。
数据结构代码汇总
数据结构代码汇总数据结构代码汇总1.数组 (Array)●创建数组●访问数组元素●修改数组元素●数组长度●遍历数组●数组排序算法2.链表 (Linked List)●单向链表●创建链表●插入节点●删除节点●链表长度●遍历链表●双向链表●创建链表●插入节点●删除节点●链表长度●遍历链表3.栈 (Stack)●创建栈●入栈●出栈●栈顶元素●栈的大小●判断栈是否为空4.队列 (Queue)●创建队列●入队●出队●队首元素●队列大小●判断队列是否为空5.哈希表 (Hash Table)●创建哈希表●哈希函数●插入元素●删除元素●查找元素●哈希表大小●哈希表是否为空6.树 (Tree)●二叉树 (Binary Tree)●创建二叉树●插入节点●删除节点●遍历二叉树 (前序、中序、后序)●二叉树的高度●二叉搜索树 (Binary Search Tree)●创建二叉搜索树●插入节点●删除节点●查找节点●遍历二叉搜索树 (中序)●二叉搜索树的高度●平衡二叉树 (AVL Tree)●创建平衡二叉树●插入节点●删除节点●遍历平衡二叉树 (前序、中序、后序)●平衡二叉树的高度●红黑树 (Red-Black Tree)●创建红黑树●插入节点●遍历红黑树 (中序)●红黑树的高度7.图 (Graph)●创建图●添加顶点●添加边●删除顶点●删除边●广度优先搜索 (BFS)●深度优先搜索 (DFS)●图的连通性●最短路径算法 (Dijkstra、Floyd-Warshall)●最小树算法 (Prim、Kruskal)8.堆 (Heap)●创建堆●插入元素●堆的大小●堆排序9.字典树 (Trie)●创建字典树●插入单词●查找单词●删除单词●字典树中的前缀数量●字典树中的单词数量10.图算法 (Graph Algorithms)●拓扑排序●强连通分量 (SCC)●最短路径算法 (Dijkstra、Bellman-Ford)●最小树算法 (Prim、Kruskal)●最大流算法 (Ford-Fulkerson、Edmonds-Karp)本文档涉及附件:附件1:数组代码实现示例附件2:链表代码实现示例附件3:栈代码实现示例附件4:队列代码实现示例附件5:哈希表代码实现示例附件6:树代码实现示例附件7:图代码实现示例附件8:堆代码实现示例附件9:字典树代码实现示例附件10:图算法代码实现示例本文所涉及的法律名词及注释:1.数组 (Array):在计算机科学中,是一种由固定数量元素组成的集合。
五元组hash算法python代码
一、概述在计算机科学中,哈希算法是一种将输入数据转换为固定大小值的算法。
它被广泛应用于密码学、数据完整性验证和数据检索等领域。
而五元组hash算法是一种特定的哈希算法,其将数据以五个元素的形式进行哈希处理。
二、五元组hash算法原理五元组hash算法的原理是将数据以五个元素的形式表示,然后将这五个元素作为输入进行哈希计算,得到一个固定大小的哈希值。
这个哈希值可以用作数据的唯一标识符,也可以用来确保数据的完整性和一致性。
在五元组hash算法中,通常使用的五个元素包括源IP位置区域、目标IP位置区域、源端口号、目标端口号和协议类型。
这五个元素能够完整地描述一次网络通信的会话信息,因此非常适合用来进行哈希计算。
三、五元组hash算法Python代码实现下面是一个简单的五元组hash算法的Python代码实现:```pythonimport hashlibdef five_tuple_hash(source_ip, destination_ip, source_port, destination_port, protocol):data = source_ip + destination_ip + str(source_port) +str(destination_port) + protocolhash_value = hashlib.sha256(data.encode()).hexdigest()return hash_value```在这段代码中,我们首先使用了Python内置的hashlib库,然后定义了一个名为five_tuple_hash的函数。
这个函数接收源IP位置区域、目标IP位置区域、源端口号、目标端口号和协议类型等五个参数作为输入。
我们将这五个参数拼接成一个字符串,并使用SHA-256哈希算法对这个字符串进行哈希计算。
我们返回了计算得到的哈希值作为函数的返回值。
四、五元组hash算法Python代码的使用以下是一个简单的示例,展示了如何使用上述的五元组hash算法Python代码:```pythonsource_ip = '192.168.1.1'destination_ip = '192.168.1.2'source_port = xxxdestination_port = 80protocol = 'TCP'hash_value = five_tuple_hash(source_ip, destination_ip, source_port, destination_port, protocol)print(f"The hash value for the given five-tuple is: {hash_value}") ```在这个示例中,我们先设置了源IP位置区域、目标IP位置区域、源端口号、目标端口号和协议类型等五个参数的取值,然后调用了five_tuple_hash函数来计算这个五元组的哈希值。
uthash用法
uthash用法UTHASH 是一个用C 语言编写的哈希表和链表的数据结构库,它通过提供高度优化的代码和易于使用的API,为开发人员提供了一种快速而灵活的方法来管理大量数据。
UTHash 同时支持哈希表和链表两种数据结构,使其成为处理各种数据集的理想选择。
在本文中,我将详细介绍如何使用UTHASH 库来实现一个简单的哈希表。
我会从引入UTHASH 开始,然后逐步解释如何定义结构体、插入和查找元素,并最后介绍一些用于删除元素和释放内存的有用函数。
首先,我们需要从UTHASH 的Github 页面(UTHASH 的源代码。
然后,我们可以将源代码文件直接包含到我们的项目中。
接下来,我们需要定义一个结构体来存储我们要存储的数据。
假设我们要存储学生的信息,我们可以定义一个名为Student 的结构体,如下所示:#include "uthash.h"typedef struct {int id;char name[100];char major[100];UT_hash_handle hh;} Student;在这个结构体中,我们定义了三个成员变量:id、name 和major,分别表示学生的学号、姓名和专业。
UT_hash_handle 是UTHASH 库中定义的一个特殊成员变量,用于管理哈希表的指针。
接下来,我们需要定义一个哈希表和一个用于插入和查找元素的函数。
首先,我们需要定义一个指向哈希表的指针:Student *students = NULL;接下来,我们可以定义一个插入函数来将学生信息插入哈希表中:void insert_student(int id, const char *name, const char *major) { Student *s = malloc(sizeof(Student));s->id = id;strcpy(s->name, name);strcpy(s->major, major);HASH_ADD_INT(students, id, s);}在这个函数中,我们首先分配了一个Student 结构体的内存,并将传入的参数赋值给结构体的成员变量。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构哈希查找
源代码:
#include<iostream>
#include<cmath>
using namespace std;
#define SUCCESS 1;
#define UNSUCCESS 0;
#define NULLKEY -1;
#define TableLength 13;
#define p 13;// H(key)=key % p
typedef int T;
template <class T>
struct ElemType
{
T key;//关键字
/* //其它
....
*/
};
template <class T>
class LHSearch
{
private:
ElemType<T> *HT; //开放定址哈希表
int count; //当前数据元素个数
int size; //哈希表长度
public:
LHSearch(); //
~LHSearch(); //
void InitHashTable(int n);//
int Hash(T key); //计算哈希地址
void Collision(int &s);//冲突,计算下一个地址
int Search(T key,int &s);//哈希查找
int Insert(ElemType<T> e); //元素插入
void Display(); //显示哈希表
};
template <class T>
LHSearch<T>::LHSearch()
{
HT=NULL;
size=0;
count=0;
}
template <class T>
LHSearch<T>::~LHSearch()
{ delete [] HT;
count=0;
}
template <class T>
int LHSearch<T>::Hash(T key)
{//由哈希函数求哈希地址
return key%p;
}
template <class T>
void LHSearch<T>::Collision(int &s)
{//开放定址法解决冲突
s=s++;
}
template <class T>
int LHSearch<T>::Search(T key,int &s)
{//查找,找到返回
//int s;
s=Hash(key);
while((HT[s].key!=-1) && (key!=HT[s].key)) Collision(s);
if(HT[s].key==key)
return 1;
else
return 0;
}
template <class T>
int LHSearch<T>::Insert(ElemType<T> e)
{//插入元素
int s;
if(count==size)
{
cout<<"表满,不能插入!"<<endl;
return UNSUCCESS;
}
else
{
s=Hash(e.key);
int f;
f=Search(e.key,s);
if(f) //表中已有和e的关键字相同的元素,不进行插入操作
{
cout<<"该元素已存在,不能插入!"<<endl;
return UNSUCCESS; }
else
{
HT[s].key=e.key;
cout<<"插入成功!"<<endl;
count++;
return SUCCESS; }
}
}
template<class T>
void LHSearch<T>::InitHashTable(int n)
{
size=n;
HT=new ElemType<T>[size];
for(int i=0;i<size;i++) //初始化,把哈希表置空
HT[i].key=NULLKEY;
}
template<class T>
void LHSearch<T>::Display()
{
for(int i=0;i<size;i++)
{
cout<<i<<'\t';
if(HT[i].key!=-1)
cout<<HT[i].key;
else
cout<<'\t';
cout<<endl;
}
}
void main()
{
int m;
T key;
int s=0;
ElemType<int> e;
LHSearch<int> a;
cout<<"输入相应代码,必须先创建哈希表)\n";
do {
cout<<"--- 1. 创建查找表--\n"
<<"--- 2. 插入----------\n"
<<"--- 3. 查找----------\n"
<<"--- 4. 显示---------\n"
<<"--- 5. 退出---------\n"
<<"请选择操作:";
cin>>m;
switch(m)
{
case 1://创建查找表
cout<<"请输入表容量:\n";
cin>>m;
a.InitHashTable(m);
cout<<"依次输入表元素,-1结束:\n";
for(cin>>e.key;e.key!=-1;cin>>e.key)
a.Insert(e);
break;
case 2: //插入元素
cout<<"输入元素:\n";
cin>>e.key;
a.Insert(e);
break;
case 3: //查找
cout<<"请输入查找关键字:\n";
cin>>key;
if(a.Search(key,s))
cout<<"找到!\n";
else
cout<<"不存在,末找到!\n";
break;
case 4://显示哈希表
a.Display();
break;
case 5://
cout<<"结束!\n";
break;
}
}while(m!=5); }。