HDU - 1412 - {A} + {B} (set)+set部分基础知识讲解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1412

题意

给定两个集合,将两个集合相加。把合并后的集合由从小到大的顺序输出。

题解

题目很简单,将给定的两组输入,都存入set中,最后迭代器输出就行了。主要是练习下set的基础知识的运用。下面附上一些关于set的知识。

set常用函数及其讲解 

  1.  构造set集合的主要目的是为了快速检索,使用set前,需要在程序头文件中包含声明“#include<set>”。
  2.  set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的的数据结构,在插入元素时,它会自动调整二叉树的排列,把该元素放到适当的位置.例如会将数字进行从小到大的默认排序,将string按字典顺序自动排列。
  3.  创建集合对象。 创建set对象时,需要指定元素的类型,这一点和其他容器一样.
    #include <iostream>
    #include <string>
    #include <set> //使用set必须引用的头文件
    using namespace std;
    int main()
    {
    	set<int> s1;//创建一个int类型的set容器
        set<string> s2;//创建一string对象的set容器
    	return 0;
    }
    
  4. 采用inset()方法把元素插入到集合中(set像集合中容器中放入元素只有inset()),插入规则在默认的比较规则下,是按元素值从小到大插入,如果自己指定了比较规则函数,则按自定义比较规则函数插入。使用前向迭代器对集合中序遍历,结果正好是元素排序后的结果。

    #include<iostream>
    #include<set>
    using namespace std;
    int main()
    {
    	set<int> s;
    	s.insert(5); //第一次插入5,可以插入
    	s.insert(1);
    	s.insert(6);
    	s.insert(3);
    	s.insert(5); //第二次插入5,重复元素,不会插入
    	set<int>::iterator it; //定义前向迭代器
    	//中序遍历集合中的所有元素
    	for(it = s.begin(); it != s.end(); it++)
    	{
    		cout << *it << " ";
    	}
    	cout << endl;
    	return 0;
    }
    //运行结果:1 3 5 6
    
  5. 元素的方向遍历。 使用反向迭代器reverse_iterator可以反向遍历集合,输出的结果正好是集合元素的反向排序结果。它需要用到rbegin()和rend()两个方法,它们分别给出了反向遍历的开始位置和结束位置。
    #include<iostream>
    #include<set>
    using namespace std;
    int main()
    {
    	set<int> s;
    	s.insert(5); //第一次插入5,可以插入
    	s.insert(1);
    	s.insert(6);
    	s.insert(3);
    	s.insert(5); //第二次插入5,重复元素,不会插入
    	set<int>::reverse_iterator rit; //定义反向迭代器
    	//反向遍历集合中的所有元素
    	for(rit = s.rbegin(); rit != s.rend(); rit++)
    	{
    		cout << *rit << " ";
    	}
    	cout << endl;
    	return 0;
    }
    //运行结果:6 5 3 1
    
  6. .元素的删除

            与插入元素的处理一样,集合具有高效的删除处理功能,并自动重新调整内部的红黑树的平衡(集合内部元素的排序)。删除的对象可以是某个迭代器位置上的元素、等于某键值的元素、一个区间上的元素和清空集合。

    #include<iostream>
    #include<set>
    using namespace std;
    int main()
    {
    	set<int> s;
    	s.insert(5); //第一次插入5,可以插入
    	s.insert(1);
    	s.insert(6);
    	s.insert(3);
    	s.insert(5); //第二次插入5,重复元素,不会插入      集合内部:1 3 5 6
    	s.erase(6); //删除键值为6的元素                   集合内部:1 3 5
    	set<int>::reverse_iterator rit; //定义反向迭代器   
    	//反向遍历集合中的所有元素
    	for(rit = s.rbegin(); rit != s.rend(); rit++)
    	{
    		cout << *rit << " ";
    	}
    	cout << endl;	
    	set<int>::iterator it;
     
    	it = s.begin();
    	for(int i = 0; i < 2; i++)
    		it = s.erase(it);      //将 1 3删除
    	for(it = s.begin(); it != s.end(); it++)
    		cout << *it << " ";
    	cout << endl;
     
    	s.clear(); //将集合清空
    	cout << s.size() << endl; //输出集合的大小,即元素个数
     
    	return 0;
    }
    /*
    运行结果:
    5 3 1
    5
    0    
    */
    
  7. 自定义比较函数

         使用insert将元素插入到集合中去的时候,集合会根据设定的比较函数奖该元素放到该放的节点上去。在定义集合的时候,如果没有指定比较函数,那么采用默认的比较函数,即按键值从小到大的顺序插入元素。但在很多情况下,需要自己编写比较函数。

编写比较函数有两种方法。

(1)如果元素不是结构体,那么可以编写比较函数。下面的程序比较规则为按键值从大到小的顺序插入到集合中。

#include<iostream>
#include<set>
using namespace std;
struct mycomp
{                                                 //自定义比较函数,重载“()”操作符
	bool operator() (const int &a, const int &b)
	{
		if(a != b)
			return a > b;
		else
			return a > b;
	}
};
int main()
{
	set<int, mycomp> s; //采用比较函数mycomp
	s.insert(5); //第一次插入5,可以插入
	s.insert(1);
	s.insert(6);
	s.insert(3);
	s.insert(5); //第二次插入5,重复元素,不会插入
	set<int,mycomp>::iterator it;
	for(it = s.begin(); it != s.end(); it++)
		cout << *it << " ";
	cout << endl;
	return 0;
}
/*
运行结果:6 5 3 1  
*/

(2)如果元素是结构体,那么可以直接把比较函数写在结构体内。

#include<iostream>
#include<set>
#include<string>
using namespace std;
struct Info
{
	string name;
	double score;
	bool operator < (const Info &a) const // 重载“<”操作符,自定义排序规则
	{
		//按score由大到小排序。如果要由小到大排序,使用“>”即可。
		return a.score < score;
	}
};
int main()
{
	set<Info> s;
	Info info;
 
	//插入三个元素
	info.name = "Jack";
	info.score = 80;
	s.insert(info);
	info.name = "Tom";
	info.score = 99;
	s.insert(info);
	info.name = "Steaven";
	info.score = 60;
	s.insert(info);
 
	set<Info>::iterator it;
	for(it = s.begin(); it != s.end(); it++)
		cout << (*it).name << " : " << (*it).score << endl; 
	return 0;
}
/*
运行结果:
Tom : 99
Jack : 80
Steaven : 60
*/

                                                                                                                                                                                                   

  • 总结知识点后,该做题,慢慢熟练运用它/
  • AC code(自己第一次用set,很生疏,不过确实很方便)
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string> 
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <functional>
    #include <algorithm>
    #define _USE_MATH_DEFINES  
    using namespace std;
    typedef long long LL;
    
    int main()
    {
    	int n, m;
    	while(~scanf("%d %d",&n,&m))  //将给定的两组输入,都存入set中,最后迭代器输出就行了。
    	{
    		set<int> s;
    		int a;
    		for(int i=1; i<=n; i++)
    		{
    			scanf("%d",&a);
    			s.insert(a);
    		}
    		for(int i=1; i<=m; i++)
    		{
    			scanf("%d",&a);
    			s.insert(a);
    		}
    		int tot = 1;
    		set<int>::iterator it; //定义前向迭代器			//中序遍历集合中的所有元素
    		for(it = s.begin(); it != s.end(); it++)
    		{
    			if(tot == 1) 
    			{
    				cout<< *it;
    				tot = 0;
    			}
    			else         cout<< " "<< *it;	
    		}
    		cout<< endl;	
    	}
    	return 0;
    }
  • 附上学长的代码(用于更熟练的运用set)

    #include<iostream>
    #include<set>
    using namespace std;
    set<int >se;
    int main()
    {
    
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            int x;
            for(int i=0;i<n;i++){
                scanf("%d",&x);
                se.insert(x);
            }
            for(int i=0;i<m;i++){
                scanf("%d",&x);
                se.insert(x);
            }
            set<int>::iterator it; //定义一个set的迭代器
            int flag=1;
            for(it=se.begin();it!=se.end();it++)
            {
                if(flag)
                cout<<*it,flag=0;//注意格式最后一个输出后无空格; 
                else cout<<' '<<*it;
            }
            cout<<endl;
            se.clear(); //注意集合要清空。因为set定义在循环外
        }
        return 0;
    }

猜你喜欢

转载自blog.csdn.net/Alibaba_lhl/article/details/81151409