❤️终于梦到了学姐,教了我剩下那四个算法,都只要一行代码,我知乎神奇!❤️(建议收藏)

Posted 英雄哪里出来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了❤️终于梦到了学姐,教了我剩下那四个算法,都只要一行代码,我知乎神奇!❤️(建议收藏)相关的知识,希望对你有一定的参考价值。

📢博客主页:https://blog.csdn.net/WhereIsHeroFrom
📢欢迎各位 👍点赞 ⭐收藏 📝评论,如有错误请留言指正,非常感谢!
📢本文由 英雄哪里出来 原创,转载请注明出处,首发于 🙉 CSDN 🙉
作者的专栏:
  👉C语言基础专栏《光天化日学C语言》
  👉算法进阶专栏《夜深人静写算法》
  👉C/C++大厂面试专栏《C/C++ 面试 100 例》
  👉奇奇怪怪的专栏《学姐教我写代码》

一、前言

  本文适合对算法处于朦胧期的初学者,文字浅显易懂,并且配有生动有趣的动图,也是作者呕心沥血之作,希望对刚入大学,或者职场上想要涉足算法的青年同僚有所启示。
  采用风趣幽默的故事的形式,对基础C语言进行了一个复习,并且引入了一些简单的一行算法,从最简单的语法开始讲起,套入故事情节,相信你一定可以看懂。
  学习算法,任何时候都不嫌晚,大不了就是大器晚成而已,所以无论你是30岁,40岁,50岁,甚至60岁,只要下了决心,就已经成功了一半!本文的故事发生在 ❤️《学姐教我写代码(二)》一行代码一个算法(上)❤️ 的几天后,剧情扑朔迷离,作者至今回忆起来还历历在目。

  • 本章能够学到的东西大概如下:

二、梦醒时分

  • 自从上次梦到学姐教了我四个算法以后。过了两天,三天,四天 一直没有等到学姐再次进入我的梦中……
  • 当我快要绝望之时,天上突然下起了倾盆大雨。
  • 然后,学姐竟然从天上下了下来!
  • 我嘞个去啊! 我扶起学姐,发现她是紫色的!说明我还在梦里咧!因为根据 《学姐教我写代码(一)》十道题搞定C语言 所说,现实中的学姐是橙色的呀!
  • 原来我根本就没有醒过,我问学姐剩下那四个算法到底是什么?
  • 学姐愣了一下!

  • 我嘞个去啊!学姐,该不会是脑子瓦特了吧!
  • 看来得帮助学姐恢复记忆,不然那剩下的四个算法我就永远学不到了。
  • 这时候身边突然出现了一颗胶囊,上面写着六个大字:
  • 我嘞个去啊!果然是做梦啊,要什么来什么!
  • 但是这颗胶囊怎么充斥着诡异的味道!
  • 于是我把药丸给学姐服下。
  • 只见一道绿光闪过!立刻风云大作!
阴雨绵绵
浊浪排空
日星隐耀
山岳潜形

  • 再回头看时,学姐竟然:
  • 成了绿色的!!!



  • 然后学姐迅速写下了四行代码,就匆匆离我而去了!
  • 这四行代码分别是:
void A(int *a, int *b) { *a = *a ^ *b, *b = *a ^ *b, *a = *a ^ *b; }
int B(struct Point a, struct Point b) { return a.x * b.y - a.y * b.x; }
int C(int n, int m) { return n == 0 ? (m == 0 ? 1 : 0) : (C(n-1, m) + C(n-1, m-1) ); }
int D(int a, int b) { return b == 0 ? 1 : ( ((b&1) ? a : 1)  * D(a*a, b/2)  ); }
  • 这时,我突然感觉头部被硬物敲击,反应过来时,发现眼前赫然站立着一个橙色的学姐。
  • 太好了,我终于回到现实世界了。

、

  • 我把梦里发生的事情一五一十的告诉了学姐……


  • 磨蹭了半个小时以后……
  • 等她回来时,我发现我的手臂上竟然有那 四!行!代!码!
  • 学姐你看!!!
  • 学姐会心一笑,嗯!然后,她告诉我这四行代码的含义。

三、算法解析

算法一

交换两个变量的值

void A(int *a, int *b) {
    *a = *a ^ *b, *b = *a ^ *b, *a = *a ^ *b;
}

在这里插入图片描述

1)逗号表达式

  • 对于C语言中的逗号表达式,你可以理解成就是为了分隔两个语句,从左往右计算即可,如下代码:
#include <stdio.h>
int main() {
	int a, b, c, d;
	d = ( a = 3, b = a + 3, c = b + 5, 56 );
	printf("%d %d %d %d\\n", a, b, c, d);
	return 0;
}
  • 对于这段代码输出的答案为:
3 6 11 56
  • 可以看出,这个逗号表达式等价于:
    a = 3;
    b = a + 3;
    c = b + 5;
    56;
  • 并且整个逗号表达式的值,就是最右边的那个表达式的值,即56

2)变量取地址和指针

  • 可以用&符号对一个变量取地址,取了地址后他就变成了一个指针变量,如下:
#include <stdio.h>
int main() {
	int a = 5;
	int *pa = &a; 
	return 0;
}
  • 这里a是一个普通变量,pa是一个指针变量。

3)指针取值

  • 指针说白了,就是一个变量的地址;在一个指针前面加上*符号的含义,就是取这个地址里面的值。看个例子加深理解:
#include <stdio.h>
int main() {
	int a = 5;
	int *pa = &a; 
	printf("%d\\n", *pa); 
	return 0;
}
  • 这段代码输出的值为 5。也就是a*pa是等价的;&apa是等价的;
  • 我们可以认为*&是两个互逆的操作。

4)异或的性质

  • 二进制的异或,就是两个数转换成二进制表示后,按照位进行以下运算:
  • 1)0和0异或为0;
  • 2)1和1异或为0;
  • 3)0和1异或为1;
  • 4)1和0异或为1;
  • 也就是对于 0 和 1,相同的数异或为 0,不同的数异或为 1。
  • 这样就有了两个比较清晰的性质:
  • 1)两个相同的十进制数异或的结果一定位零。
  • 2)任何一个数和 0 的异或结果一定是它本身。
  • 3)异或运算满足结合律和交换律。

5)算法解析

  • 首先,我们可以把这段代码拆分开来,因为逗号表达式是可以拆分的,于是得到如下代码:
void A(int *a, int *b) {
    *a = *a ^ *b;
    *b = *a ^ *b;
    *a = *a ^ *b;
}
  • 然后,由于这里指针取值了,所以我们可以认为就是普通变量,也就是把*a当成是A即可,把*b当成是B即可。函数内部,可以理解成是:
    A = A ^ B;
    B = A ^ B;
    A = A ^ B;
  • 我们直接来看前两句话,相当于B等于A^B^B,根据异或的几个性质,我们知道,这时候的B的值已经变成原先A的值了。
  • 而再来看最后一句话,相当于A等于A^B^A,还是根据异或的几个性质,这时候,A的值已经变成了原先B的值。

算法二

叉乘

  • 叉乘是用来判定一个顶点是在一条射线的左侧还是右侧。

在这里插入图片描述

1)点

  • 对于一个二维空间中的点,只需要两个数字就能表示,即(x, y)分别代表的是横坐标和纵坐标,如图所示:

、

  • 可以用如下数据结构来代表一个点:
struct Point {
    int x, y;
};

2)向量

  • 向量则代表了两个点之间的差值,即横坐标相减,纵坐标相减。并且向量是有方向的。如图所示红色的箭头代表的就是一个向量。
  • 我们可以表示成点 (4,7)和原点(0,0)的差。

3)叉乘的运算