哈希表和有序表的使用

目录

哈希表

哈希表的增、查操作

对哈希表的修改、删除操作

有序表

有序表的增删改查操作

有序表排序功能的简单操作


哈希表

从时间复杂度的角度来看,哈希表的优势之处在于无论表中有多少条数据,其增删改查所耗费的时间复杂度是O(1)常数级别

注:这里的常数时间是一个较大的时间,即比常规的加减法等操作时间大。

哈希表的增、查操作

        //创建一个哈希表 (K V)
        HashMap<String,String> map = new HashMap<>();
        //map.put(),增加/修改数据
        map.put("super","爱坤");
		//map.containsKey()    判断map中是否存在K == "super",存在则返回true
        System.out.println(map.containsKey("super"));
		//map.containsValue()    判断map中是否存在V == "爱坤",存在则返回true
        System.out.println(map.containsValue("爱坤"));
		//map.get()   得到map中 K值 所对应的 V值
        System.out.println(map.get("super"));

输出结果如下:

true
true
爱坤

值得注意的是:对于哈希表的查操作,所查询的并非是某个变量的内存地址,这里将直接查找变量的内容。举个例子:

        map.put("super","爱坤");
        String a = "super";
        String b = "super";
        System.out.println(map.get(a));
        System.out.println(map.get(b));
		System.out.println(map.containsKey(a));
        System.out.println(map.containsKey(b));
        
        //返回结果
        爱坤
		爱坤
        true
		true    

尽管a和b的内存地址不同,但返回的结果依旧相同。

注:这里尽针对于原生类;若为自定义类,则需另作说明。

对哈希表的修改、删除操作

        map.put("super","爱坤");
        System.out.println(map.get("super"));
        
        //修改K==“super”所对应的value值
        map.put("super","小黑子");
        System.out.println(map.get("super"));
        
        //删除“super”及其value值,返回null
        map.remove("super");
        System.out.println(map.get("super"));
        

输出结果如下:

爱坤
小黑子
null

有序表

基本操作与哈希表类似;有序表的一个最大的优点是:可以对key的值进行排序。(这里讲述的是原生类的排序)

从算法时间性能的角度上看:有序表的每一次增删改查操作是O(logn)级别的。

有序表的增删改查操作

TreeMap<Integer, String> trMap = new TreeMap<>();
        //增添数据
		TreeMap<Integer, String> trMap = new TreeMap<>();
        trMap.put(5,"我是5");
        trMap.put(2,"我是2");
        trMap.put(7,"我是7");
        trMap.put(0,"我是0");
        trMap.put(3,"我是3");
		//查询数据
        System.out.println("查表中是否有5:"+trMap.containsKey(5));
        System.out.println("查表中是否有6:"+trMap.containsKey(6));
        System.out.println("5所对应的value值是:"+trMap.get(5));
        System.out.println("-----------------");
        //修改数据
		trMap.put(5,"他是5");
        System.out.println("修改后5所对应的value值是:"+trMap.get(5));
        //删除数据
		trMap.remove(5);
        System.out.println("删除后5所对应的value值是:"+trMap.get(5));

输出结果:

查表中是否有5:true
查表中是否有6:false
5所对应的value值是:我是5
-----------------
修改后5所对应的value值是:他是5
删除后5所对应的value值是:null

有序表排序功能的简单操作

TreeMap<Integer, String> trMap = new TreeMap<>();
        trMap.put(5,"我是5");
        trMap.put(2,"我是2");
        trMap.put(7,"我是7");
        trMap.put(0,"我是0");
        trMap.put(3,"我是3");

        System.out.println("输出表中第一个key:"+trMap.firstKey());
        System.out.println("输出表中最后一个key:"+trMap.lastKey());
        System.out.println("输出表中<=5离5最近的key:"+trMap.floorKey(5));
        System.out.println("输出表中>=6离6最近的key:"+trMap.ceilingKey(6));

输出结果:

输出表中第一个key:0
输出表中最后一个key:7
输出表中<=5离5最近的key:5
输出表中>=6离6最近的key:7

舞台再大,你不上台,永远是个观众。平台再好,你不参与,永远是局外人。

<think> 我们被问到“哈希表有序表吗”,需要首先明确哈希表的特性。哈希表(Hash Table)是一种根据键(Key)直接访问内存存储位置的数据结构,它通过哈希函数将键映射到表中的某个位置来实现快速的数据访问。然而,哈希表本身并不保证元素的顺序。在大多数实现中,元素的存储顺序取决于哈希函数解决冲突的方法(如链地址法或开放寻址法),因此遍历哈希表时元素的顺序通常是不确定的。 但是,有些编程语言提供了同时具有哈希表快速访问特性有序性的数据结构,例如Java中的LinkedHashMap或Python中的OrderedDict(在Python 3.7+中,字典默认保持插入顺序)。这些数据结构通过额外的链表或其他机制来维护元素的插入顺序或访问顺序。 因此,回答这个问题需要分情况讨论: 1. 标准哈希表:无序,不保证元素的顺序(插入顺序、键的顺序等)。 2. 特殊实现的哈希表:如有序哈希表(比如Java的LinkedHashMap),可以维护插入顺序或访问顺序。 所以,我们回答:通常情况下,哈希表不是有序表,但可以通过特殊实现使其有序。 接下来,按照要求,在回答后提出3-5个相关问题。注意,问题必须与用户的问题我们的回答相关。 我们可以提出如下问题: 1. 哈希表在哪些场景下需要有序? 2. 如何实现一个有序的哈希表? 3. 有序哈希表与普通哈希表在性能上有何差异? 4. 在常见编程语言中(如Python、Java),哈希表默认是有序的吗? 注意:必须用“§§相关问题§§”开头,然后列出问题,禁止换行分散。 因此,完整的回答如下: </think> 哈希表通常**不是有序表**。其核心特性如下: ### 无序性本质 1. **存储机制** 数据位置由哈希函数(`hash_key % size`)决定,与插入顺序或键值大小无关 ```c /* 计算存储位置 */ unsigned int key = (*hash->hash_key)(data); unsigned int index = key % hash->size; // 位置随机分布 ``` 2. **遍历顺序** 迭代时按桶索引顺序访问(非键值顺序): ```c void hash_iterate(struct hash *hash, void (*func)(...)){ for (i = 0; i < hash->size; i++) // 按桶索引遍历 for (hb = hash->index[i]; hb; hb = hbnext) ... } ``` ### 有序化实现方案 若需有序访问,可通过以下扩展实现: ```c /* 有序哈希表扩展结构 */ struct ordered_hash { struct hash *hash; // 基础哈希表 struct list *key_list; // 维护键的有序链表 }; /* 插入时同步记录顺序 */ void ordered_hash_insert(...){ hash_get(oh->hash, data, alloc_func); list_add_tail(oh->key_list, data); // 链表尾部追加 } /* 有序迭代 */ void ordered_hash_iterate(...){ struct listnode *node; for (node = oh->key_list->head; node; node = node->next) { void *data = node->data; func(data, arg); // 按插入顺序处理数据 } } ``` ### 典型场景对比 | 特性 | 标准哈希表 | 有序哈希扩展 | |-------------|---------------------|-------------------| | **插入顺序** | ❌ 不保留 | ✅ 链表记录顺序 | | **键值排序** | ❌ 不保证 | ✅ 可排序链表维护 | | **查找速度** | ⚡️ O(1) 平均 | ⚡️ O(1) 查找 | | **遍历速度** | ⚡️ O(n) | 🐢 O(n)+链表开销 | | **内存开销** | 较低 | 增加链表存储空间 | ### 使用建议 1. **无需顺序的场景** 直接使用基础哈希表(最高效) 2. **需要插入顺序的场景** 增加链表维护(如Java `LinkedHashMap`) 3. **需要键值排序的场景** 改用红黑树(如C++ `std::map`)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

superzheng__

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

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

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

打赏作者

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

抵扣说明:

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

余额充值