C++减少过多if判断的一种思路

本文介绍了一种使用C++11新特性减少if-else判断的方法,通过将判断和处理逻辑封装进函数对,并利用vector和lambda表达式进行遍历处理,有效简化了代码并提高了可读性。

有时候if判断会写很多,代码写很长

如果if判断的层次很简单,只是if-else这种结构,读起来不会觉得有多么困难,只是很长而已;麻烦的是有很多嵌套(当然这是可以优化的);

优化的好,其实并不会太影响阅读;但对于有强迫症的人,if写太多,心理就是觉得不舒服。

网上有很多利用设计模式的方法处理过多的if判断的的文章。只是要写很多类,构造函数什么的,麻烦!

利用C++中的function,pair,vector和lambda表达式

最近我也有减少if的冲动,看到一个叫“麦片说”的人在2013-11-30写的博客(http://ju.outofmemory.cn/entry/56050),采用C++11新特性,将判断和处理封装成一对函数,将这一对函数放入链表中,通过遍历链表来实现判断,确实代码量减少了,逻辑清晰了,但该文章的代码,在VS2010下编译未通过。

现将我在VS2010环境下编译通过的代码贴出,留作速查;只是在细节上做了变化,思路完全未改变。

// testProcessIfelse.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <cstdio>
#include <vector>
#include <functional>

using namespace std;
//helper function
typedef std::pair<std::function<bool(int)>
                 ,std::function<void(void)>> IfDoPair;
//指向类型为IfDoPair的对象的指针P_IfDoPair;
typedef std::shared_ptr<IfDoPair> P_IfDoPair;
typedef std::vector<P_IfDoPair> IfDoContainer;
IfDoContainer allcases;

template<typename F1, typename F2>
void add_case(F1& judgeFunc, F2& doFunc)
{
    auto ifDoPair = std::make_shared<IfDoPair>(judgeFunc,doFunc);
    allcases.push_back(ifDoPair);
}

int _tmain(int argc, _TCHAR* argv[])
{
    //add all cases
    add_case([](int nPara1){return nPara1 > 0 && nPara1<= 10;},
        [](){std::cout<<"show 1";});


    add_case([](int nPara1){return nPara1 > 11 && nPara1<= 20;},
        [](){std::cout<<"show 2";});

    //replace if-else
    int nJudgeNumber = 15;
    for(IfDoContainer::iterator it = allcases.begin(); it!=allcases.end(); it++)
    {
        if((*it)->first(nJudgeNumber))
        {
            (*it)->second();
        }
    }

    int nPause = 0;
    std::cin>>nPause;
    return 0;
}

当然具体问题还需具体研究,没有通用公式

由于要通过vector进行遍历,所以每一个判断函数的参数个数和类型应当保持一致。如果每一个判断的条件都有很大差异的话,上述方法应该作用没有那么明显。当然分离判断与处理为2个不同的函数的思路是非常有用的,以后可以举一反三。请注意,我是在VS2010下,创建控制台程序测试的,需要了解C++11的这几个新特性。

<think>我们已有用户的问题:使用C++利用哈希表判断哈希表中是否有已知全部元素的方法。 根据之前的回答(Python版本)和用户提供的引用(主要是C++相关的引用),我们需要用C++实现类似功能。 步骤: 1. 理解需求:判断一个哈希表(比如C++中的std::unordered_set或std::unordered_map)是否包含一个给定集合中的所有元素。 2. 方法:遍历给定的集合,检查每个元素是否在哈希表中。如果所有元素都在,则返回true;否则,返回false。 用户提供的引用中: 引用[1]提到:哈希表用来快速判断一个元素是否出现在集合里。 引用[2]展示了一个C++哈希表查找的实现(线性探测的开放寻址法)。 引用[3]展示了用拉链法实现的哈希表及其查找。 我们可以使用C++标准库中的std::unordered_set(如果只需要判断存在性)或者std::unordered_map(如果需要存储键值对)来实现。 这里我们假设有两种情况: 情况一:使用std::unordered_set(最简单,因为只需要存储键) 情况二:使用用户自定义的哈希表(如引用[2]或[3]中的实现) 但是,为了通用性,我们首先使用C++标准库的std::unordered_set。 另外,用户提到“判断哈希表中有已知的全部元素”,注意是“全部元素”,所以需要遍历已知元素集合。 实现步骤: 1. 创建一个哈希表(可以是std::unordered_set或std::unordered_map)并插入一些元素。 2. 给定一个要检查的元素集合(比如std::vector或数组)。 3. 遍历这个集合,对每个元素检查它是否在哈希表中。 如果使用std::unordered_set,代码示例: 注意:如果使用std::unordered_map,我们通常只检查键是否存在,可以用map的find方法或者count方法。 下面我们将分别用std::unordered_set和std::unordered_map来实现。 另外,如果用户希望使用自定义的哈希表(如引用[2]或[3]),我们也可以提供一个自定义哈希表的版本,但通常标准库已经足够。 我们首先使用标准库。 方案一:使用std::unordered_set 方案二:使用std::unordered_map(检查键) 方案三:自定义哈希表(拉链法或开放寻址法) 由于用户引用中提供了两种自定义哈希表的实现(引用[2]是开放寻址法,引用[3]是拉链法),我们可以选择其中一种来实现。但为了简洁,我们主要使用标准库,然后简要展示自定义哈希表的思路。 下面给出代码示例: 1. 使用std::unordered_set 2. 使用std::unordered_map(只检查键) 3. 自定义哈希表(以拉链法为例,因为引用[3]的代码更完整) 同时,我们也要考虑给定集合中可能有重复元素的情况,但哈希表本身是无重复的,所以我们需要先对给定集合去重吗?实际上,如果给定集合有重复元素,那么重复元素只要在哈希表中出现一次即可。所以我们可以不去重,因为重复元素每次查找都会成功。当然,如果希望效率更高,可以先对目标集合去重,但一般情况下目标集合不大,不去重也可以。 具体实现: </think>### 使用C++哈希表判断是否包含全部元素的方法 在C++中,可以通过遍历已知元素集合并利用哈希表的快速查找特性(平均 O(1) 时间复杂度)判断哈希表是否包含所有元素。以下是三种实现方法: --- #### 方法1:使用STL的`unordered_set`(推荐) ```cpp #include <iostream> #include <unordered_set> #include <vector> using namespace std; bool contains_all(const unordered_set<int>& hash_table, const vector<int>& elements) { for (int elem : elements) { // 哈希查找:平均O(1),最坏O(n) if (hash_table.find(elem) == hash_table.end()) { return false; } } return true; } int main() { unordered_set<int> hash_table = {10, 20, 30, 40, 50}; vector<int> target1 = {20, 30}; // 全部存在 vector<int> target2 = {20, 60}; // 60缺失 cout << boolalpha; cout << contains_all(hash_table, target1) << endl; // 输出: true cout << contains_all(hash_table, target2) << endl; // 输出: false } ``` **说明**: 1. `hash_table.find(elem)` 查找元素 [^1] 2. 若返回`end()`迭代器表示元素不存在 [^2] 3. 平均时间复杂度:$O(n)$(n为元素集合大小) --- #### 方法2:使用STL的`unordered_map`(需检查键) ```cpp bool contains_all_map(const unordered_map<int, int>& hash_map, const vector<int>& elements) { for (int elem : elements) { if (!hash_map.count(elem)) { // 检查键是否存在 return false; } } return true; } ``` --- #### 方法3:自定义哈希表(拉链法) 参考引用[3]实现拉链法哈希表,扩展查找功能: ```cpp const int MOD = 170001; // 哈希表大小(质数减少冲突) struct HashTable { vector<int> h = vector<int>(MOD, 0); vector<int> pre, nxt; int cnt = 0; void add(int x) { int tmp = x % MOD; pre.push_back(x); nxt.push_back(h[tmp]); h[tmp] = cnt++; } bool find(int x) { int tmp = x % MOD; for (int i = h[tmp]; i != 0; i = nxt[i]) { if (pre[i] == x) return true; } return false; } bool contains_all(vector<int>& elements) { for (int elem : elements) { if (!find(elem)) return false; } return true; } }; // 用法示例 HashTable custom_table; custom_table.add(10); custom_table.add(20); vector<int> check_list = {10, 20}; cout << custom_table.contains_all(check_list); // 输出: 1 (true) ``` --- ### 关键点解析 1. **查找原理**: - 哈希表通过哈希函数定位桶(bucket) - 在桶内线性查找元素(开放寻址法/拉链法)[^2][^3] 2. **时间复杂度**: - 平均情况:$O(n)$(n为元素个数) - 最坏情况:$O(n \times k)$(k为桶内元素数,冲突过多时) 3. **优化建议**: - 使用质数大小的哈希表减少冲突[^3] - 自定义哈希函数优化元素分布 - 冲突严重时转换为红黑树(如STL实现) > 当遇到“判断元素是否存在集合中”的问题时,哈希表通常是首选数据结构[^1]。其核心优势是将集合成员检测从 $O(n)$ 降至平均 $O(1)$,特别适合大规模数据查询。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值