C/C++机试小技巧

常用宏定义

// 求最大值和最小值
#define MAX(x,y) (((x) > (y))? (x):(y))
#define MIN(x,y) (((x) < (y))? (x):(y))

// 取余
# define mod(x) ((x) % MOD)

// for循环
#define FOR(i, f_start, f_end) for(int i=f_start;i<f_end;++i)

// 返回数组元素的个数
# define ARR_SIZE(a) (sizeof((a))/sizeof((a[0])))

// 初始化数组
#define MT(x,i) memset(x,i,sizeof(x))
#define MEM(a,b) memset((a),(b),sizeof(a))

// 符号重定义
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>

// 常见常数
#define PI acos(-1.0)  // 求圆周率 tan45度=1 -> 45度换成弧度就是pi/4 -> 反三角函数就是atan(1.0)再乘以4 -> acos(-1.0) -> pi
#define eps 1e-12
#define INF 0x3f3f3f3f	// int 最大值,作为 +∞ 使用

const int INF_INT = 2147483647;
const ll INF_LL = 9223372036854775807LL;
const ull INF_ULL = 18446744073709551615Ull;
const ll P = 9254064680811039LL;
const ll maxn = 1e5 + 10, MOD = 1e9 + 7;
const int Move[4][2] = {-1,0,1,0,0,1,0,-1};
const int Move_[8][2] = {-1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1};


i++和++i

对于i++和++i,大家都知道前者是先使用再自增,后者是先自增再使用,
但是在for循环中,i++和++i有区别嘛?我本来是觉得不应该有区别的,但是这里使用了++i,我还是搜了一下
对于一个 for 循环:

for(A;B;C)
{
   D;
}

其执行步骤如下:

  1. 进入循环执行A; //只是进入的时候执行.
  2. 执行B; //条件为真才执行D,不然就跳出for循环了.
  3. 执行D;
  4. 执行C;
  5. 再回到第2步开始执行

那么我们接着看下面实例:

for( int i = 0; i<10; i++ )

for(int i = 0; i<10; i++) {
    System.out.println(i);
}

相当于:

for(int i=0; i<10;)
{
    System.out.println(i);
    i++;
}

for( int i=0; i<10; ++i )

for(int i = 0; i<10; ++i) {
    System.out.println(i);
}

相当于:

for(int i=0; i<10;)
{
    System.out.println(i);
    ++i;
}

在上述的循环体中,i++ 和 ++i 的作用是一样的。
打印出来的信息都是:

0
1
2
3
4
5
6
7
8
9

然而到这步也只是证明了其作用效果是一样,但是他们肯定是有一定区别的。
把循环耗时也打印出来:
循环次数=100
在这里插入图片描述
循环次数=1000
在这里插入图片描述
循环次数=10000
在这里插入图片描述
这样区别就很明显了 ---- 运行时间,
当循环次数较少时两者效率近似,但是当循环的次数上去了,这差距就比较明显了。
其原因在于:
i++ 语句需要一个临时变量存储返回自增前的值,而++i不需要。
i++比起++i多了一个创建临时变量(放入数据栈)的步骤,这样就导致了运行时间上的差异。
所以建议大家以后在写for循环且不影响逻辑的情况下多使用++i,少使用i++,这也算一定程度的优化啦!
还需要注意的一点是:

	int y=0;	
	//注意"="是赋值,"=="才是相等
	y=++y;
	y=++y;
	y=++y;
	y=++y;
	y=++y;
	cout<<"y="<<y<<endl;//5
	int i =0;
	i=i++;
	i=i++;
	i=i++;
	i=i++;
	i=i++;
	cout<<"i="<<i<<endl;//0
	cout<<"i"<<endl;//1

结果如图:
在这里插入图片描述
i=++i,是 i 在内存自增一,然后进寄存器,赋值的时候 第一个 i 赋值为1,第二个就是2,第五个就是5;
i=i++, 是赋值之后再自增1,i=0这个值先进寄存器,然后i在内存自增1,最后赋值的时候寄存器出来的 0 会冲掉 1 成为最终结果,所以无论多少个结果都会是 0


# define INF 0x3f3f3f3f

看到INF为0x3f3f3f3f的时候我还挺奇怪的,int 是4 bytes即32 bit,最大值应该为 0x7fffffff来着,
搜了一下发现是因为 “0x7fffffff 不能满足 无穷大加一个有穷的数仍然是无穷大”,
(比如在最短路径算法中,我们使用松弛操作:如果u,v之间没有边,那么w[u][v]=INF,如果INF取7fffffff,那么d[u]+w[u][v]会溢出而变成负数,松弛操作便出错了)
所以选择0x3f3f3f3f来作为 ∞ ,它有以下几个好处:

  1. 0x3f3f3f3f的十进制是1061109567,109级别(和0x7fffffff是一个数量级),而一般数据都小于109,所以其可作为无穷大使用而不致出现数据大于无穷大的情形,且避免了加法算术上溢出或者繁琐的判断
  2. 0x3f3f3f3f + 0x3f3f3f3f = 2122219134,未超过int的表示范围,满足 “无穷大加无穷大还是无穷大” 的需求
  3. 想将某个数组全部赋值为无穷大时,若使用 0x7fffffff,则需要写循环,而 0x3f3f3f3f则可以直接使用memset函数,因为memset是按字节操作的,它能够对数组清零是因为0的每个字节都是0(一般只有赋值为-1/0时使用memset),当我们要赋值为无穷大-0x3f3f3f3f时,奇迹就出现了,其每个字节都是0x3f,所以要把一段内存全部置为无穷大,可以使用 memset(a,0x3f,sizeof(a))



结构体

typedef struct {
	int id;
	int h;
} node;
bool operator <(const node& a, const& b) {
	return (a.h) < (b.h);
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值