STL集合类

简介

标准模板库中提供了一些容器类,以便在应用程序中进行频繁而快速的搜索。std::set 和 set::multiset 用于存储一组经过排序的元素,其查找元素的复杂度为对数,而unordered集合的插入和查找时间是固定的。

容器set可以让程序员在容器中快速查找键,键是存储在一维容器中的值。set只能存储唯一的键值,multiset可以存储重复的键值。为了实现快速搜索,其内部结构类像二叉树,位于set中特定位置的元素不能替换为值不同的新元素,这是因为set将把新元素同内部树中的其他元素进行比较,进而将其放在其他位置。

PS:要使用std::set和set::multiset类,需要包含头文件:

#include <set>

STLset和multiset的基本操作

实例化std::set对象

#include <set>

// used as a template parameter in set / multiset instantiation
template <typename T>
struct SortDescending
{
   bool operator()(const T& lhs, const T& rhs) const
   {
      return (lhs > rhs);
   }
};

int main ()
{
   using namespace std;

   // a simple set or multiset of integers (using default sort predicate)
   set<int> setInts1;
   multiset<int> msetInts1;

   // set and multiset instantiated given a user-defined sort predicate
   set<int, SortDescending<int> > setInts2;
   multiset<int, SortDescending<int> > msetInts2;

   // creating one set from another, or part of another container
   set<int> setInts3(setInts1);
   multiset<int> msetInts3(setInts1.begin(), setInts1.end());

   return 0;
}

在set 或multiset中插入元素

#include <set>
#include <iostream>
using namespace std;

template <typename T>
void DisplayContents(const T& container)
{
   for (typename T:: const_iterator element = container.begin();//不支持auto(C++11)可以这么写
        element != container.end();
        ++element)
      cout << *element << ' ';

   cout << endl;
}

int main()
{
   //set <int> setInts{ 202, 151, -999, -1 };
   set <int> setInts;
   setInts.insert(202);
   setInts.insert(151);
   setInts.insert(-999);
   setInts.insert(-1);
   setInts.insert(-1); // duplicate
   cout << "Contents of the set: " << endl;
   DisplayContents(setInts);

   multiset <int> msetInts;
   msetInts.insert(setInts.begin(), setInts.end());
   msetInts.insert(-1); // duplicate

   cout << "Contents of the multiset: " << endl;
   DisplayContents(msetInts);

   cout << "Number of instances of '-1' in the multiset are: '";
   cout << msetInts.count(-1) << "'" << endl;

   return 0;
}
运行结果

在STLset或multiset中查找元素

#include <set>
#include <iostream>
using namespace std;

int main ()
{
   //set<int> setInts{ 43, 78, -1, 124 };
   set<int> setInts;
   setInts.insert(43);
   setInts.insert(78);
   setInts.insert(-1);
   setInts.insert(124);

   // Display contents of the set to the screen
   for (set<int>:: const_iterator element = setInts.begin();
        element != setInts.end ();
        ++ element )
      cout << *element << endl;

   // Try finding an element
    set<int>:: const_iterator elementFound = setInts.find (-1);

   // Check if found...
   if (elementFound != setInts.end ())
      cout << "Element " << *elementFound << " found!" << endl;
   else
      cout << "Element not found in set!" << endl;

   // finding another
   set<int>:: const_iterator anotherFind = setInts.find (12345);

   // Check if found...
   if (anotherFind != setInts.end ())
      cout << "Element " << *anotherFind << " found!" << endl;
   else
      cout << "Element 12345 not found in set!" << endl;

   return 0;
}
运行结果

PS:find()返回的迭代器与end()进行比较,以核实是否找到了指定的元素。如果该迭代器有效,便可以使用*elementFound访问它所指向的值。

删除STLset或multiset中的元素

#include <set>
#include <iostream>
using namespace std;

template <typename T>
void DisplayContents (const T& Input)
{
   for (typename T::const_iterator element = Input.begin();
        element != Input.end ();
         ++ element )
      cout << *element << ' ';

   cout << endl;
}

typedef multiset <int> MSETINT;

int main ()
{
   //MSETINT msetInts{ 43, 78, 78, -1, 124 };
   MSETINT msetInts;
   msetInts.insert(43);
   msetInts.insert(78);
   msetInts.insert(78);
   msetInts.insert(-1);
   msetInts.insert(124);
   cout << "multiset contains " << msetInts.size () << " elements: ";
   DisplayContents(msetInts);

   cout << "Enter a number to erase from the set: ";
   int input = 0;
   cin >> input;

   cout << "Erasing " << msetInts.count (input);
   cout << " instances of value " << input << endl;

   msetInts.erase (input);

   cout << "multiset now contains " << msetInts.size () << " elements: ";
   DisplayContents(msetInts);

   return 0;
}
运行结果

PS:还可以将迭代器(如find()返回的迭代器)传递给erase(),这将删除单个元素

MSETINT :: iterator elementFound = msetInts.find(numberToErase);
if(elementFound != msetInts.end())
    msetInts.erase(elementFound);
else
    cout << "Element not found!" <<endl;

erase()还可以用于从multiset中删除指定范围内的元素

MSETINT :: iterator elementFound = msetInts.find(valueToErase);
if(elementFound != msetInts.end())
    msetInts.erase(msetInts.begin(),elementFound);

一个使用STLset及其成员函数find和erase的电话簿

扫描二维码关注公众号,回复: 6156085 查看本文章
#include <set>
#include <iostream>
#include <string>
using namespace std;

template <typename T>
void DisplayContents (const T& container)
{
   for (typename T :: const_iterator iElement = container.begin();
         iElement != container.end();
         ++ iElement )
      cout << *iElement << endl;

   cout << endl;
}

struct ContactItem
{
   string name;
   string phoneNum;
   string displayAs;

   ContactItem (const string& nameInit, const string & phone)
   {
      name = nameInit;
      phoneNum = phone;
      displayAs = (name + ": " + phoneNum);
   }

   // used by set::find() given contact list item
   bool operator == (const ContactItem& itemToCompare) const
   {
      return (itemToCompare.name == this->name);
   }

   // used to sort
   bool operator < (const ContactItem& itemToCompare) const
   {
      return (this->name < itemToCompare.name);
   }

   // Used in DisplayContents via cout
   operator const char*() const
   {
      return displayAs.c_str();
   }
};

int main ()
{
   set<ContactItem> setContacts;
   setContacts.insert(ContactItem("Jack Welsch", "+1 7889 879 879"));
   setContacts.insert(ContactItem("Bill Gates", "+1 97 7897 8799 8"));
   setContacts.insert(ContactItem("Angi Merkel", "+49 23456 5466"));
   setContacts.insert(ContactItem("Vlad Putin", "+7 6645 4564 797"));
   setContacts.insert(ContactItem("John Travolta", "91 234 4564 789"));
   setContacts.insert(ContactItem("Ben Affleck", "+1 745 641 314"));
   DisplayContents(setContacts);

   cout << "Enter a name you wish to delete: ";
   string inputName;
   getline(cin, inputName);

   set<ContactItem>::iterator contactFound = setContacts.find(ContactItem(inputName, ""));
   if(contactFound != setContacts.end())
   {
      setContacts.erase(contactFound);
      cout << "Displaying contents after erasing " << inputName << endl;
      DisplayContents(setContacts);
   }
   else
      cout << "Contact not found" << endl;

   return 0;
}
运行结果

PS:std::set排序是在插入元素时进行的,在插入的时候使用operator<进行了排序。

使用STLset和multiset的优缺点

STLset和multiset在插入时对元素进行了排序,如果应用程序将频繁使用find( )函数的话,这种开销就是值得的。find()利用了内部二叉树的结构,在vector中,可以使用新值替换迭代器(如std::find( )返回的迭代器)指向的元素,但set根据元素的值对其进行了排序,因此不能使用迭代器覆盖元素的值,虽然通过编程可以实现这种功能。

STL散列集合实现std::unordered_set和std::unordered_multiset

因为set在插入时已经对元素进行了排序,所以在set中查找元素的时,所需要的时间不是与元素数成正比,而是与元素数的对数成正比。有一种插入和排序时间固定的的方式基于散列实现的。将元素插入散列集合时,首先利用散列函数计算出一个唯一的索引,再根据该索引决定将元素放到哪个桶(bucket)中.

#include<unordered_set>
#include <iostream>
using namespace std;

template <typename T>
void DisplayContents(const T& cont)
{
   cout << "Unordered set contains: ";
   for (typename T :: const_iterator element = cont.begin();
        element != cont.end();
        ++ element )
      cout<< *element << ' ';

   cout << endl;

   cout << "Number of elements, size() = " << cont.size() << endl;
   cout << "Bucket count = " << cont.bucket_count() << endl;
   cout << "Max load factor = " << cont.max_load_factor() << endl;
   cout << "Load factor: " << cont.load_factor() << endl << endl;
}

int main()
{
   unordered_set<int> usetInt{ 1, -3, 2017, 300, -1, 989, -300, 9 };
   DisplayContents(usetInt);
   usetInt.insert(999);
   DisplayContents(usetInt);

   cout << "Enter int you want to check for existence in set: ";
   int input = 0;
   cin >> input;
   auto elementFound = usetInt.find(input);

   if (elementFound != usetInt.end())
      cout << *elementFound << " found in set" << endl;
   else
      cout << input << " not available in set" << endl;

   return 0;
}

这个程序跑不起来,手上的编译器不支持C++11。这就比较难受了。那就这样吧,继续学习,后续会有补充的。

猜你喜欢

转载自blog.csdn.net/qq_35353824/article/details/89785450