算法竞赛中的结构体简单重载运算符

                                结构体运算符的简单重载

在算法竞赛中我们经常会使用结构体来保存我们需要的变量,但在我们需要进行排序或使用一些需要运算符的STL容器时,我们往往会定义一个函数cmp来保存,但这不是一个万全的方法.

假如现在需要保存每个人的名字,身高,年龄等信息

我们很容易想到要用结构体 来进行保存

const int maxn=1e6;
struct people{
    std::string name;
    unsigned int age;
    unsigned int height;
}pp[maxn];

设我们现在需要按照name来进行排序

一般我们会在外面定义一个cmp函数

bool cmp(people x,people y)
{
    return x.name<y.name;
}

再使用sort来排序

sort(pp,pp+n,cmp);

 当然这样做确实是好的,但在很多情况下重载运算符更好.

关键字   operator

运算符的重载和函数很像

这里我们先看operator的一个使用

const int maxn=1e6
struct people{
    std::string name;
    unsigned int age;
    unsigned int height;
    bool operator<(const people & t)
    {
            return name<t.name;
    }//按照名字的字典序来排序
}pp[maxn];

看到这里,大家可能就会问了:为什么函数里面前面的是name,后面是t.name.

因为我们是在结构体里的直接重载的,所以可以直接调用结构体里的变量,后面的t则需要使用"."运算符;

若我们把重载运算符看作函数,则

//bool operator<(const people & t);
//是一个返回值为bool 型的 接受一个参数 const people & 的函数

people a,b;
a.name="Jane";a.age=12;a.height=165;
b.name="Tom";b.age=13;b.height=170;
if(a<b)cout<<a.name;//这里 可以看作成调用了a的成员函数
                    // a<b == a.operator<(b)
else cout<<b.name;

当进行a<b比较时,相当于调用了a的成员函数.

以此类推,我们可以写出这个结构体的其他运算符

注:如果像这样重载运算符,在使用sort时,有些编译器会出现玄学错误,后面会讲适合sort的方法

bool operator >(const people & t)
{    
        return t<*this;//this 指针
        //可以调用已经有了的运算符
}
bool operator ==(const people & t)
{
            return this->name==t.name;//this->name ==name;
}

//其他>= ,<=, !=运算符省略...

this 指针

this指针是运用于结构体和类对象(可以不管)中的一个指针,它指向的是当前这个结构体(类)本身,由于是指针,所以使用时要调用某个变量则可以用->来表示 例如上面的实例.*this则是表示这个结构体,this指针可以解决一些需要调用本身的尴尬问题等等.

上面的this->name也就是结构体的name;可以很好的区分.

重载输入输出运算符 >> ,<<

现在我们遇到了一个尴尬的问题----我们在对结构体重载运算符时只能选择结构体作为前一个参数,另一个变量做后面的参数.

如果我们在结构体里定义形如 bool operator >(const string & t,const  people & peo);的形式;则会报错;

同时,上面提到只在结构体里重载该结构体的后面一个参数的话sort也会出现玄学错误.

这种情况有两种解决方法

  • 在结构体外面重载运算符,可以添加两个参数.
  • 在结构体内重载运算符,在前面添加friend关键字,添加两个参数.

第一个就直接定义两个参数的就行

//结构体外~
bool operator (const string & name,const people & t)//可以添加想要比较的对象的先后顺序
{
        return name<t.name;
}
bool operator (const people & t,const string & name)
{
    return t.name<name;
}
void operator = (const string & k,const people & t)//重载赋值运算符
{
        k=t.name;
         return;   
}

第二种方法则是在结构体内加friend

//结构体内~
friend bool operator <(const people & a,const people & b)
{
        //如果像这样重载<运算符则sort不会有玄学错误
        //可以定义在外,外面请不要加friend
        //格式如此,friend加在最前面
        return a.name<b.name;
}

那么我们现在就可以重载输入输出运算符啦~

//为了加深印象 前面重载在内,重载在外各一个
//内
friend ostream & operator<<(ostream & os,const people & t)
{
    //由于ofstream 是由ostream派生来的,所以可以不管
    //oier听不懂没关系,无视不影响
    //记住一定要返回ostream & !!!,第一个参数也要&!!!,不然无法连用
        os<<t.name<<' '<<t.age<<' '<<t.height;
        return os;
} 
//外
istream & operaotr>>(istream & is,const people & t)
{
        is>>t.name>>t.age>>t.height;//顺序皆为名字,年龄,身高
        return is;
}

ps : 用多了就会感觉只是函数换了个名字...

----------------------------------------2018 9,9 更新-------------------------------------------------

最近同学问我怎么重载+ - *  /,其实方法都一样的;这里就举一个例子:

//矩阵乘法
struct Matrix{
	enum array_size{maxn=1005};
	long long a[maxn][maxn];
	friend Matrix operator * (const Matrix & x,const Matrix & y)
	{
		Matrix t;
		for(int i=1;i<=1000;i++)
			for(int j=1;j<=1000;j++)
				for(int k=1;k<=1000;k++)
					t.a[i][j]+=x.a[i][k]*y.a[k][j];
		return t;
	}
};

如有错误或疑问请留言给我O(∩_∩)O

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务