C++ STL unordered_set使用

C++ unordered_set/multiset使用

概述

  • unordered_set 与 unordered_multiset 都定义于头文件<unordered_set>
  • unordered_set 是含有 Key 类型唯一对象集合的关联容器。搜索、插入和移除拥有平均常数时间复杂度。
  • unordered_multiset 是含有 Key 类型不唯一对象集合的关联容器。
  • unordered_set 与 unordered_multiset 成员函数及非成员函数使用方法相同,只是在 insert 函数内部,unordered_set 调用 insert_unique 函数不允许键重复,而 unordered_multiset 调用 insert_equal 函数允许键重复。
  • 在内部,元素并不以任何特别顺序排序,而是组织进桶中。元素被放进哪个桶完全依赖其值的哈希。这允许对单独元素的快速访问,因为哈希一旦确定,就准确指代元素被放入的桶。

类模板:

template<
    class Key,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator<Key>
> class unordered_set;

创建unordered_set

构造函数

  • 与set大致相同。

opertor=

  • 赋值给容器
    定义:
unordered_set& operator=( const unordered_set& other );	// 复制赋值运算符。
unordered_set& operator=( unordered_set&& other );	// 移动赋值运算符。
unordered_set& operator=( std::initializer_unordered_set<T> iunordered_set ); // 以 initializer_unordered_set iunordered_set 所标识者替换内容。

用法:

    std::unordered_set<int> nums1 {3, 1, 4, 6, 5, 9};
    std::unordered_set<int> nums2;
    std::unordered_set<int> nums3;

    // 从 nums1 复制赋值数据到 nums2
    nums2 = nums1;
    // 从 nums1 移动赋值数据到 nums3,
    nums3 = std::move(nums1);
    // initializer_unordered_set 的复制赋值复制数据给 nums1
    nums1 = {1, 2, 3};

迭代器

begin\cbegin

在这里插入图片描述

  • 返回指向 unordered_set 首元素的迭代器。
  • cbegin中的c表示const,即返回const_iterator,不允许通过迭代器修改元素。
  • 若 unordered_set 为空,则返回的迭代器将等于 end() 。

定义:

iterator begin();
const_iterator cbegin() const noexcept;

end\cend

  • 返回指向 unordered_set 末元素后一元素的迭代器。

定义:

iterator end();
const_iterator cend() const noexcept;

容量

empty

  • 检查容器是否无元素,即是否 begin() == end() 。

定义:

bool empty() const;

用法:

	std::unordered_set<int> v;
	bool flag = v.empty();	// 输出 true

size

  • 返回容纳的元素数。 即 std::distance(begin(), end()) 。

定义:

size_type size() const;

用法:

	std::unordered_set<int> nums {1, 3, 5, 7};
    std::cout << nums.size() << std::endl;	// 输出 4

max_size

  • 返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。

定义:

size_type max_size() const;

用法:

	std::unordered_set<int> vi;
	std::cout << vi.max_size() << std::endl;	// 可能输出 4611686018427387903
	std::unordered_set<char> vc;
	std::cout << vc.max_size() << std::endl;	// 可能输出 18446744073709551615

修改器

clear

  • 从容器擦除所有元素。此调用后 size() 返回零。
  • 非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器亦被非法化。

定义:

void clear();

用法:

	std::unordered_set<int> container{1, 2, 3};
	container.clear();
	std::cout << container.size() << std::endl;		// 输出 0

insert

  • 插入元素或结点

定义:

std::pair<iterator,bool> insert( const value_type& value );

std::pair<iterator,bool> insert( value_type&& value );

template< class InputIt >
void insert( InputIt first, InputIt last );

void insert( std::initializer_list<value_type> ilist );

用法:

    std::unordered_set<int> a;
 	
 	a.insert(4);

	std::unordered_set<int> b { 7, 8, 9 };
	a.insert(b.begin(), b.end());
	
 	a.insert({ 1, 2, 3 });

emplace

  原位构造元素
定义:

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );;

emplace_hint

  • 使用提示原位构造元素
  • 返回值
      返回指向新插入元素的迭代器。
      若因元素已存在而插入失败,则返回指向拥有等价关键的既存元素的迭代器。

定义:

template <class... Args>
iterator emplace_hint( const_iterator hint, Args&&... args );

erase

  • 从容器擦除指定的元素。

定义:

// 1、移除位于 pos 的元素。
iterator erase( iterator pos );

// 2、移除范围 [first; last) 中的元素。
iterator erase( iterator first, iterator last );

// 3、移除关键等于 key 的元素(若存在一个)。
size_type erase( const key_type& key )

用法:

#include <unordered_set>
#include <iostream>
int main()
{
	std::unordered_set<int> c = { 8, 1, 2, 4, 5, 7, 9, 6, 3 };
	// 从 c 擦除所有奇数
	for (auto it = c.begin(); it != c.end(); )
		if (*it % 2 == 1)
			it = c.erase(it);
		else
			++it;
	for (int n : c)
		std::cout << n << ' ';
}
     // c : 8 2 4 6 

swap

  • 交换内容

定义:

void swap( unordered_set& other );

用法:

	std::unordered_set<int> a1{1, 2, 3}, a2{4, 5};
	a1.swap(a2);

extract

  • 从另一容器释出结点 C++17

定义:

// 解链含 position 所指向元素的结点并返回占有它的结点柄。
node_type extract( const_iterator position );

// 若容器拥有元素而其关键等于 x ,则从容器解链该元素并返回占有它的结点柄。否则,返回空结点柄。
node_type extract( const key_type& x );

merge

  • 从另一容器接合结点 C++17

定义:

template<class C2>
void merge( std::unordered_set<Key, C2, Allocator>& source );

template<class C2>
void merge( std::unordered_set<Key, C2, Allocator>&& source );

用法:

    std::unordered_set<char>
        p{ 'C', 'B', 'B', 'A' }, 
        q{ 'E', 'D', 'E', 'C' };
 
    p.merge(q);

// p:  { E, D, A, B, C }
// q:  { C }

查找

count

  • 返回匹配特定键的元素数量
  • 返回拥有关键比较等价于指定参数的元素数,因为此容器不允许重复故为 1 或 0。

定义:

size_type count( const Key& key ) const;

find

  • 寻找带有特定键的元素
  • 返回值
      指向键等于 key 的元素的迭代器。若找不到这种元素,则返回尾后(见 end() )迭代器。

定义:

iterator find( const Key& key );
const_iterator find( const Key& key ) const;

用法:

	std::unordered_set<int> example = {1, 2, 3, 4};
 
    auto search = example.find(2);
    if (search != example.end()) {
        std::cout << "Found " << (*search) << '\n';
    } else {
        std::cout << "Not found\n";
    }

contains

  • 检查容器是否含有带特定键的元素
  • 若有这种元素则返回 true ,否则返回 false

定义:

bool contains( const Key& key ) const;

template< class K > bool contains( const K& x ) const;

用法:

	std::unordered_set<int> example = {1, 2, 3, 4};
 
    for(int x: {2, 5}) {
        if(example.contains(x)) {
            std::cout << x << ": Found\n";
        } else {
            std::cout << x << ": Not found\n";
        }
    }

equal_range

  • 返回匹配特定键的元素范围
  • 返回容器中所有键等于 key 的元素范围。范围以二个迭代器定义,第一个指向所需范围的首元素,而第二个指向范围的尾后一位元素

定义:

std::pair<iterator,iterator> equal_range( const Key& key );

桶接口

begin、cbegin

  • 返回一个迭代器,指向指定的桶的开始
local_iterator begin( size_type n );
const_local_iterator begin( size_type n ) const;
const_local_iterator cbegin( size_type n ) const;

end、cend

  • 返回一个迭代器,指向指定的桶的末尾
local_iterator end( size_type n );
(C++11)
const_local_iterator end( size_type n ) const;
const_local_iterator cend( size_type n ) const;

bucket_count

  • 返回桶数
size_type bucket_count() const;

max_bucket_count

  • 返回桶的最大数量
size_type max_bucket_count() const;

bucket_size

  • 返回在特定的桶中的元素数量
size_type bucket_size( size_type n ) const;

bucket

  • 返回带有特定键的桶
size_type bucket( const Key& key ) const;

哈希策略

load_factor

  • 返回每个桶元素的平均数,即 size() 除以 bucket_count()
float load_factor() const;

max_load_factor

  • 管理最大加载因子(每个桶的平均元素数)。若加载因子超出此阈值,则容器自动增加桶数。
// 返回最大加载因子
float max_load_factor() const;

// 设置最大加载因子为 ml
void max_load_factor( float ml );

rehash

  • 设置桶数为 count 并重哈希容器,即考虑桶总数已改变,再把元素放到适当的桶中。
  • 若新的桶数使加载因子大于最大加载因子( count < size() / max_load_factor() ),则新桶数至少为 size() / max_load_factor()
void rehash( size_type count );

reserve

  • 设置桶数为适应至少 count 个元素,而不超出最大加载因子所需的数,并重哈希容器,即考虑桶数已更改后将元素放进适合的桶。等效地调用 rehash(std::ceil(count / max_load_factor())) 。
void reserve( size_type count );

观察器

hash_function

  • 返回对关键哈希的函数
hasher hash_function() const;

key_eq

  • 返回比较关键相等性的函数
key_equal key_eq() const;

非成员函数

operator==

  • 比较 unordered_set 中的值

定义:

template< class Key, class Hash, class KeyEqual, class Allocator >
bool operator==( const std::unordered_set<Key,Hash,KeyEqual,Allocator>& lhs,
                 const std::unordered_set<Key,Hash,KeyEqual,Allocator>& rhs );

用法:

	std::unordered_set<int> alice{1, 2, 3};
	std::unordered_set<int> bob{7, 8, 9, 10};
	std::unordered_set<int> eve{1, 2, 3};
 
	// 比较不相等的容器
	std::cout << "alice == bob returns " << (alice == bob) << std::endl;	//输出 false
	// 比较相等的容器
	std::cout << "alice == eve returns " << (alice == eve) << std::endl;	//输出 true

std::swap

  • 为 std::unordered_set 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。

定义:

template< class Key, class Hash, class KeyEqual, class Alloc >
void swap( std::unordered_set<Key,Hash,KeyEqual,Alloc>& lhs,
           std::unordered_set<Key,Hash,KeyEqual,Alloc>& rhs );

用法:

	std::unordered_set<int> alice{1, 2, 3};
	std::unordered_set<int> bob{7, 8, 9, 10};
	//交换容器
	std::swap(alice,bob);
	//交换后:alice : 7 8 9 10	bob : 1 2 3

erase_if(std::unordered_set)

  • 擦除所有满足特定判别标准的元素(C++ 20)

定义:

template< class Key, class Hash, class KeyEqual, class Alloc, class Pred >
typename std::unordered_set<Key,Hash,KeyEqual,Alloc>::size_type
    erase_if(std::unordered_set<Key,Hash,KeyEqual,Alloc>& c, Pred pred);

用法:

	std::unordered_set<char> cnt {'1', '2', '3', '5', '6'};
	std::erase_if(cnt, 
		[](char x) { return (x - '0') % 2 == 0; }
		);
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值