❤️终于梦到了学姐,教了我剩下那四个算法,都只要一行代码,我知乎神奇!❤️(建议收藏)
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
是等价的;&a
和pa
是等价的; - 我们可以认为
*
和&
是两个互逆的操作。
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)叉乘的运算
- 叉乘(又叫叉积、向量积,外积),表示的是两个向量经过运算后,和这两个向量垂直的向量(和点乘不同,它的结果还是一个向量),如下:
a ⃗ = ( x a , y a , z a ) \\vec a = (x_a,y_a,z_a) a=(xa,ya,za) b ⃗ = ( x b , y b , z b ) \\vec b = (x_b,y_b,z_b) b=(xb,yb,zb) a ⃗ × b ⃗ = c ⃗ = ( y a z b − z a y b ) i ⃗ + ( z a x b − x a z b ) j ⃗ + ( x a y b − y a x b ) k ⃗ \\vec a \\times \\vec b = \\vec c = (y_az_b-z_ay_b) \\vec i + (z_ax_b-x_az_b)\\vec j + (x_ay_b-y_ax_b)\\vec k a×b=c=(yazb−zayb)i+(zaxb−xazb)j+(xayb−yaxb)k - 其中 i ⃗ = ( 1 , 0 , 0 ) , j ⃗ = ( 0 , 1 , 0 ) , k ⃗ = ( 0 , 0 , 1 ) \\vec i = (1, 0, 0), \\vec j = (0, 1, 0), \\vec k = (0, 0, 1) i=(1,0,0),j=(0,1,0),k=(0,0,1)
- 当两个向量都在 z = 0 z = 0 z=0 的平面上时, z a = z b = 0 z_a=z_b=0 za=zb=❤️学姐说她用 8 行代码写了 8 个算法(上)❤️(推荐收藏)