├── LICENSE ├── README.md ├── algorithm ├── 十大排序算法 │ ├── 10、radixSort.c │ ├── 1、swapSort.c │ ├── 2、chooseSort.c │ ├── 3、insertSort.c │ ├── 4、mergeSort.c │ ├── 5、shellSort.c │ ├── 6、heapSort.c │ ├── 7、quickSort.c │ ├── 8、bucketSort.c │ └── 9、countSort.c ├── 字符串函数实现算法 │ ├── 1、strlen.c │ ├── 2、strcpy.c │ ├── 3、strcmp.c │ └── 4、strcat.c ├── 数组常见算法 │ ├── 1、和为定值的2个数.cpp │ ├── 2、奇数位于偶数前面.c │ ├── 3、数组逆序.c │ ├── 4、随机化数组.c │ ├── 5、通用的二维数组.c │ ├── 7、寻找一个数组中的第二大数字.c │ └── 8、寻找最小的k个数.c ├── 算法资料.jpeg ├── 经典字符串算法 │ ├── 10、字符串去重.c │ ├── 11、字符串转换成整数.c │ ├── 12、KMP算法.c │ ├── 1、串匹配基础算法.c │ ├── 2、单词反转.c │ ├── 3、回文判断.c │ ├── 4、全排列.c │ ├── 5、三步反转递归法.c │ ├── 6、三步反转非递归.c │ ├── 7、整数转换为字符串.c │ ├── 8、字符串包含.c │ └── 9、字符串去空格.c ├── 经典查找算法 │ ├── 1、binarySearch.c │ ├── 2、binarySearch_other.c │ ├── 3、出现次数一半的数.c │ ├── 4、出现次数超过一半以上的数.c │ └── 5、杨氏矩阵查找.c ├── 高频树算法 │ ├── 1、二叉树创建及方法实现.c │ ├── 2、二叉树非递归遍历.cpp │ ├── 3、前中后创建二叉树.c │ └── binTree.h └── 高频面试算法 │ ├── 10、哥德巴赫猜想验证.c │ ├── 11、汉诺塔问题.c │ ├── 12、将任意整数转换为二进制.c │ ├── 13、将任意整数转换为十六进制.c │ ├── 14、括号匹配算法.cpp │ ├── 15、判断大小端.c │ ├── 16、求前n个数和.c │ ├── 17、求字符串的长度.c │ ├── 18、约瑟夫环.c │ ├── 19、转换数字.c │ ├── 1、2个栈实现一个队列.cpp │ ├── 20、字符串转置.c │ ├── 21、字符串转置_1.c │ ├── 22、最大子数组和.c │ ├── 23、最长公共子序列.c │ ├── 24、KMP.c │ ├── 25、随机化数组.c │ ├── 2、10到M进制转换.cpp │ ├── 3、八皇后问题.c │ ├── 4、饿汉式.c │ ├── 5、懒汉式.c │ ├── 6、二进制中1的个数.c │ ├── 7、斐波那契数列.c │ ├── 8、斐波那契数列_1.c │ └── 9、高效查找自幂数.c └── cs-basics └── 学习路线指南 ├── Java学习路线_2019版.md ├── LinuxC_C++学习路线_2019版.md ├── Linux学习路线.md ├── 五大能力提升.md ├── 数据分析学习路线.md ├── 算法工程师学习路线_NLP 方向.md └── 算法成神之路.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 puge-up 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | - [computer-basics](#computer-basics) 2 | - [个人履历](#个人履历) 3 | - [编程学习](#编程学习) 4 | - [计算机学习体系](#计算机学习体系) 5 | - [一、学习路线指南](#一学习路线指南) 6 | - [二、基础知识学习](#二基础知识学习) 7 | - [算法系列](#算法系列) 8 | - [一、高频面试算法](#一高频面试算法) 9 | - [二、十大排序算法](#二十大排序算法) 10 | - [三、经典字符串算法](#三经典字符串算法) 11 | - [四、经典查找算法](#四经典查找算法) 12 | - [五、数组常见算法](#五数组常见算法) 13 | - [六、高频树算法](#六高频树算法) 14 | - [七、字符串函数实现算法](#七字符串函数实现算法) 15 | - [面经](#面经) 16 | - [声明](#声明) 17 | 18 | # computer-basics 19 | 20 | ”computer-basics“ 中文意思为”计算机基础知识“,本 github 专注于计算机基础知识学习,夯实内功才能走的更远。 21 | 22 | 基础知识往往是大厂面试核心,尤其在校招中将决定你是否能冲进大厂,围绕“计算机基础知识”,来看看我的学习方法,思维模式,以及如何实战演练,如何高效学习基础知识将成为关键。 23 | 24 | 核心分享 4 方面: 25 | 26 | - 学习路线指南 27 | - 计算机基础知识 28 | - 算法 29 | - 面经 30 | 31 | # 个人履历 32 | 33 | 普通本科毕业,非科班学生,在校一路自学编程、摸索打法,实习过腾讯、百度,秋招拿到过 BAT、美团、京东、商汤科技等大厂 offer,毕业在 BAT 大厂搬砖。 34 | 35 | - 2014.9 - 2018.6 普通一本,非科班学生 36 | - 2017.7 - 2017.9 腾讯暑期实习,并转正留用 37 | - 2017.9 秋招,拿到过 BAT 美团 京东等大厂 offer 38 | - 2018.1 - 2018.3 百度入职前实习 39 | - 2018.7 毕业入职 BAT 大厂搬砖 40 | - 2019.4 绩效+价值观均获得优秀,授予人生第一笔股票 41 | - 2020.7 晋升成功 42 | 43 | 兵马未动、粮草先行,得把这些意识深深的扎下去,扎入到骨髓中,我最喜欢的十句话送给各位: 44 | 45 | - 认真的人,自带光芒! 46 | - 天下武功,唯快不破! 47 | - 帮助别人就是帮助自己! 48 | - 心中无敌,方能无敌于天下! 49 | - 三步走战略,五大能力提升! 50 | - 思想过硬、作风过硬、技术过硬! 51 | - 人生需要布局,得有战略、打法! 52 | - 一辈子很长,要和有趣的人在一起! 53 | - 今天最好的表现,是明天最低的要求! 54 | - 以武会友、以剑论道、仗剑天涯,潇洒人生! 55 | 56 | # 编程学习 57 | 58 | 三步走战略: 59 | 60 | - 看视频/书 + 敲代码 + 记笔记(视频为主、书为辅) 61 | - 算法 + 基础 + 技术栈 62 | 63 | 五大能力提升:快速的学习能力、应用业务的能力、解决问题的能力、信息检索的能力、有效资料判断力。 64 | 65 | - 快速的学习能力:指的是面对新的技术领域,自己从未接触过的技术,能不能在有效的时间内,把它学会、弄懂,这就是学习能力; 66 | - 应用业务的能力:指的是技术到位了,能不能用于项目中,用于实际问题中,在工作中尤为重要,学好跟用起来差距还是挺大的,听懂了不一定会做题,这就是学以致用; 67 | - 解决问题的能力:指的是根据现有的技术,现有的资源、举一反三、触类旁通、灵活运用,能否解决一个技术难题、攻克困难的能力; 68 | - 信息检索的能力:指的是利用互联网上面的一切资源,利用各种搜索技术、各种网站、各种论坛、快速的找到你所需要的资源(视频、电子书、图片等等等)的能力; 69 | - 有效资料判断力:指的是现在互联网上面,优质资源有,但是劣质的资源更多,随手一搜,一大片,你是否具有一定的判断力呢?就 Java 视频一大堆,哪个是比较优质的呢?有效资料判断力可以帮助你少走弯路,节省大把的时间,这就是学会筛选的能力。 70 | 71 | 认清自我的能力、独立思考的能力、分析问题的能力等等这些能力,时刻无处不在,但是跟五大能力是有本质的区别,培养方式与提高也是完全不一样的。 72 | 73 | # 计算机学习体系 74 | 75 | ## 一、学习路线指南 76 | 77 | 1. [个人五大能力提升.md](https://github.com/puge-up/computer-basics/blob/main/cs-basics/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF%E6%8C%87%E5%8D%97/%E4%BA%94%E5%A4%A7%E8%83%BD%E5%8A%9B%E6%8F%90%E5%8D%87.md) 78 | 2. [Java学习路线_2019版.md](https://github.com/puge-up/computer-basics/blob/main/cs-basics/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF%E6%8C%87%E5%8D%97/Java%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF_2019%E7%89%88.md) 79 | 3. [LinuxC/C++学习路线_2019版.md](https://github.com/puge-up/computer-basics/blob/main/cs-basics/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF%E6%8C%87%E5%8D%97/LinuxC_C%2B%2B%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF_2019%E7%89%88.md) 80 | 4. [算法工程师学习路线_NLP方向.md](https://github.com/puge-up/computer-basics/blob/main/cs-basics/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF%E6%8C%87%E5%8D%97/%E7%AE%97%E6%B3%95%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF_NLP%20%E6%96%B9%E5%90%91.md) 81 | 5. [算法成神之路.md](https://github.com/puge-up/computer-basics/blob/main/cs-basics/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF%E6%8C%87%E5%8D%97/%E7%AE%97%E6%B3%95%E6%88%90%E7%A5%9E%E4%B9%8B%E8%B7%AF.md) 82 | 6. [数据分析学习路线.md](https://github.com/puge-up/computer-basics/blob/main/cs-basics/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF%E6%8C%87%E5%8D%97/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF.md) 83 | 7. [Linux学习路线.md](https://github.com/puge-up/computer-basics/blob/main/cs-basics/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF%E6%8C%87%E5%8D%97/Linux%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF.md) 84 | 85 | ## 二、基础知识学习 86 | 87 | 系列打造中。。。 88 | 89 | # 算法系列 90 | 91 | > 本 github 绝大部分算法都是用 C 语言实现的,主要是通过实现算法达到 C 语言的熟练掌握,在面试中 C、C++、Java、Python 均可实现算法题,主要看思路是否是最优解。 92 | 93 | 大学期间实现的基础算法题,可以看看这些高频面试算法题,你是否都能写出来,用于校验自己现阶段的算法能力。 94 | 95 |
96 |

(高频面试算法)

97 | 98 | ## 一、高频面试算法 99 | 100 | 1. [2个栈实现一个队列.cpp](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/1%E3%80%812%E4%B8%AA%E6%A0%88%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E9%98%9F%E5%88%97.cpp) 101 | 2. [10到M进制转换.cpp](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/2%E3%80%8110%E5%88%B0M%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2.cpp) 102 | 3. [八皇后问题.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/3%E3%80%81%E5%85%AB%E7%9A%87%E5%90%8E%E9%97%AE%E9%A2%98.c) 103 | 4. [饿汉式.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/4%E3%80%81%E9%A5%BF%E6%B1%89%E5%BC%8F.c) 104 | 5. [懒汉式.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/5%E3%80%81%E6%87%92%E6%B1%89%E5%BC%8F.c) 105 | 6. [二进制中1的个数.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/6%E3%80%81%E4%BA%8C%E8%BF%9B%E5%88%B6%E4%B8%AD1%E7%9A%84%E4%B8%AA%E6%95%B0.c) 106 | 7. [斐波那契数列.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/7%E3%80%81%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97.c) 107 | 8. [斐波那契数列_1.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/8%E3%80%81%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97_1.c) 108 | 9. [高效查找自幂数.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/9%E3%80%81%E9%AB%98%E6%95%88%E6%9F%A5%E6%89%BE%E8%87%AA%E5%B9%82%E6%95%B0.c) 109 | 10. [哥德巴赫猜想验证.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/10%E3%80%81%E5%93%A5%E5%BE%B7%E5%B7%B4%E8%B5%AB%E7%8C%9C%E6%83%B3%E9%AA%8C%E8%AF%81.c) 110 | 11. [汉诺塔问题.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/11%E3%80%81%E6%B1%89%E8%AF%BA%E5%A1%94%E9%97%AE%E9%A2%98.c) 111 | 12. [将任意整数转换为二进制.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/12%E3%80%81%E5%B0%86%E4%BB%BB%E6%84%8F%E6%95%B4%E6%95%B0%E8%BD%AC%E6%8D%A2%E4%B8%BA%E4%BA%8C%E8%BF%9B%E5%88%B6.c) 112 | 13. [将任意整数转换为十六进制.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/13%E3%80%81%E5%B0%86%E4%BB%BB%E6%84%8F%E6%95%B4%E6%95%B0%E8%BD%AC%E6%8D%A2%E4%B8%BA%E5%8D%81%E5%85%AD%E8%BF%9B%E5%88%B6.c) 113 | 14. [括号匹配算法.cpp](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/14%E3%80%81%E6%8B%AC%E5%8F%B7%E5%8C%B9%E9%85%8D%E7%AE%97%E6%B3%95.cpp) 114 | 15. [判断大小端.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/15%E3%80%81%E5%88%A4%E6%96%AD%E5%A4%A7%E5%B0%8F%E7%AB%AF.c) 115 | 16. [求前n个数和.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/16%E3%80%81%E6%B1%82%E5%89%8Dn%E4%B8%AA%E6%95%B0%E5%92%8C.c) 116 | 17. [求字符串的长度.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/17%E3%80%81%E6%B1%82%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E9%95%BF%E5%BA%A6.c) 117 | 18. [约瑟夫环.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/18%E3%80%81%E7%BA%A6%E7%91%9F%E5%A4%AB%E7%8E%AF.c) 118 | 19. [转换数字.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/19%E3%80%81%E8%BD%AC%E6%8D%A2%E6%95%B0%E5%AD%97.c) 119 | 20. [字符串转置.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/20%E3%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E7%BD%AE.c) 120 | 21. [字符串转置_1.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/21%E3%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E7%BD%AE_1.c) 121 | 22. [最大子数组和.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/22%E3%80%81%E6%9C%80%E5%A4%A7%E5%AD%90%E6%95%B0%E7%BB%84%E5%92%8C.c) 122 | 23. [最长公共子序列.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/23%E3%80%81%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97.c) 123 | 24. [KMP.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/24%E3%80%81KMP.c) 124 | 25. [随机化数组.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E9%9D%A2%E8%AF%95%E7%AE%97%E6%B3%95/25%E3%80%81%E9%9A%8F%E6%9C%BA%E5%8C%96%E6%95%B0%E7%BB%84.c) 125 | 126 | ## 二、十大排序算法 127 | 128 | 1. [swapSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/1%E3%80%81swapSort.c) 129 | 2. [chooseSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/2%E3%80%81chooseSort.c) 130 | 3. [insertSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/3%E3%80%81insertSort.c) 131 | 4. [mergeSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/4%E3%80%81mergeSort.c) 132 | 5. [shellSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/5%E3%80%81shellSort.c) 133 | 6. [heapSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/6%E3%80%81heapSort.c) 134 | 7. [quickSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/7%E3%80%81quickSort.c) 135 | 8. [bucketSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/8%E3%80%81bucketSort.c) 136 | 9. [countSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/9%E3%80%81countSort.c) 137 | 10. [radixSort.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%8D%81%E5%A4%A7%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/10%E3%80%81radixSort.c) 138 | 139 | ## 三、经典字符串算法 140 | 141 | 1. [串匹配基础算法.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/1%E3%80%81%E4%B8%B2%E5%8C%B9%E9%85%8D%E5%9F%BA%E7%A1%80%E7%AE%97%E6%B3%95.c) 142 | 2. [单词反转.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/2%E3%80%81%E5%8D%95%E8%AF%8D%E5%8F%8D%E8%BD%AC.c) 143 | 3. [回文判断.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/3%E3%80%81%E5%9B%9E%E6%96%87%E5%88%A4%E6%96%AD.c) 144 | 4. [全排列.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/4%E3%80%81%E5%85%A8%E6%8E%92%E5%88%97.c) 145 | 5. [三步反转递归法.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/5%E3%80%81%E4%B8%89%E6%AD%A5%E5%8F%8D%E8%BD%AC%E9%80%92%E5%BD%92%E6%B3%95.c) 146 | 6. [三步反转非递归.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/6%E3%80%81%E4%B8%89%E6%AD%A5%E5%8F%8D%E8%BD%AC%E9%9D%9E%E9%80%92%E5%BD%92.c) 147 | 7. [整数转换为字符串.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/7%E3%80%81%E6%95%B4%E6%95%B0%E8%BD%AC%E6%8D%A2%E4%B8%BA%E5%AD%97%E7%AC%A6%E4%B8%B2.c) 148 | 8. [字符串包含.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/8%E3%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%85%E5%90%AB.c) 149 | 9. [字符串去空格.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/9%E3%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8E%BB%E7%A9%BA%E6%A0%BC.c) 150 | 10. [字符串去重.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/10%E3%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8E%BB%E9%87%8D.c) 151 | 11. [字符串转换成整数.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/11%E3%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E6%8D%A2%E6%88%90%E6%95%B4%E6%95%B0.c) 152 | 12. [KMP算法.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%AE%97%E6%B3%95/12%E3%80%81KMP%E7%AE%97%E6%B3%95.c) 153 | 154 | ## 四、经典查找算法 155 | 156 | 1. [binarySearch.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95/1%E3%80%81binarySearch.c) 157 | 2. [binarySearch_other.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95/2%E3%80%81binarySearch_other.c) 158 | 3. [出现次数一半的数.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95/3%E3%80%81%E5%87%BA%E7%8E%B0%E6%AC%A1%E6%95%B0%E4%B8%80%E5%8D%8A%E7%9A%84%E6%95%B0.c) 159 | 4. [出现次数超过一半以上的数.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95/4%E3%80%81%E5%87%BA%E7%8E%B0%E6%AC%A1%E6%95%B0%E8%B6%85%E8%BF%87%E4%B8%80%E5%8D%8A%E4%BB%A5%E4%B8%8A%E7%9A%84%E6%95%B0.c) 160 | 5. [杨氏矩阵查找.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E7%BB%8F%E5%85%B8%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95/5%E3%80%81%E6%9D%A8%E6%B0%8F%E7%9F%A9%E9%98%B5%E6%9F%A5%E6%89%BE.c) 161 | 162 | ## 五、数组常见算法 163 | 164 | 1. [和为定值的2个数.cpp](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E6%95%B0%E7%BB%84%E5%B8%B8%E8%A7%81%E7%AE%97%E6%B3%95/1%E3%80%81%E5%92%8C%E4%B8%BA%E5%AE%9A%E5%80%BC%E7%9A%842%E4%B8%AA%E6%95%B0.cpp) 165 | 2. [奇数位于偶数前面.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E6%95%B0%E7%BB%84%E5%B8%B8%E8%A7%81%E7%AE%97%E6%B3%95/2%E3%80%81%E5%A5%87%E6%95%B0%E4%BD%8D%E4%BA%8E%E5%81%B6%E6%95%B0%E5%89%8D%E9%9D%A2.c) 166 | 3. [数组逆序.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E6%95%B0%E7%BB%84%E5%B8%B8%E8%A7%81%E7%AE%97%E6%B3%95/3%E3%80%81%E6%95%B0%E7%BB%84%E9%80%86%E5%BA%8F.c) 167 | 4. [随机化数组.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E6%95%B0%E7%BB%84%E5%B8%B8%E8%A7%81%E7%AE%97%E6%B3%95/4%E3%80%81%E9%9A%8F%E6%9C%BA%E5%8C%96%E6%95%B0%E7%BB%84.c) 168 | 5. [通用的二维数组.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E6%95%B0%E7%BB%84%E5%B8%B8%E8%A7%81%E7%AE%97%E6%B3%95/5%E3%80%81%E9%80%9A%E7%94%A8%E7%9A%84%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84.c) 169 | 6. [寻找一个数组中的第二大数字.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E6%95%B0%E7%BB%84%E5%B8%B8%E8%A7%81%E7%AE%97%E6%B3%95/7%E3%80%81%E5%AF%BB%E6%89%BE%E4%B8%80%E4%B8%AA%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E7%AC%AC%E4%BA%8C%E5%A4%A7%E6%95%B0%E5%AD%97.c) 170 | 7. [寻找最小的k个数.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E6%95%B0%E7%BB%84%E5%B8%B8%E8%A7%81%E7%AE%97%E6%B3%95/8%E3%80%81%E5%AF%BB%E6%89%BE%E6%9C%80%E5%B0%8F%E7%9A%84k%E4%B8%AA%E6%95%B0.c) 171 | 172 | ## 六、高频树算法 173 | 174 | 1. [二叉树创建及方法实现.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E6%A0%91%E7%AE%97%E6%B3%95/1%E3%80%81%E4%BA%8C%E5%8F%89%E6%A0%91%E5%88%9B%E5%BB%BA%E5%8F%8A%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0.c) 175 | 2. [二叉树非递归遍历.cpp](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E6%A0%91%E7%AE%97%E6%B3%95/2%E3%80%81%E4%BA%8C%E5%8F%89%E6%A0%91%E9%9D%9E%E9%80%92%E5%BD%92%E9%81%8D%E5%8E%86.cpp) 176 | 3. [前中后创建二叉树.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E9%AB%98%E9%A2%91%E6%A0%91%E7%AE%97%E6%B3%95/3%E3%80%81%E5%89%8D%E4%B8%AD%E5%90%8E%E5%88%9B%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91.c) 177 | 178 | ## 七、字符串函数实现算法 179 | 180 | 1. [strlen.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E7%AE%97%E6%B3%95/1%E3%80%81strlen.c) 181 | 2. [strcpy.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E7%AE%97%E6%B3%95/2%E3%80%81strcpy.c) 182 | 3. [strcmp.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E7%AE%97%E6%B3%95/3%E3%80%81strcmp.c) 183 | 4. [strcat.c](https://github.com/puge-up/computer-basics/blob/main/algorithm/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E7%AE%97%E6%B3%95/4%E3%80%81strcat.c) 184 | 185 | # 面经 186 | 187 | 1. Java 面经 pdf 188 | 2. C++ 面经 pdf 189 | 3. 。。。 190 | 191 | --- 192 | >**获取面经方式:wx搜索公众号【程序员谱戈】,后台回复:面经,即可获取以上 Java/C++ 面经 pdf。** 193 | > 194 | > **如果百度网盘链接失效,请发【邮件】联系我,说明你的来意即可,我会通过邮件发送给你对应的资料。** 195 | 196 | --- 197 | 198 | # 声明 199 | 200 | - 全网网名:谱戈 201 | - 邮箱:1042068690@qq.com 202 | - 公众号【程序员谱戈】,【编程剑谱】欢迎关注 203 | - 知识星球:[谱戈和他的朋友们](https://t.zsxq.com/FYbm6aA) 204 | - 交流群:校招、社招、技术群欢迎加入 205 | - 所有文章均原创,严禁抄袭,违者必究 206 | 207 | **非常经典的一句话送给各位:** 208 | 209 | > 一个剑客,和对手狭路相逢,他发现对方竟是天下第一剑客,这时候他明知是死,也必须亮出宝剑!没有这个勇气就别当剑客,倒在对手的剑下不丢人,要是不敢亮剑,那才叫丢脸。 210 | > 211 | > 这也是我为啥这么多年了,还一直喜欢《亮剑》这部剧的原因,主要是精气神,这比啥都重要! 212 | -------------------------------------------------------------------------------- /algorithm/十大排序算法/10、radixSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 基数排序,时间复杂度:O(n) 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | void radixSort(int *a, int count); 9 | void countSort(int *bitNumber, int count, int *newA, int *c, int *a); 10 | void showArray(int *a, int count); 11 | 12 | void showArray(int *a, int count){ 13 | int i; 14 | 15 | for(i = 0; i < count; i++){ 16 | printf("%d ", a[i]); 17 | } 18 | printf("\n"); 19 | } 20 | 21 | void countSort(int *bitNumber, int count, int *newA, int *c, int *a){ 22 | int i; 23 | 24 | // 从个位-->十位-->百位,每一次调用这个函数,辅助空间都必须初始化为0; 25 | for(i = 0; i < 10; i++){ 26 | c[i] = 0; 27 | } 28 | 29 | for(i = 0; i < count; i++){ 30 | c[bitNumber[i]]++; 31 | } 32 | 33 | for(i = 1; i < 10; i++){ 34 | c[i] += c[i-1]; 35 | } 36 | 37 | for(i = count-1; i >= 0; i--){ 38 | newA[c[bitNumber[i]]-1] = a[i]; // a[i]与原先所取的位顺序一致 39 | c[bitNumber[i]]--; 40 | } 41 | } 42 | 43 | void radixSort(int *a, int count){ 44 | int *bitNumber; 45 | int *newA; 46 | int c[10] = {0}; 47 | int i; 48 | 49 | // 个位进行排序 50 | bitNumber = (int *)malloc(sizeof(int) * count); 51 | newA = (int *)malloc(sizeof(int) * count); 52 | for(i = 0; i < count; i++){ 53 | bitNumber[i] = a[i]%10; 54 | } 55 | countSort(bitNumber, count, newA, c, a); // bitNumber:代表要排的数字;newA:代表最终排行的新空间 56 | // c:代表辅助空间 a:代表原先数字 57 | for(i = 0; i < count; i++){ 58 | a[i] = newA[i]; 59 | } 60 | 61 | // 十位进行排序 62 | for(i = 0; i < count; i++){ 63 | bitNumber[i] = a[i]/10%10; 64 | } 65 | countSort(bitNumber, count, newA, c, a); 66 | for(i = 0; i < count; i++){ 67 | a[i] = newA[i]; 68 | } 69 | 70 | // 百位排序 71 | for(i = 0; i < count; i++){ 72 | bitNumber[i] = a[i]/100%10; 73 | } 74 | countSort(bitNumber, count, newA, c, a); 75 | 76 | for(i = 0; i < count; i++){ 77 | a[i] = newA[i]; 78 | } 79 | // 千位排序 80 | for(i = 0; i < count; i++){ 81 | bitNumber[i] = a[i]/1000%10; 82 | } 83 | countSort(bitNumber, count, newA, c, a); 84 | 85 | for(i = 0; i < count; i++){ 86 | a[i] = newA[i]; 87 | } 88 | 89 | } 90 | 91 | void main(void){ 92 | int a[] = {23, 1000, 90, 34, 2, 6, 3, 444, 555, 666, 777, 888, 999, 111, 222}; 93 | int count = sizeof(a)/sizeof(int); 94 | radixSort(a, count); 95 | showArray(a, count); 96 | } -------------------------------------------------------------------------------- /algorithm/十大排序算法/1、swapSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 冒泡排序,时间复杂度:O(n^2) 3 | */ 4 | 5 | #include 6 | 7 | void swapSort(int *a, int count); 8 | void showArray(int *a, int count); 9 | 10 | void showArray(int *a, int count){ 11 | int i; 12 | 13 | for(i = 0; i < count; i++){ 14 | printf("%d ", a[i]); 15 | } 16 | 17 | printf("\n"); 18 | } 19 | 20 | void swapSort(int *a, int count){ 21 | int i; 22 | int j; 23 | int tmp; 24 | 25 | for(i = 0; i < count; i++){ 26 | for(j = 0; j < count-i-1; j++){ 27 | if(a[j] > a[j+1]){ 28 | tmp = a[j]; 29 | a[j] = a[j+1]; 30 | a[j+1] = tmp; 31 | } 32 | } 33 | } 34 | } 35 | 36 | void main(void){ 37 | int a[] = {3, 5, 7, 9, 1, 6, 10}; 38 | int count = sizeof(a)/sizeof(int); 39 | 40 | swapSort(a, count); 41 | showArray(a, count); 42 | } -------------------------------------------------------------------------------- /algorithm/十大排序算法/2、chooseSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 选择排序,时间复杂度:O(n^2) 3 | */ 4 | 5 | #include 6 | 7 | void sort(int *a, int count); 8 | void showArray(int *a, int count); 9 | 10 | void showArray(int *a, int count){ 11 | int i; 12 | 13 | for(i = 0; i < count; i++){ 14 | printf("%d ", a[i]); 15 | } 16 | printf("\n"); 17 | } 18 | 19 | void sort(int *a, int count){ 20 | int i; 21 | int j; 22 | int tmp; 23 | 24 | for(i = 0; i < count; i++){ 25 | for(j = i+1; j < count; j++){ 26 | if(a[i] > a[j]){ 27 | tmp = a[i]; 28 | a[i] = a[j]; 29 | a[j] = tmp; 30 | } 31 | } 32 | } 33 | } 34 | 35 | void main(void){ 36 | int a[] = {3 ,5 ,6, 1, 7, 2, 9, 8}; 37 | int count = sizeof(a)/sizeof(int); 38 | 39 | sort(a, count); 40 | showArray(a, count); 41 | } 42 | -------------------------------------------------------------------------------- /algorithm/十大排序算法/3、insertSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 插入排序,时间复杂度:O(n^2) 3 | */ 4 | 5 | #include 6 | 7 | void insertSort(int *a, int count); 8 | void showArray(int *a, int count); 9 | 10 | void showArray(int *a, int count){ 11 | int i; 12 | 13 | for(i = 0; i < count; i++){ 14 | printf("%d ", a[i]); 15 | } 16 | printf("\n"); 17 | } 18 | 19 | void insertSort(int *a, int count){ 20 | int i; 21 | int j; 22 | int n; 23 | int tmp; 24 | 25 | for(i = 1; i < count; i++){ 26 | tmp = a[i]; 27 | for(j = 0; a[i]>a[j] && j j; n--){ 32 | a[n] = a[n-1]; 33 | } 34 | a[j] = tmp; 35 | } 36 | } 37 | } 38 | 39 | void main(void){ 40 | int a[] = {2, 5, 7, 1, 11, 0, 6, 9}; 41 | int count = sizeof(a)/sizeof(int); 42 | 43 | printf("排序前输出如下: "); 44 | showArray(a, count); 45 | insertSort(a, count); 46 | printf("排序后输出如下: "); 47 | showArray(a, count); 48 | } -------------------------------------------------------------------------------- /algorithm/十大排序算法/4、mergeSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 归并排序,时间复杂度:O(nlogn) 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | void mergeSort(int *a, int low, int high); 9 | void merge(int *a, int low, int mid, int high); 10 | 11 | void merge(int *a, int low, int mid, int high){ 12 | int i = low; 13 | int j = mid+1; 14 | int n = 0; 15 | int *a2; 16 | 17 | a2 = (int *)malloc(sizeof(int) * (high-low+1)); 18 | if(a2 == NULL){ 19 | return; 20 | } 21 | 22 | // 以下都是<=,因为传过来的都是下标; 23 | while(i <= mid && j <= high){ 24 | if(a[i] < a[j]){ 25 | a2[n++] = a[i]; 26 | i++; 27 | }else if(a[i] == a[j]){ 28 | a2[n++] = a[i]; 29 | i++; 30 | j++; 31 | }else{ 32 | a2[n++] = a[j]; 33 | j++; 34 | } 35 | } 36 | 37 | while(i <= mid){ 38 | a2[n++] = a[i]; 39 | i++; 40 | } 41 | while(j <= high){ 42 | a2[n++] = a[j]; 43 | j++; 44 | } 45 | 46 | for(n = 0, i = low; i <= high; n++, i++){ // 将a2中的元素复制回a中; 47 | a[i] = a2[n]; 48 | } 49 | 50 | free(a2); 51 | } 52 | 53 | void mergeSort(int *a, int low, int high){ 54 | int mid; 55 | if(low < high){ 56 | mid = (low + high) / 2; 57 | mergeSort(a, low, mid); 58 | mergeSort(a, mid+1, high); 59 | merge(a, low, mid, high); 60 | } 61 | } 62 | 63 | void main(void){ 64 | int a[] = {2, 4, 1, 7, 5, 6, 9, 10}; 65 | int count = sizeof(a)/sizeof(int); 66 | int i; 67 | 68 | mergeSort(a, 0, count-1); 69 | for(i = 0; i < count; i++){ 70 | printf("%d ", a[i]); 71 | } 72 | printf("\n"); 73 | 74 | } -------------------------------------------------------------------------------- /algorithm/十大排序算法/5、shellSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 希尔排序,时间复杂度:平均 O(nlogn),最坏O(n^2) 3 | */ 4 | 5 | #include 6 | 7 | void insertSort(int *a, int count, int step); 8 | void showArray(int *a, int count); 9 | void shellSort(int *a, int count); 10 | 11 | void shellSort(int *a, int count){ 12 | int step; 13 | 14 | for(step = count/2; step > 0; step /= 2){ 15 | insertSort(a, count, step); 16 | } 17 | } 18 | 19 | void showArray(int *a, int count){ 20 | int i; 21 | 22 | for(i = 0; i < count; i++){ 23 | printf("%d ", a[i]); 24 | } 25 | printf("\n"); 26 | } 27 | 28 | // 以下就是插入排序了,思想完全一样,只不过步长为step而已!!! 29 | void insertSort(int *a, int count, int step){ 30 | int i; 31 | int j; 32 | int n; 33 | int tmp; 34 | 35 | for(i = step; i < count; i+=step){ 36 | tmp = a[i]; 37 | for(j = 0; a[i]>a[j] && j j; n-=step){ 42 | a[n] = a[n-step]; 43 | } 44 | a[j] = tmp; 45 | } 46 | } 47 | } 48 | 49 | void main(void){ 50 | int a[] = {2, 7, 1, 11, 0, 9, 8, 10}; 51 | int count = sizeof(a)/sizeof(int); 52 | 53 | printf("排序前输出如下: "); 54 | showArray(a, count); 55 | shellSort(a, count); 56 | printf("排序后输出如下: "); 57 | showArray(a, count); 58 | 59 | } -------------------------------------------------------------------------------- /algorithm/十大排序算法/6、heapSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 堆排序,时间复杂度:O(nlogn) 3 | */ 4 | 5 | #include 6 | 7 | void heapSort(int *a, int count); 8 | void siftDown(int *a, int count, int start); 9 | void swap(int *a, int *b); 10 | int removeHeap(int *a, int n); 11 | 12 | int removeHeap(int *a, int n){ 13 | int key = a[0]; 14 | 15 | a[0] = a[n]; 16 | siftDown(a, n, 0); 17 | 18 | return key; 19 | } 20 | 21 | void swap(int *a, int *b){ 22 | int tmp; 23 | 24 | tmp = *a; 25 | *a = *b; 26 | *b = tmp; 27 | } 28 | 29 | void siftDown(int *a, int count, int start){ 30 | int i = start; 31 | int j = 2*i+1; 32 | 33 | while(j < count){ // 说明有左子树 34 | if(j < count-1 && a[j] > a[j+1]){ // 表示存在右孩子的情况下; 35 | j++; // j:表示指向左右子树中最小的一个 36 | } 37 | if(a[i] <= a[j]){ 38 | break; // 不用调整,父节点的值是最小的; 39 | }else{ 40 | swap(&a[i], &a[j]); 41 | // 交换 42 | i = j; // 一直往树下交换,一直调整到叶子结点 43 | j = 2*i+1; 44 | } 45 | } 46 | } 47 | 48 | void heapSort(int *a, int count){ 49 | int curPos = count/2-1; // 最后一个非叶子结点 50 | int i; 51 | int key; 52 | 53 | while(curPos >= 0){ 54 | siftDown(a, count, curPos); 55 | curPos--; 56 | } 57 | /* 输出构建好的堆结构 58 | for(i = 0; i < count; i++){ 59 | printf("%d ", a[i]); 60 | } 61 | printf("\n"); 62 | */ 63 | 64 | for(i = 0; i < count; i++){ 65 | key = removeHeap(a, count-i-1); // 传参:第二个参数是下标 66 | printf("%d ", key); 67 | } 68 | printf("\n"); 69 | } 70 | 71 | void main(void){ 72 | int a[] = {3, 5, 7, 1, 4, 2, 9, 10}; 73 | int count = sizeof(a)/sizeof(int); 74 | 75 | heapSort(a, count); 76 | } -------------------------------------------------------------------------------- /algorithm/十大排序算法/7、quickSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 快速排序,时间复杂度:平均 O(nlogn),最坏O(n^2) 3 | */ 4 | 5 | #include 6 | 7 | int oneQuickSort(int *a, int i, int j); 8 | void quickSort(int *a, int i, int j); 9 | void showArray(int *a, int count); 10 | 11 | void showArray(int *a, int count){ 12 | int i; 13 | 14 | for(i = 0; i < count; i++){ 15 | printf("%d ", a[i]); 16 | } 17 | printf("\n"); 18 | } 19 | void quickSort(int *a, int i, int j){ 20 | int index; 21 | 22 | if(i < j){ 23 | index = oneQuickSort(a, i, j); 24 | quickSort(a, i, index-1); 25 | quickSort(a, index+1, j); 26 | } 27 | } 28 | 29 | int oneQuickSort(int *a, int i, int j){ 30 | int tmp; 31 | 32 | tmp = a[i]; 33 | while(i < j){ 34 | while(i < j && a[j] > tmp){ 35 | j--; 36 | } 37 | if(i < j){ 38 | a[i++] = a[j]; 39 | } 40 | while(i < j && a[i] < tmp){ 41 | i++; 42 | } 43 | if(i < j){ 44 | a[j--] = a[i]; 45 | } 46 | } 47 | a[i] = tmp; 48 | 49 | return i; 50 | } 51 | 52 | void main(void){ 53 | int a[] = {3, 7, 1, 0, 9, -9,}; 54 | int count = sizeof(a)/sizeof(int); 55 | 56 | quickSort(a, 0, count-1); 57 | showArray(a, count); 58 | } -------------------------------------------------------------------------------- /algorithm/十大排序算法/8、bucketSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 桶排序,时间复杂度:O(n) 3 | */ 4 | 5 | #include 6 | 7 | void bucketSort(int *a, int count); 8 | void showArray(int *a, int count); 9 | 10 | void showArray(int *a, int count){ 11 | int i; 12 | 13 | for(i = 0; i < count; i++){ 14 | printf("%d ", a[i]); 15 | } 16 | printf("\n"); 17 | } 18 | 19 | void bucketSort(int *a, int count){ 20 | int b[10] = {0}; // 知道要排序值的最大范围 21 | int i; 22 | int n = 0; 23 | 24 | for(i = 0; i < count; i++){ 25 | b[a[i]]++; 26 | } 27 | 28 | for(i = 0; i < 10; i++){ 29 | if(b[i]){ 30 | a[n++] = i; 31 | } 32 | } 33 | } 34 | 35 | void main(void){ 36 | int a[] = {3, 5, 1, 8, 9, 6}; 37 | int count = sizeof(a)/sizeof(int); 38 | 39 | bucketSort(a, count); 40 | showArray(a, count); 41 | } -------------------------------------------------------------------------------- /algorithm/十大排序算法/9、countSort.c: -------------------------------------------------------------------------------- 1 | /* 2 | 计数排序,时间复杂度:O(n) 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | void countSort(int *a, int count); 9 | void showArray(int *a, int count); 10 | 11 | void showArray(int *a, int count){ 12 | int i; 13 | 14 | for(i = 0; i < count; i++){ 15 | printf("%d ", a[i]); 16 | } 17 | printf("\n"); 18 | } 19 | 20 | void countSort(int *a, int count){ 21 | int b[10] = {0}; 22 | int *c; 23 | int i; 24 | 25 | c = (int *)malloc(sizeof(int) * count); 26 | for(i = 0; i < count; i++){ 27 | b[a[i]]++; 28 | } 29 | for(i = 1; i < 10; i++){ 30 | b[i] += b[i-1]; 31 | } 32 | 33 | for(i = count-1; i >= 0; i--){ 34 | c[b[a[i]]-1] = a[i]; 35 | b[a[i]]--; 36 | } 37 | 38 | for(i = 0; i < count; i++){ 39 | a[i] = c[i]; 40 | } 41 | 42 | free(c); 43 | 44 | } 45 | void main(void){ 46 | int a[] = {2, 4, 7, 2, 1, 0, 9}; 47 | int count = sizeof(a)/sizeof(int); 48 | 49 | countSort(a, count); 50 | showArray(a, count); 51 | } -------------------------------------------------------------------------------- /algorithm/字符串函数实现算法/1、strlen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // 假如不允许使用变量进行计数,此时就得进行递归计算,是一种倒着加回去的思想; 5 | size_t myStrlen_1(const char *str); 6 | size_t myStrlen_1(const char *str){ 7 | assert(str != NULL); 8 | 9 | if(*str == 0){ 10 | return 0; 11 | }else{ 12 | return myStrlen_1(str+1)+1; 13 | } 14 | } 15 | 16 | //typedef unsigned int size_t; 17 | size_t myStrlen(const char *str); 18 | size_t myStrlen(const char *str){ 19 | const char *ptmp = str; // 1、对参数进行保护机制 20 | size_t count = 0; 21 | 22 | assert(str != NULL); // 2、对参数的合法性进行断言 23 | while(*ptmp++){ // 此处的++运算符的优先级大于*,但是是后++,所以先进行指向运算,在进行++; 24 | count++; 25 | } 26 | 27 | return count; 28 | } 29 | 30 | int main(void){ 31 | char *str = "Hello C"; 32 | 33 | printf("%d\n", myStrlen_1(str)); 34 | return 0; 35 | } -------------------------------------------------------------------------------- /algorithm/字符串函数实现算法/2、strcpy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // 字符串的拷贝操作:连同0结束标志一起进行拷贝; 5 | char *myStrcpy(char *strD, const char *strS); 6 | 7 | char *myStrcpy(char *strD, const char *strS){ 8 | char *ptmpD = strD; 9 | const char *ptmpS = strS; 10 | 11 | assert(ptmpD != NULL && ptmpS != NULL); 12 | while(*ptmpS){ 13 | *ptmpD++ = *ptmpS++; 14 | } 15 | *ptmpD = 0; // 连同0标志一同进行拷贝; 16 | 17 | return strD; 18 | } 19 | 20 | int main(void){ 21 | char s1[20] = "hello"; // 保证要拷贝的空间足够; 22 | char *s2 = "wor"; 23 | 24 | printf("%s\n", myStrcpy(s1, s2)); 25 | return 0; 26 | } -------------------------------------------------------------------------------- /algorithm/字符串函数实现算法/3、strcmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int myStrcmp_1(const char *str1, const char *str2); 5 | int myStrcmp_1(const char *str1, const char *str2){ 6 | const char *s1 = str1; 7 | const char *s2 = str2; 8 | int result = 0; 9 | 10 | // 简便的算法 11 | assert(str1 != NULL && str2 != NULL); 12 | while(*s1 || *s2){ 13 | result = *s1 - *s2; 14 | if(result){ 15 | break; 16 | } 17 | s1++; 18 | s2++; 19 | } 20 | if(result > 0){ 21 | result = 1; 22 | }else if(result < 0){ 23 | result = -1; 24 | } 25 | 26 | return result; 27 | } 28 | 29 | // 字符串的连接和复制一定要记住给最后的一个字符空间赋值为0; 30 | int myStrcmp(const char *str1, const char *str2); 31 | 32 | int myStrcmp(const char *str1, const char *str2){ 33 | const char *s1 = str1; 34 | const char *s2 = str2; 35 | 36 | assert(str1 != NULL && str2 != NULL); 37 | while(*s1 && *s2){ 38 | if(*s1 > *s2){ 39 | return 1; 40 | }else if(*s1 < *s2){ 41 | return -1; 42 | }else{ 43 | s1++; 44 | s2++; 45 | } 46 | } 47 | if(*s1 && *s2 == NULL){ 48 | return 1; 49 | }else if(*s1 == NULL && *s2){ 50 | return -1; 51 | } 52 | 53 | return 0; 54 | 55 | } 56 | 57 | int main(void){ 58 | char *s1 = "hello"; 59 | char *s2 = "hello"; 60 | int result; 61 | 62 | result = myStrcmp_1(s1, s2); 63 | if(result == 0){ 64 | printf("s1 == s2\n"); 65 | }else if(result > 0){ 66 | printf("s1 > s2\n"); 67 | }else{ 68 | printf("s1 < s2\n"); 69 | } 70 | return 0; 71 | } -------------------------------------------------------------------------------- /algorithm/字符串函数实现算法/4、strcat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | char *myStrcat(char *strD, const char *strS); 5 | 6 | char *myStrcat(char *strD, const char *strS){ // 返回的是第一个字符串的地址:s1 += s2; 7 | char *ptmpD = strD; // 1、对原参数的保护机制 8 | const char *ptmpS = strS; 9 | 10 | assert(strD != NULL && strS != NULL); // 断言,防止出错; 11 | 12 | while(*ptmpD){ // 目标的先走到第一个字符串的末尾 13 | ptmpD++; 14 | } 15 | 16 | while(*ptmpS){ // 原的不为空,将原的一个一个字符的拷到目标的字符串中 17 | *ptmpD++ = *ptmpS++; 18 | } 19 | *ptmpD = 0; // 最后一个字符的空间必须赋值为0; 20 | 21 | return strD; 22 | } 23 | 24 | int main(void){ 25 | char s1[20] = "hello"; // 申请足够的空间够连接的; 26 | char *s2 = "world"; 27 | 28 | printf("%s\n", myStrcat(s1, s2)); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /algorithm/数组常见算法/1、和为定值的2个数.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | void twoSum(vector &v1, int sum); 9 | 10 | void twoSum(vector &v1, int sum){ 11 | int begin = 0; 12 | int end = v1.size()-1; 13 | 14 | while(begin < end){ 15 | if(v1[begin] + v1[end] == sum){ 16 | printf("%d %d\n", v1[begin], v1[end]); 17 | break; 18 | }else if(v1[begin] + v1[end] < sum){ 19 | begin++; 20 | }else{ 21 | end--; 22 | } 23 | } 24 | 25 | if(begin == end){ 26 | printf("和为定值 = %d\n", sum); 27 | } 28 | } 29 | 30 | void main(void){ 31 | int a[] = {3, 5, 1, 8, 4, 0,}; 32 | int count = sizeof(a)/sizeof(int); 33 | int i; 34 | vector v1; 35 | 36 | for(i = 0; i < count; i++){ 37 | v1.push_back(a[i]); 38 | } 39 | sort(v1.begin(), v1.end(), less()); 40 | 41 | twoSum(v1, 9); 42 | 43 | } -------------------------------------------------------------------------------- /algorithm/数组常见算法/2、奇数位于偶数前面.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // 保持奇偶顺序不变的话,就得开辟新的空间,第一遍遍历只放奇数,在奇数的后面,第二遍遍历只放偶数; 4 | void adjustArray(int *a, int count); 5 | void swap(int *a, int *b); 6 | 7 | void swap(int *a, int *b){ 8 | int tmp; 9 | 10 | tmp = *a; 11 | *a = *b; 12 | *b = tmp; 13 | } 14 | 15 | void adjustArray(int *a, int count){ 16 | int front = 0; 17 | int back = count-1; 18 | 19 | if(a == NULL || count < 2){ // 代码的鲁棒性的验证 20 | return; 21 | } 22 | 23 | while(front < back){ 24 | if(a[front]%2 == 1){ 25 | front++; 26 | }else if(a[back] % 2 == 0){ 27 | back--; 28 | }else{ 29 | swap(&a[front], &a[back]); 30 | } 31 | } 32 | 33 | } 34 | 35 | void main(void){ 36 | int a[] = {4, 3, 5, 2, 7, 1, 9}; 37 | int count = sizeof(a)/sizeof(int); 38 | int i; 39 | 40 | adjustArray(a, count); 41 | for(i = 0; i < count; i++){ 42 | printf("%d ", a[i]); 43 | } 44 | printf("\n"); 45 | 46 | } -------------------------------------------------------------------------------- /algorithm/数组常见算法/3、数组逆序.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void arrayRev(int *a, int count); 4 | void printT(int *a, int count); 5 | 6 | void printT(int *a, int count){ 7 | int i; 8 | 9 | for(i = 0; i < count; i++){ 10 | printf("%d ", a[i]); 11 | } 12 | } 13 | void arrayRev(int *a, int count){ 14 | int low = 0; 15 | int high = count-1; 16 | int tmp; 17 | 18 | while(low < high){ 19 | tmp = a[low]; 20 | a[low] = a[high]; 21 | a[high] = tmp; 22 | low++; 23 | high--; 24 | } 25 | } 26 | int main(void){ 27 | int a[] = {1, 4, 2, 6, 8, 9, 11, 43, 12, 55,}; 28 | int len; 29 | 30 | len = sizeof(a)/sizeof(a[0]); 31 | 32 | printf("排序前:\n"); 33 | printT(a, len); 34 | arrayRev(a, len); 35 | printf("\n排序后:\n"); 36 | printT(a, len); 37 | printf("\n"); 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /algorithm/数组常见算法/4、随机化数组.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void showArray(int *a, int count); 6 | void random_1(int *a, int count); 7 | void random_1(int *a, int count){ 8 | int i; 9 | int tmp; 10 | int index; 11 | 12 | srand(time(NULL)); 13 | for(i = count; i > 0; i--){ 14 | index = rand()%i; 15 | tmp = a[index]; 16 | a[index] = a[i-1]; 17 | a[i-1] = tmp; 18 | } 19 | 20 | } 21 | void showArray(int *a, int count){ 22 | int i; 23 | 24 | for(i = 0; i < count; i++){ 25 | printf("%d ", a[i]); 26 | } 27 | printf("\n"); 28 | } 29 | 30 | 31 | int main(void){ 32 | int a[] = {4, 6, 8, 2, 0, 7, 1,}; 33 | int count = sizeof(a)/sizeof(int); 34 | 35 | showArray(a, count); 36 | random_1(a, count); 37 | showArray(a, count); 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /algorithm/数组常见算法/5、通用的二维数组.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef unsigned char boolean; 5 | typedef int USER_TYPE; 6 | 7 | typedef struct MATRIX{ 8 | USER_TYPE *data; 9 | int maxRow; 10 | int maxCol; 11 | }MATRIX; 12 | 13 | #define TRUE 1 14 | #define FALSE 0 15 | 16 | void initMatrix(MATRIX **matrixHead, int maxRow, int maxCol); 17 | void destoryMatrix(MATRIX **matrixHead); 18 | boolean setElementAt(MATRIX matrix, int row, int col, USER_TYPE value); 19 | boolean getElementAt(MATRIX matrix, int row, int col, USER_TYPE *value); 20 | 21 | boolean getElementAt(MATRIX matrix, int row, int col, USER_TYPE *value){ 22 | if(row < 0 || col < 0 || row >= matrix.maxRow || col >= matrix.maxCol){ 23 | return FALSE; 24 | } 25 | 26 | *value = matrix.data[row*matrix.maxCol + col]; 27 | 28 | return TRUE; 29 | } 30 | 31 | boolean setElementAt(MATRIX matrix, int row, int col, USER_TYPE value){ 32 | if(row < 0 || col < 0 || row >= matrix.maxRow || col >= matrix.maxCol){ 33 | return FALSE; 34 | } 35 | 36 | matrix.data[row*matrix.maxCol + col] = value; 37 | 38 | return TRUE; 39 | } 40 | 41 | 42 | void destoryMatrix(MATRIX **matrixHead){ 43 | if(*matrixHead == NULL){ 44 | return; 45 | } 46 | 47 | if((*matrixHead)->data != NULL){ 48 | free((*matrixHead)->data); 49 | } 50 | free(*matrixHead); 51 | *matrixHead = NULL; 52 | 53 | } 54 | 55 | void initMatrix(MATRIX **matrixHead, int maxRow, int maxCol){ 56 | MATRIX *matrix = NULL; 57 | 58 | if(*matrixHead != NULL || maxRow <= 0 || maxCol <= 0){ 59 | return; 60 | } 61 | 62 | matrix = (MATRIX *)calloc(sizeof(MATRIX), 1); 63 | matrix->maxRow = maxRow; 64 | matrix->maxCol = maxCol; 65 | 66 | matrix->data = (USER_TYPE *)calloc(sizeof(USER_TYPE), maxRow * maxCol); 67 | 68 | *matrixHead = matrix; 69 | } 70 | 71 | void main(void){ 72 | MATRIX *matrix = NULL; 73 | int maxRow; 74 | int maxCol; 75 | int value; 76 | 77 | printf("请输入二维数组的行、列: "); 78 | scanf("%d%d", &maxRow, &maxCol); 79 | initMatrix(&matrix, maxRow, maxCol); 80 | setElementAt(*matrix, 1, 1, 2); // 用户的做自己返回时检测 81 | getElementAt(*matrix, 1, 1, &value); // 用户的做自己返回时检测 82 | 83 | printf("matrix[1][1] = %d\n", value); 84 | 85 | destoryMatrix(&matrix); 86 | } -------------------------------------------------------------------------------- /algorithm/数组常见算法/7、寻找一个数组中的第二大数字.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int secondMax(int *a, int len); 4 | void printT(int *a, int count); 5 | 6 | void printT(int *a, int count){ 7 | int i; 8 | 9 | for(i = 0; i < count; i++){ 10 | printf("%d ", a[i]); 11 | } 12 | printf("\n"); 13 | } 14 | int secondMax(int *a, int len){ 15 | int max = a[0] > a[1] ? a[0] : a[1]; 16 | int second = a[0] > a[1] ? a[1] : a[0]; 17 | int i; 18 | 19 | for(i = 2; i < len; i++){ 20 | if(a[i] > max){ 21 | second = max; 22 | max = a[i]; 23 | }else if(a[i] > second){ 24 | second = a[i]; 25 | }else{ 26 | ; 27 | } 28 | } 29 | return second; 30 | } 31 | 32 | int main(void){ 33 | int a[] = {44, 4, 66, 6, 8, 33, 22, 2 ,55 ,1}; 34 | int len = sizeof(a)/sizeof(a[0]); 35 | int num; 36 | 37 | num = secondMax(a, len); 38 | printT(a, len); 39 | printf("%d\n", num); 40 | 41 | return 0; 42 | } -------------------------------------------------------------------------------- /algorithm/数组常见算法/8、寻找最小的k个数.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void findKSmall(int *a, int start, int end, int key); 4 | // 最小的k个数和最小的第k个数 5 | void findKSmall(int *a, int start, int end, int key){ 6 | int i = start; 7 | int j = end; 8 | int tmp = a[i]; 9 | // 快排中的升序 10 | while(i < j){ 11 | while(i < j && a[j] > tmp){ 12 | j--; 13 | } 14 | if(i < j){ 15 | a[i++] = a[j]; 16 | } 17 | while(i < j && a[i] < tmp){ 18 | i++; 19 | } 20 | if(i < j){ 21 | a[j--] = a[i]; 22 | } 23 | } 24 | a[i] = tmp; 25 | 26 | if(key-1 < i){ 27 | findKSmall(a, 0, i-1, key); 28 | }else if(key-1 > i){ 29 | findKSmall(a, i+1, end, key); 30 | }else{ 31 | return; 32 | } 33 | } 34 | 35 | void main(void){ 36 | int a[] = {8, 4, 6, 9, 2, 3, 7, 9, 11, 10}; 37 | int count = sizeof(a)/sizeof(int); 38 | int k; 39 | int i; 40 | 41 | printf("请输入要查找的第k小的数:"); 42 | scanf("%d", &k); 43 | findKSmall(a, 0, count-1, k); 44 | for(i = 0; i < count; i++){ 45 | printf("%d ", a[i]); 46 | } 47 | 48 | printf("\n"); 49 | for(i = 0; i < k; i++){ 50 | printf("%d ", a[i]); 51 | } 52 | printf("\n"); 53 | } -------------------------------------------------------------------------------- /algorithm/算法资料.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/puge-up/computer-basics/ddde2be090fe426082f18c8a90f7df0c6bc517d6/algorithm/算法资料.jpeg -------------------------------------------------------------------------------- /algorithm/经典字符串算法/10、字符串去重.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void main(void){ 4 | char str[] = "abacdefabcde"; 5 | char alpha[128] = {0}; // 辅助空间,桶的思想 6 | char res[80] = {0}; // 存放去重后的结果字符串 7 | int i; 8 | int t = 0; 9 | 10 | for(i = 0; str[i]; i++){ 11 | if(alpha[str[i]] == 0){ 12 | res[t++] = str[i]; 13 | alpha[str[i]]++; 14 | } 15 | } 16 | 17 | for(i = 0; i < t; i++){ 18 | printf("%c", res[i]); 19 | } 20 | printf("\n"); 21 | 22 | } -------------------------------------------------------------------------------- /algorithm/经典字符串算法/11、字符串转换成整数.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define TRUE 1 6 | #define FALSE 0 7 | #define MAX_NUM 2147483647 8 | #define MIN_NUM 2147483648 9 | 10 | char islegal = TRUE; // 设置一个全局变量,用来判断输入的是否合法; 11 | 12 | int strToInt(char *str); 13 | int strToInt(char *str){ 14 | int sign = 1; // 代表正数 15 | int i; 16 | unsigned int num = 0; // 要保证num不能溢出,在做比较的时候 17 | 18 | // int的范围:-2147483648---2147483647 19 | // unsigned int的范围:0-4294967296,此时在保证不溢出的情况下,对数值进行判断; 20 | 21 | if(NULL == str){ // 判断输入是否为空 22 | islegal = FALSE; 23 | return -1; 24 | } 25 | 26 | while(isspace(*str)){ 27 | ++str; 28 | } 29 | if(*str == '+' || *str == '-'){ 30 | if(*str++ == '-'){ 31 | sign = -1; 32 | } 33 | if(*str == 0){ // 字符串只输入了一个+/-都是非法输入; 34 | islegal = FALSE; 35 | return -1; 36 | } 37 | } 38 | 39 | for(i = 0; str[i]; i++){ 40 | if(isdigit(str[i])){ 41 | ; 42 | }else{ 43 | islegal = FALSE; 44 | return -1; 45 | } 46 | } 47 | 48 | while(isdigit(*str)){ // 判断是否为0-9,是的话返回非0,不是返回0 49 | // 此时的难点是判断溢出问题; 50 | num = num * 10 + *str - '0'; 51 | ++str; 52 | 53 | if(sign == 1 && num > MAX_NUM){ 54 | islegal = FALSE; 55 | return -1; 56 | } 57 | if(sign == -1 && num > MIN_NUM){ 58 | islegal = FALSE; 59 | return -1; 60 | } 61 | } 62 | return (sign > 0 ? (int)num : (int)-num); 63 | } 64 | 65 | void main(void){ 66 | char str[80] = {0}; 67 | int num; 68 | 69 | printf("str : "); 70 | gets(str); 71 | num = strToInt(str); 72 | if(islegal == TRUE){ 73 | printf("%d\n", num); 74 | }else{ 75 | printf("输入的是非法的\n"); 76 | } 77 | } -------------------------------------------------------------------------------- /algorithm/经典字符串算法/12、KMP算法.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void KMPnext(const char *sub, int *next); 6 | int findSubIndex(const char *source, const char *sub); 7 | /* 8 | aaaaaaaabaaa 9 | aaabaa 10 | */ 11 | int findSubIndex(const char *source, const char *sub){ 12 | int i = 0; 13 | int j = 0; 14 | int *next; 15 | int len = strlen(source); 16 | 17 | next = (int *)calloc(sizeof(int), len); 18 | KMPnext(sub, next); 19 | 20 | while(source[i]){ 21 | for(j = next[j]; sub[j] && source[i] == sub[j]; i++, j++){ 22 | ; 23 | } 24 | if(sub[j] == 0){ 25 | return i-j; 26 | }else if(j == 0){ 27 | i++; 28 | } 29 | } 30 | free(next); 31 | return -1; 32 | } 33 | 34 | void KMPnext(const char *sub, int *next){ 35 | int index; 36 | int j; 37 | 38 | for(index = 2; sub[index]; index++){ 39 | for(j = index-1; j && sub[next[j]] != sub[index-1]; j = next[j]){ 40 | ; 41 | } 42 | next[index] = j ? next[j]+1 : 0; // 给当前的next数组赋值!!! 43 | } 44 | } 45 | 46 | void main(void){ 47 | char source[80]; 48 | char sub[80]; 49 | 50 | puts("请输入原串: "); 51 | gets(source); 52 | puts("请输入子串: "); 53 | gets(sub); 54 | 55 | printf("%d\n", findSubIndex(source, sub)); 56 | } -------------------------------------------------------------------------------- /algorithm/经典字符串算法/1、串匹配基础算法.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // 时间复杂度为:O(m * n) 5 | int findSubIndex(const char *source, const char *sub); 6 | 7 | int findSubIndex(const char *source, const char *sub){ 8 | int i; 9 | int j; 10 | int len = strlen(source) - strlen(sub); 11 | 12 | for(i = 0; i <= len; i++){ 13 | for(j = 0; sub[j] && source[i+j] == sub[j]; j++){ 14 | ; 15 | } 16 | if(sub[j] == 0){ 17 | return i; 18 | } 19 | } 20 | 21 | return -1; 22 | } 23 | 24 | void main(void){ 25 | char source[80]; 26 | char sub[80]; 27 | 28 | puts("请输入原串: "); 29 | gets(source); 30 | puts("请输入子串: "); 31 | gets(sub); 32 | 33 | printf("%d\n", findSubIndex(source, sub)); 34 | } -------------------------------------------------------------------------------- /algorithm/经典字符串算法/2、单词反转.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | void revStr(char *str, int from, int to); 7 | void finalRev(char *str); 8 | 9 | void finalRev(char *str){ 10 | int from = 0; 11 | int to = 0; 12 | 13 | while(str[to]){ 14 | while(isalpha(str[to])){ 15 | to++; 16 | } 17 | revStr(str, from, to-1); 18 | while(isspace(str[to])){ 19 | to++; 20 | } 21 | from = to; 22 | } 23 | } 24 | 25 | void revStr(char *str, int from, int to){ 26 | char tmp; 27 | 28 | while(from < to){ 29 | tmp = str[from]; 30 | str[from++] = str[to]; 31 | str[to--] = tmp; 32 | } 33 | } 34 | 35 | void main(void){ 36 | char str[80]; 37 | int strLen; 38 | int count = 0; 39 | int i = 0; 40 | 41 | // gets在接收字符串时,可以接收空格,中间的空格都将被接收下来; 42 | // scanf在接收字符串时,遇到空格、回车和Tab键都会认为输入结束,所有它不能接收空格; 43 | printf("请输入字符串: \n"); 44 | gets(str); 45 | strLen = strlen(str); 46 | revStr(str, 0, strLen-1); 47 | finalRev(str); 48 | 49 | puts(str); 50 | } -------------------------------------------------------------------------------- /algorithm/经典字符串算法/3、回文判断.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define TRUE 1 5 | #define FALSE 0 6 | 7 | typedef unsigned char boolean; 8 | 9 | boolean isPalindrome(char *str); 10 | boolean isPalindrome(char *str){ 11 | char *front = str; 12 | char *back; 13 | 14 | if(NULL == str){ 15 | return FALSE; 16 | } 17 | int length = strlen(str); 18 | back = str+length-1; 19 | 20 | while(front < back){ 21 | if(*front == *back){ 22 | front++; 23 | back--; 24 | }else{ 25 | return FALSE; 26 | } 27 | } 28 | 29 | return TRUE; 30 | } 31 | 32 | void main(void){ 33 | char str[80] = {0}; 34 | boolean flag; 35 | 36 | printf("str : "); 37 | gets(str); 38 | flag = isPalindrome(str); 39 | if(flag){ 40 | printf("是回文\n"); 41 | }else{ 42 | printf("不是回文\n"); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /algorithm/经典字符串算法/4、全排列.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void allPermutation(char *str, int from, int to); 5 | void swap(char *a, char *b); 6 | 7 | void swap(char *a, char *b){ 8 | char tmp; 9 | 10 | tmp = *a; 11 | *a = *b; 12 | *b = tmp; 13 | } 14 | void allPermutation(char *str, int from, int to){ 15 | int i; 16 | int j; 17 | 18 | if(to <= 1){ 19 | return; 20 | } 21 | if(from == to){ 22 | for(i = 0; i <= to; i++){ 23 | printf("%c", str[i]); 24 | } 25 | printf("\n"); 26 | }else{ 27 | for(j = from; j <= to; j++){ 28 | swap(&str[j], &str[from]); 29 | allPermutation(str, from+1, to); 30 | swap(&str[j], &str[from]); 31 | } 32 | } 33 | } 34 | 35 | void main(void){ 36 | char str[80] = {0}; 37 | int length; 38 | 39 | printf("str : "); 40 | gets(str); 41 | length = strlen(str); 42 | allPermutation(str, 0, length-1); 43 | } 44 | -------------------------------------------------------------------------------- /algorithm/经典字符串算法/5、三步反转递归法.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // 时间复杂度为:O(n),空间复杂度为:O(1); 5 | // abcdefg----->cdefgab 6 | void revStr(char *str, int length); 7 | 8 | void revStr(char *str, int length){ 9 | char tmp; 10 | 11 | if(length > 1){ 12 | tmp = str[0]; 13 | str[0] = str[length-1]; 14 | str[length-1] = tmp; 15 | revStr(str+1, length-2); 16 | } 17 | } 18 | 19 | void main(void){ 20 | char str[80]; 21 | int number; 22 | int strLen; 23 | 24 | printf("请输入字符串: \n"); 25 | gets(str); 26 | strLen = strlen(str); 27 | printf("请输入要放到后面字符串的个数: "); 28 | scanf("%d", &number); 29 | revStr(str, number); 30 | revStr(str+number, strLen-number); 31 | revStr(str, strLen); 32 | printf("%s\n", str); 33 | } 34 | -------------------------------------------------------------------------------- /algorithm/经典字符串算法/6、三步反转非递归.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void revStr(char *str, int from, int to); 5 | 6 | void revStr(char *str, int from, int to){ 7 | int tmp; 8 | 9 | while(from < to){ 10 | tmp = str[from]; 11 | str[from++] = str[to]; 12 | str[to--] = tmp; 13 | } 14 | } 15 | 16 | void main(void){ 17 | char str[80]; 18 | int number; 19 | int strLen; 20 | 21 | printf("请输入字符串: \n"); 22 | gets(str); 23 | strLen = strlen(str); 24 | printf("请输入要放到后面字符串的个数: "); 25 | scanf("%d", &number); 26 | revStr(str, 0, number-1); 27 | revStr(str, number, strLen-1); 28 | revStr(str, 0, strLen-1); 29 | printf("%s\n", str); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /algorithm/经典字符串算法/7、整数转换为字符串.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void printfInt(int data); 4 | void printfDouble(double data, int count); 5 | 6 | void printfDouble(double data, int count){ 7 | int d = (int)data; 8 | double x = data - d; 9 | int i, tmp; 10 | int p = 1; 11 | 12 | printfInt(d); 13 | printf("."); 14 | for(i = 0; i < count; i++){ 15 | p *= 10; 16 | } 17 | tmp = (int)(p*x+0.5); // 在强转时,由于有截断误差,所以加上0.5,保证了小数点最后一位的取值是正确的。 18 | printfInt(tmp); 19 | } 20 | 21 | void printfInt(int data){ 22 | int q = 1; 23 | 24 | if(data > 1000000000){ 25 | q = 1000000000; 26 | }else if(data > 100000000){ 27 | q = 100000000; 28 | }else if(data > 10000000){ 29 | q = 10000000; 30 | }else if(data > 1000000){ 31 | q = 1000000; 32 | }else if(data > 100000){ 33 | q = 100000; 34 | }else if(data > 10000){ 35 | q = 10000; 36 | }else if(data > 1000){ 37 | q = 1000; 38 | }else if(data > 100){ 39 | q = 100; 40 | }else if(data > 10){ 41 | q = 10; 42 | } 43 | 44 | for(; q; q /= 10){ 45 | printf("%c", '0' + (data/q)%10); 46 | } 47 | } 48 | 49 | int main(void){ 50 | int number; 51 | double x_number; 52 | int bit; 53 | 54 | printf("请输入一个整数: "); 55 | scanf("%d", &number); 56 | // printf("请输入小数,和小数位数: "); 57 | // scanf("%lf%d", &x_number, &bit); 58 | 59 | printfInt(number); 60 | printf("\n"); 61 | // printfDouble(x_number, bit); 62 | // printf("\n"); 63 | } -------------------------------------------------------------------------------- /algorithm/经典字符串算法/8、字符串包含.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef unsigned char boolean; 4 | 5 | #define TRUE 1 6 | #define FALSE 0 7 | // 字符串单纯的包含,与位置没有关系 8 | boolean isContain(char *str1, char *str2); 9 | 10 | boolean isContain(char *str1, char *str2){ 11 | char tmp[128] = {0}; 12 | int i; 13 | int flag = 0; 14 | 15 | for(i = 0; str1[i]; i++){ 16 | tmp[str1[i]]++; 17 | } 18 | for(i = 0; str2[i]; i++){ 19 | if(tmp[str2[i]]){ 20 | ; 21 | }else{ 22 | flag = 1; 23 | break; 24 | } 25 | } 26 | 27 | return flag == 0; 28 | } 29 | 30 | void main(void){ 31 | char str1[80] = {0}; 32 | char str2[80] = {0}; 33 | boolean f; 34 | 35 | gets(str1); 36 | 37 | gets(str2); 38 | f = isContain(str1, str2); 39 | if(f){ 40 | printf("str1包含str2\n"); 41 | }else{ 42 | printf("str1不包含str2\n"); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /algorithm/经典字符串算法/9、字符串去空格.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void removeBlank(char *str); 5 | void removeBlank(char *str){ 6 | char *cur = str; 7 | char *pre = str; 8 | assert(str != NULL); 9 | 10 | while(*cur != 0){ 11 | if(*cur != ' '){ 12 | *pre++ = *cur; 13 | } 14 | cur++; 15 | } 16 | *pre = 0; 17 | } 18 | 19 | void main(void){ 20 | char str[] = " ABCD EFG HI JKL "; 21 | removeBlank(str); 22 | printf("%s\n", str); 23 | 24 | } -------------------------------------------------------------------------------- /algorithm/经典查找算法/1、binarySearch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define NOT_FOUND -1 4 | 5 | int binarySearch(int *a, int count, int key); 6 | 7 | int binarySearch(int *a, int count, int key){ 8 | int head = 0; 9 | int tail = count-1; 10 | int mid; 11 | 12 | while(head <= tail){ 13 | mid = (head + tail) / 2; 14 | if(a[mid] > key){ 15 | tail = mid-1; 16 | }else if(a[mid] < key){ 17 | head = mid + 1; 18 | }else{ 19 | return mid; 20 | } 21 | } 22 | 23 | return NOT_FOUND; 24 | } 25 | 26 | void main(void){ 27 | int a[] = {1, 3, 5, 7, 9, 11, 13, 15, 17,}; 28 | int count = sizeof(a)/sizeof(int); 29 | int key; 30 | int index; 31 | 32 | scanf("%d", &key); 33 | index = binarySearch(a, count, key); 34 | if(index == NOT_FOUND){ 35 | printf("要查找的数在数组中不存在\n"); 36 | }else{ 37 | printf("%d %d\n", index, a[index]); 38 | } 39 | } -------------------------------------------------------------------------------- /algorithm/经典查找算法/2、binarySearch_other.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define NOT_FOUND -1; 4 | 5 | int binSearch(int *a, int head, int tail, int key); 6 | 7 | int binSearch(int *a, int head, int tail, int key){ 8 | int middle; 9 | 10 | if(head <= tail){ 11 | middle = (head + tail)/2; 12 | 13 | if(key == a[middle]){ 14 | return middle; 15 | } 16 | if(key < a[middle]){ 17 | return binSearch(a, head, middle-1, key); 18 | } 19 | if(key > a[middle]){ 20 | return binSearch(a, middle+1, tail, key); 21 | } 22 | } 23 | 24 | return NOT_FOUND; 25 | } 26 | 27 | void main(void){ 28 | int a[] = {2, 3, 4, 6, 8, 10}; 29 | int count = sizeof(a)/sizeof(int); 30 | int index; 31 | int number; 32 | 33 | printf("请输入: "); 34 | scanf("%d", &number); 35 | index = binSearch(a, 0, count-1, number); 36 | printf("%d\n", index); 37 | 38 | } -------------------------------------------------------------------------------- /algorithm/经典查找算法/3、出现次数一半的数.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define NOT_FOUND -1 4 | 5 | int findMoreNum(int *a, int n); 6 | int findMoreNum(int *a, int n){ 7 | int result = a[0]; 8 | int times = 1; 9 | int count = 0; 10 | int i; 11 | 12 | for(i = 1; i < n; i++){ 13 | if(times == 0){ 14 | result = a[i]; 15 | times = 1; 16 | }else if(a[i] == result){ 17 | times++; 18 | }else{ 19 | times--; 20 | } 21 | } 22 | 23 | for(i = 0; i < n; i++){ 24 | if(result == a[i]) 25 | count++; 26 | } 27 | 28 | return count == n/2 ? result : NOT_FOUND; 29 | } 30 | 31 | void main(void){ 32 | int a[] = {3, 5, 2, 8, 5, 2, 1, 2, 2, 2,}; 33 | int count = sizeof(a)/sizeof(int); 34 | int num; 35 | 36 | num = findMoreNum(a, count); 37 | if(num == NOT_FOUND){ 38 | printf("这个数组中没有一半的数字\n"); 39 | }else{ 40 | printf("%d\n", num); 41 | } 42 | } -------------------------------------------------------------------------------- /algorithm/经典查找算法/4、出现次数超过一半以上的数.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define NOT_FOUND -1 4 | 5 | int findMoreNum(int *a, int n); 6 | int findMoreNum(int *a, int n){ 7 | int result = a[0]; 8 | int times = 1; 9 | int count = 0; 10 | int i; 11 | 12 | for(i = 1; i < n; i++){ 13 | if(times == 0){ 14 | result = a[i]; 15 | times = 1; 16 | }else if(a[i] == result){ 17 | times++; 18 | }else{ 19 | times--; 20 | } 21 | } 22 | 23 | for(i = 0; i < n; i++){ 24 | if(result == a[i]) 25 | count++; 26 | } 27 | 28 | return count > n/2 ? result : NOT_FOUND; 29 | } 30 | 31 | void main(void){ 32 | int a[] = {3, 5, 2, 8, 5, 2, 1, 2, 2, 2, 2,}; 33 | int count = sizeof(a)/sizeof(int); 34 | int num; 35 | 36 | num = findMoreNum(a, count); 37 | if(num == NOT_FOUND){ 38 | printf("这个数组中没有超过一半以上的数字\n"); 39 | }else{ 40 | printf("%d\n", num); 41 | } 42 | } -------------------------------------------------------------------------------- /algorithm/经典查找算法/5、杨氏矩阵查找.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef unsigned char boolean; 4 | 5 | #define TRUE 1 6 | #define FALSE 0 7 | 8 | boolean findNum(int (*a)[4], int rowCount, int colCount, int key); 9 | 10 | boolean findNum(int (*a)[4], int rowCount, int colCount, int key){ 11 | int i; 12 | int j; 13 | 14 | for(i = rowCount-1, j = 0; i >= 0 && j < colCount;){ 15 | if(key == a[i][j]){ 16 | return TRUE; 17 | } 18 | if(key < a[i][j]){ 19 | i--; 20 | continue; 21 | } 22 | if(key > a[i][j]){ 23 | j++; 24 | continue; 25 | } 26 | } 27 | 28 | return FALSE; 29 | } 30 | 31 | void main(void){ 32 | int a[4][4] = { 33 | 1, 2, 3, 4, 34 | 5, 6, 7, 8, 35 | 9, 10, 11, 12, 36 | 13, 14, 15, 16, 37 | }; 38 | boolean flag; 39 | 40 | flag = findNum(a, 4, 4, 5); 41 | if(flag){ 42 | printf("找到了\n"); 43 | }else{ 44 | printf("没找到\n"); 45 | } 46 | } -------------------------------------------------------------------------------- /algorithm/高频树算法/1、二叉树创建及方法实现.c: -------------------------------------------------------------------------------- 1 | #include"./binTree.h" 2 | 3 | // 前序创建二叉树 4 | 5 | void createbintree(BinTreeNode **root){ 6 | Element data; 7 | 8 | scanf("%c", &data); 9 | 10 | if(data == '#'){ 11 | *root = NULL; 12 | }else{ 13 | *root = (BinTreeNode *)malloc(sizeof(BinTreeNode)); 14 | (*root)->data = data; 15 | createbintree(&(*root)->left); 16 | createbintree(&(*root)->right); 17 | } 18 | } 19 | 20 | void showbintree(BinTreeNode *root){ 21 | if(root != NULL){ 22 | printf("%c", root->data); 23 | showbintree(root->left); 24 | showbintree(root->right); 25 | } 26 | 27 | } 28 | 29 | void createbintree_1(BinTreeNode **root, char **str){ 30 | if(**str == '#'){ 31 | *root = NULL; 32 | }else{ 33 | (*root) = (BinTreeNode *)malloc(sizeof(BinTreeNode)); 34 | (*root)->data = **str; 35 | char *tmp = ++*str; 36 | createbintree_1(&(*root)->left, &tmp); 37 | char *tmp1 = ++*str; 38 | createbintree_1(&(*root)->right, &tmp1); 39 | } 40 | } 41 | 42 | int size(BinTreeNode *root){ // 左子树+右子树+1 43 | if(root == NULL){ 44 | return 0; 45 | }else{ 46 | return size(root->left) + size(root->right) + 1; 47 | } 48 | } 49 | 50 | int heigh(BinTreeNode *root){ 51 | if(root == NULL){ 52 | return 0; 53 | }else{ 54 | int leftheigh = heigh(root->left); 55 | int rightheigh = heigh(root->right); 56 | return (leftheigh > rightheigh ? leftheigh : rightheigh) + 1; 57 | } 58 | } 59 | BinTreeNode *search(BinTreeNode *root, Element key){ 60 | if(root == NULL){ 61 | return NULL; 62 | } 63 | 64 | if(root->data == key){ 65 | return root; 66 | } 67 | 68 | BinTreeNode *p = search(root->left, key); 69 | if(p){ // p不为空,说明找到了 70 | return p; 71 | } 72 | return search(root->right, key); 73 | } 74 | 75 | BinTreeNode* Parent(BinTreeNode *root, BinTreeNode *p){ 76 | if(root == NULL || p == NULL){ 77 | return NULL; 78 | } 79 | if(root->left == p || root->right == p){ 80 | return root; 81 | } 82 | BinTreeNode *q = Parent(root->left, p); 83 | if(q){ 84 | return q; 85 | } 86 | 87 | return Parent(root->right, p); 88 | } 89 | 90 | BinTreeNode* left(BinTreeNode *root){ 91 | if(root){ 92 | return root->left; 93 | } 94 | 95 | return NULL; 96 | } 97 | 98 | BinTreeNode* right(BinTreeNode *root){ 99 | if(root){ 100 | return root->right; 101 | } 102 | 103 | return NULL; 104 | } 105 | boolean bintreeempty(BinTreeNode *root){ 106 | return root == NULL; 107 | } 108 | 109 | void copy(BinTreeNode *r1, BinTreeNode **r2){ 110 | if(r1 == NULL){ 111 | *r2 = NULL; 112 | }else{ 113 | (*r2) = (BinTreeNode *)malloc(sizeof(BinTreeNode)); 114 | (*r2)->data = r1->data; 115 | copy(r1->left, &(*r2)->left); 116 | copy(r1->right, &(*r2)->right); 117 | } 118 | } 119 | 120 | void clear(BinTreeNode **root){ 121 | if(*root != NULL){ 122 | clear(&(*root)->left); 123 | clear(&(*root)->right); 124 | free(*root); 125 | *root = NULL; 126 | } 127 | } 128 | 129 | int main(void){ 130 | BinTreeNode *root = NULL; 131 | char *str = "abc####"; 132 | 133 | createbintree(&root); 134 | //createbintree_1(&root, &str); 135 | showbintree(root); 136 | printf("\n"); 137 | 138 | printf("size = %d\n", size(root)); 139 | printf("heigh = %d\n", heigh(root)); 140 | BinTreeNode *p = search(root, 'C'); 141 | if(p == NULL){ 142 | printf("no found\n"); 143 | }else{ 144 | printf("found\n"); 145 | } 146 | BinTreeNode *parent = Parent(root, p); // 查找节点的地址 147 | if(parent == NULL){ 148 | printf("no found\n"); 149 | }else{ 150 | printf("found\n"); 151 | } 152 | BinTreeNode *r2 = NULL; 153 | copy(root, &r2); 154 | showbintree(r2); 155 | printf("\n"); 156 | 157 | clear(&root); 158 | return 0; 159 | 160 | } -------------------------------------------------------------------------------- /algorithm/高频树算法/2、二叉树非递归遍历.cpp: -------------------------------------------------------------------------------- 1 | #include"./binTree.h" 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | void createTree(BinTreeNode *&root){ 8 | Element data; 9 | 10 | cin>>data; 11 | 12 | if(data == '#'){ 13 | root = NULL; 14 | }else{ 15 | root = (BinTreeNode *)malloc(sizeof(BinTreeNode)); 16 | root->data = data; 17 | createTree(root->left); 18 | createTree(root->right); 19 | } 20 | } 21 | 22 | void levelTree(BinTreeNode *root){ 23 | queue qu; 24 | 25 | if(root){ 26 | qu.push(root); 27 | while(!qu.empty()){ 28 | BinTreeNode *p = qu.front(); 29 | qu.pop(); 30 | printf("%c", p->data); 31 | if(p->left){ 32 | qu.push(p->left); 33 | } 34 | if(p->right){ 35 | qu.push(p->right); 36 | } 37 | } 38 | cout< st; 45 | 46 | if(root){ 47 | st.push(root); 48 | while(!st.empty()){ 49 | BinTreeNode *p = st.top(); 50 | st.pop(); 51 | printf("%c", p->data); 52 | if(p->right){ 53 | st.push(p->right); 54 | } 55 | if(p->left){ 56 | st.push(p->left); 57 | } 58 | } 59 | 60 | printf("\n"); 61 | } 62 | } 63 | 64 | void midTree(BinTreeNode *root){ 65 | stack st; 66 | 67 | if(root){ 68 | st.push(root); 69 | while(!st.empty()){ 70 | while(root && root->left){ 71 | st.push(root->left); 72 | root = root->left; 73 | } 74 | 75 | BinTreeNode *p = st.top(); 76 | st.pop(); 77 | printf("%c", p->data); 78 | 79 | if(p->right){ 80 | root = p->right; 81 | st.push(root); 82 | } 83 | } 84 | } 85 | 86 | printf("\n"); 87 | } 88 | /* 89 | void lastTree(BinTreeNode *root){ 90 | if(root){ 91 | stack st; 92 | FlagNode sn; 93 | do{ 94 | while(root){ 95 | sn.ptr = root; 96 | sn.tag = L; 97 | st.push(sn); 98 | root = root->left; 99 | } 100 | 101 | bool flag = true; 102 | while(flag && !st.empty()){ 103 | sn = st.top(); 104 | st.pop(); 105 | switch(sn.tag){ 106 | case R: 107 | printf("%c", sn.ptr->data); 108 | break; 109 | case L: 110 | sn.tag = R; 111 | st.push(sn); 112 | flag = false; 113 | root = sn.ptr->right; 114 | break; 115 | } 116 | 117 | } 118 | 119 | }while(!st.empty()); 120 | 121 | printf("\n"); 122 | } 123 | } 124 | */ 125 | void lastTree(BinTreeNode *root){ 126 | FlagNode sn; 127 | stack st; 128 | 129 | if(root){ 130 | do{ 131 | while(root){ 132 | sn.ptr = root; 133 | sn.tag = L; 134 | st.push(sn); 135 | root = root->left; 136 | } 137 | 138 | bool flag = true; 139 | while(flag && !st.empty()){ 140 | sn = st.top(); 141 | st.pop(); 142 | switch(sn.tag){ 143 | case L: 144 | sn.tag = R; 145 | st.push(sn); 146 | flag = false; 147 | root = sn.ptr->right; 148 | break; 149 | case R: 150 | printf("%c", sn.ptr->data); 151 | break; 152 | } 153 | } 154 | 155 | }while(!st.empty()); 156 | printf("\n"); 157 | } 158 | } 159 | 160 | int main(void){ 161 | BinTreeNode *root = NULL; 162 | createTree(root); 163 | //levelTree(root); 164 | //preTree(root); 165 | midTree(root); 166 | //lastTree(root); 167 | 168 | return 0; 169 | } 170 | 171 | -------------------------------------------------------------------------------- /algorithm/高频树算法/3、前中后创建二叉树.c: -------------------------------------------------------------------------------- 1 | #include"./binTree.h" 2 | #include 3 | 4 | void preMidTree(BinTreeNode **root, const char *VLR, const char *LVR, int n){ 5 | if(n == 0){ 6 | root = NULL; 7 | return; 8 | }else{ 9 | int k = 0; 10 | 11 | while(VLR[0] != LVR[k]){ 12 | k++; 13 | } 14 | (*root) = (BinTreeNode *)malloc(sizeof(BinTreeNode)); 15 | (*root)->data = VLR[0]; 16 | 17 | preMidTree(&(*root)->left, VLR+1, LVR, k); 18 | preMidTree(&(*root)->right, VLR+k+1, LVR+k+1, n-k-1); 19 | } 20 | } 21 | void midLastTree(BinTreeNode **root, char *LVR, char *LRV, int n){ 22 | if(n == 0){ 23 | *root = NULL; 24 | return; 25 | }else{ 26 | int k = 0; 27 | while(LVR[k] != LRV[n-1]){ 28 | k++; 29 | } 30 | 31 | (*root) = (BinTreeNode *)malloc(sizeof(BinTreeNode)); 32 | (*root)->data = LRV[n-1]; 33 | midLastTree(&(*root)->right, LVR+k+1, LRV+k, n-k-1); 34 | midLastTree(&(*root)->left, LVR, LRV, k); 35 | 36 | } 37 | } 38 | 39 | void showTree(BinTreeNode *root){ 40 | if(root){ 41 | printf("%c", root->data); 42 | showTree(root->left); 43 | showTree(root->right); 44 | } 45 | } 46 | 47 | int main(void){ 48 | char *VLR = "ABCDEFGH"; 49 | char *LVR = "CBEDFAGH"; 50 | char *LRV = "CEFDBHGA"; 51 | BinTreeNode *root = NULL; 52 | 53 | //pareMidTree(&root, VLR, LVR, strlen(VLR)); 54 | midLastTree(&root, LVR, LRV, strlen(LVR)); 55 | showTree(root); 56 | printf("\n"); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /algorithm/高频树算法/binTree.h: -------------------------------------------------------------------------------- 1 | #ifndef _BIN_TREE_H_ 2 | #define _BIN_TREE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define Element char 9 | 10 | typedef struct BinTreeNode{ 11 | Element data; 12 | struct BinTreeNode *left; 13 | struct BinTreeNode *right; 14 | }BinTreeNode; 15 | 16 | typedef enum{L, R} Tag; 17 | typedef struct FlagNode{ 18 | BinTreeNode *ptr; 19 | Tag tag; 20 | }FlagNode; 21 | 22 | typedef FlagNode newElement; 23 | 24 | typedef unsigned char boolean; 25 | 26 | #define TRUE 1 27 | #define FALSE 0 28 | 29 | #endif -------------------------------------------------------------------------------- /algorithm/高频面试算法/10、哥德巴赫猜想验证.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef unsigned char boolean; 6 | 7 | #define TRUE 1 8 | #define FALSE 0 9 | 10 | // 位运算计算的效率更快 11 | #define SET_BIT(byte, i) (byte |= 1 << (7 ^ (i))) // 设置这个字节的指定位为1 12 | #define CLR_BIT(byte, i) (byte &= ~(1 << (7 ^ (i)))) // 设置这个字节的指定位为0 13 | #define GET_BIT(byte, i) !!((byte) & (1 << (7^(i)))) // 得到这个字节的指定位 14 | 15 | // num >> 3 数组下标 16 | // num & 7 <===> num % 8 17 | void findPrime(int number, char **p); 18 | boolean isPrime(int num, char *p); 19 | boolean Gguess(int userNumber, char *p); 20 | 21 | boolean Gguess(int userNumber, char *p){ 22 | int num; 23 | int i; 24 | int flag = TRUE; 25 | 26 | for(num = 6; TRUE == flag && num < userNumber; num += 2){ // 从6开始---userNumber的所有数字进行哥德巴赫猜想 27 | flag = FALSE; 28 | for(i = 3; i < num && FALSE == flag; i += 2){ 29 | if(isPrime(i, p) && isPrime(num-i, p)){ 30 | flag = TRUE; 31 | printf("%d = %d + %d\n", num, i, num-i); 32 | } 33 | } 34 | } 35 | 36 | return flag; 37 | } 38 | 39 | boolean isPrime(int num, char *p){ 40 | return GET_BIT(p[num >> 3], num & 7) == 0; // 0:表示为质数; 41 | } 42 | 43 | void findPrime(int number, char **p){ 44 | int len = (int)(sqrt(number)); 45 | int i; 46 | int j; 47 | char *pool; 48 | 49 | pool = (char *)calloc(sizeof(char), (number+7)>>3); 50 | for(i = 2; i < len; i++){ // 从2判断到根号number的长度即可 51 | if(GET_BIT(pool[i >> 3], i & 7) == 0){ 52 | for(j = i*i; j < number; j += i){ // 前面的都重复的判断过了 53 | SET_BIT(pool[j >> 3], j & 7); // 非质数标记为1 54 | } 55 | } 56 | } 57 | 58 | *p = pool; 59 | } 60 | 61 | void main(void){ 62 | int num; 63 | char *p; 64 | 65 | printf("请输入一个边界数: "); 66 | scanf("%d", &num); 67 | 68 | findPrime(num, &p); 69 | if(FALSE == Gguess(num, p)){ 70 | printf("哥德巴赫猜想失败\n"); 71 | }else{ 72 | printf("哥德巴赫猜想成功了\n"); 73 | } 74 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/11、汉诺塔问题.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void Hanoii(int n, char s, char a, char t); 4 | 5 | void Hanoii(int n, char s, char a, char t) 6 | { 7 | if(n > 0) 8 | { 9 | Hanoii(n-1, s, t, a); 10 | printf("%d : %c -> %c\n", n, s, t); 11 | Hanoii(n-1, a, s, t); 12 | } 13 | } 14 | 15 | void main(void) 16 | { 17 | Hanoii(4, 'A', 'B', 'C'); 18 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/12、将任意整数转换为二进制.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void digui(int n){ 4 | int c; 5 | c = n%2; 6 | 7 | if(n > 0){ 8 | digui(n/2); 9 | printf("%d", c); 10 | } 11 | } 12 | 13 | int main(void){ 14 | int n; 15 | 16 | scanf("%d", &n); 17 | digui(n); 18 | printf("\n"); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/13、将任意整数转换为十六进制.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void digui(int n); 4 | 5 | void digui(int n){ 6 | int c; 7 | c = n%16; 8 | 9 | if(n > 0){ 10 | digui(n/16); 11 | if(c >= 10){ 12 | printf("%c", c-10+'A'); 13 | }else{ 14 | printf("%d", c); 15 | } 16 | } 17 | } 18 | int main(void){ 19 | int n; 20 | 21 | scanf("%d", &n); 22 | digui(n); 23 | printf("\n"); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/14、括号匹配算法.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | typedef unsigned char boolean; 6 | #define TRUE 1 7 | #define FALSE 0 8 | 9 | boolean backetMatch(char *str); 10 | boolean backetMatch(char *str){ 11 | stack s; 12 | int i = 0; 13 | 14 | while(str[i]){ 15 | if(s.empty()){ 16 | s.push(str[i]); 17 | }else{ 18 | if(s.top() == ')' || s.top() == ']' || s.top() == '}'){ 19 | return FALSE; //首先出现右括号的,肯定是不匹配的; 20 | } 21 | 22 | if(s.top() == '('){ //为'('的情况 23 | if(str[i] == ')'){ 24 | s.pop(); 25 | }else{ 26 | s.push(str[i]); 27 | } 28 | }else if(s.top() == '['){ //为'['的情况 29 | if(str[i] == ']'){ 30 | s.pop(); 31 | }else{ 32 | s.push(str[i]); 33 | } 34 | }else if(s.top() == '{'){ //为'{'的情况 35 | if(str[i] == '}'){ 36 | s.pop(); 37 | }else{ 38 | s.push(str[i]); 39 | } 40 | } 41 | } 42 | i++; 43 | } 44 | 45 | if(s.empty()){ 46 | return TRUE; 47 | }else{ 48 | return FALSE; 49 | } 50 | } 51 | 52 | int main(void){ 53 | char *str = "({[])}"; 54 | boolean flag; 55 | 56 | flag = backetMatch(str); 57 | if(flag){ 58 | printf("括号匹配\n"); 59 | }else{ 60 | printf("括号不匹配\n"); 61 | } 62 | 63 | return 0; 64 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/15、判断大小端.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef unsigned char boolean; 4 | 5 | #define TRUE 1 6 | #define FALSE 0 7 | 8 | 9 | boolean checkSystem(); 10 | boolean checkSystem(){ 11 | union{ 12 | int a; 13 | char b; 14 | }t; 15 | 16 | t.a = 1; 17 | return t.b == 1; 18 | } 19 | 20 | void main(void){ 21 | boolean flag; 22 | flag = checkSystem(); 23 | if(flag){ 24 | printf("This is small\n"); 25 | }else{ 26 | printf("This is big\n"); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/16、求前n个数和.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int sum(int n){ 4 | if(n == 0){ 5 | return 0; 6 | } 7 | 8 | return n+sum(n-1); 9 | } 10 | 11 | int main(void){ 12 | int number; 13 | int n; 14 | 15 | scanf("%d", &number); 16 | n = sum(number); 17 | printf("%d\n", n); 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/17、求字符串的长度.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int strLen(char *str); 5 | int strLen(char *str){ 6 | if(*str == 0){ 7 | return; 8 | } 9 | 10 | return 1+strLen(str+1); 11 | } 12 | 13 | int main(void){ 14 | char str[80]; 15 | int len; 16 | 17 | gets(str); 18 | len = strLen(str); 19 | printf("%d\n", len); 20 | 21 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/18、约瑟夫环.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void yusf(char **str, int count, int doom, int start){ 5 | int *person; 6 | int i; 7 | int pre = start-2; 8 | int cur = start-1; 9 | int alive = count; 10 | int doomNumber = 0; 11 | 12 | if(start == 1){ 13 | pre = count-1; 14 | } 15 | 16 | person = (int *)malloc(sizeof(int) * count); 17 | for(i = 0; i < count; i++){ 18 | person[i] = (i+1)%count; //循环数组 19 | } 20 | 21 | for(; alive > 0; cur = person[cur]){ 22 | if(++doomNumber >= doom){ 23 | printf("%s->出圈\n", str[cur]); 24 | alive--; 25 | doomNumber = 0; 26 | person[pre] = person[cur]; //出圈时的pre的保存 27 | }else{ 28 | pre = cur; 29 | } 30 | } 31 | } 32 | 33 | int main(void){ 34 | char *str[] = {"李大", "马二", "张三", "李四", "王五", "刘六", "吊七", "朱八", "杨九"}; 35 | int count = sizeof(str)/sizeof(char *); 36 | int doom; //恶运数字 37 | int start; //从第几个人开始 38 | 39 | scanf("%d%d", &doom, &start); 40 | if(doom > count || doom <= 0 || start > count|| start <= 0){ 41 | return; 42 | } 43 | 44 | yusf(str, count, doom, start); //count个元素,doom个厄运数字,从第start开始; 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/19、转换数字.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //"a1b2c3ef4" <===> a=1,b=2,c=3,ef=4; 5 | void prinT(char *str); 6 | void prinT(char *str){ 7 | int i; 8 | 9 | for(i = 0; str[i];){ 10 | while(str[i] >= 'a' && str[i] <= 'z'){ 11 | printf("%c", str[i]); 12 | i++; 13 | } 14 | printf(" = %d ", str[i]-'0'); 15 | i++; 16 | } 17 | } 18 | 19 | void main(void){ 20 | char str[80] = {0}; 21 | 22 | printf("str : "); 23 | gets(str); 24 | prinT(str); 25 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/1、2个栈实现一个队列.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Test{ 6 | public: 7 | void push_(int data){ 8 | st1.push(data); 9 | } 10 | int pop_(){ 11 | int tmp; 12 | 13 | if(st2.empty()){ 14 | while(!st1.empty()){ 15 | int element = st1.top(); 16 | st1.pop(); 17 | st2.push(element); 18 | } 19 | } 20 | 21 | if(!st2.empty()){ 22 | tmp = st2.top(); 23 | st2.pop(); 24 | } 25 | 26 | return tmp; 27 | 28 | } 29 | 30 | private: 31 | stack st1; 32 | stack st2; 33 | }; 34 | 35 | int main(void){ 36 | Test t; 37 | int num; 38 | 39 | t.push_(6); 40 | t.push_(5); 41 | t.push_(4); 42 | t.push_(3); 43 | t.push_(2); 44 | t.push_(1); 45 | 46 | for(int i = 0; i < 6; i++){ 47 | num = t.pop_(); 48 | cout< 2 | #include 3 | 4 | void strrev_1(char *str, int length); 5 | void strrev_1(char *str, int length){ 6 | char tmp; 7 | 8 | if(length > 1){ 9 | tmp = *str; 10 | *str = *(str+length-1); 11 | *(str+length-1) = tmp; 12 | strrev_1(str+1, length-2); 13 | } 14 | 15 | } 16 | int main(void){ 17 | char str[] = "abcdefg"; 18 | int length = strlen(str); 19 | 20 | printf("转置前: %s\n", str); 21 | strrev_1(str, length); 22 | printf("转置后: %s\n", str); 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/21、字符串转置_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void revStr(char *str, char *tmp); 5 | void revStr(char *str, char *tmp){ 6 | if(str == NULL || tmp == NULL){ 7 | printf("有为空的,逆序不能进行\n"); 8 | return; 9 | } 10 | if(*str == 0){ 11 | return; 12 | } 13 | revStr(str+1, tmp); //用栈实现字符串的逆序,先进后出; 14 | 15 | strncat(tmp, str, 1); 16 | } 17 | 18 | int main(void){ 19 | char str1[80] = "abcdefghijkl"; 20 | char tmp[80]; 21 | 22 | printf("逆序前:%s\n", str1); 23 | revStr(str1, tmp); 24 | printf("逆序后:%s\n", tmp); 25 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/22、最大子数组和.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //最大子数字和:贪心算法,时间复杂度为:O(n) 4 | int maxSubArray(int *a, int n); 5 | int maxSubArray(int *a, int n){ 6 | int i; 7 | int ans = -10000000; 8 | int sum = 0; 9 | 10 | for(i = 0; i < n; i++){ 11 | sum += a[i]; 12 | if(sum > ans){ 13 | ans = sum; //保存先前的最大值 14 | } 15 | if(sum < 0){ 16 | sum = 0; //将一部分和<0的直接删去 17 | } 18 | } 19 | 20 | return ans; 21 | } 22 | 23 | void main(void){ 24 | int a[] = {-1, -2, 3, 6, -6, 3, 3, 2, -3}; 25 | int count = sizeof(a)/sizeof(int); 26 | int maxNumber; 27 | 28 | maxNumber = maxSubArray(a, count); 29 | printf("%d\n", maxNumber); 30 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/23、最长公共子序列.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define N 10 4 | 5 | int LCS(int *a, int count1, int *b, int count2); 6 | int LCS(int *a, int count1, int *b, int count2){ 7 | int table[N][N] = {0}; 8 | int i; 9 | int j; 10 | 11 | for(i = 0; i < count1; i++){ 12 | for(j = 0; j < count2; j++){ 13 | if(a[i] == b[j]){ 14 | table[i+1][j+1] = table[i][j]+1; 15 | }else{ 16 | table[i+1][j+1] = table[i+1][j] > table[i][j+1] ? table[i+1][j] : table[i][j+1]; 17 | } 18 | } 19 | } 20 | 21 | return table[count1][count2]; 22 | } 23 | 24 | void main(void){ 25 | int a[] = {1, 2, 3, 4, 5, 6}; 26 | int b[] = {2, 3, 5, 6, 7}; 27 | int count1 = sizeof(a)/sizeof(int); 28 | int count2 = sizeof(b)/sizeof(int); 29 | int number; 30 | 31 | number = LCS(a, count1, b, count2); 32 | printf("%d\n", number); 33 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/24、KMP.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define NOT_FOUND -1; 6 | 7 | void KMPnext(char *substr, int *next); 8 | int KMP(char *str, char *substr); 9 | int KMP(char *str, char *substr){ 10 | int *next; 11 | int i = 0; 12 | int j = 0; 13 | //abcdefabcdefgabcdefgabcd 14 | //bcdefg 15 | next = (int *)calloc(sizeof(int), strlen(substr)); 16 | KMPnext(substr, next); 17 | while(str[i]){ 18 | for(j = next[j]; substr[j] && str[i] == substr[j]; i++, j++){ 19 | ; 20 | } 21 | 22 | if(substr[j] == 0){ 23 | return i-j; 24 | } 25 | if(j == 0){ 26 | i++; 27 | } 28 | } 29 | free(next); 30 | 31 | return NOT_FOUND; 32 | 33 | } 34 | 35 | void KMPnext(char *substr, int *next){ 36 | int index; 37 | int j; 38 | 39 | for(index = 2; substr[index]; index++){ 40 | for(j = index-1; j && substr[next[j]] != substr[index-1]; j = next[j]){ 41 | ; 42 | } 43 | 44 | next[index] = j ? next[j]+1 : 0; 45 | } 46 | } 47 | 48 | void main(void){ 49 | char substr[80] = {0}; 50 | char str[80] = {0}; 51 | int index; 52 | 53 | printf("str : "); 54 | scanf("%s", str); 55 | printf("substr : "); 56 | scanf("%s", substr); 57 | index = KMP(str, substr); 58 | printf("%d\n", index); 59 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/25、随机化数组.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void showArray(int *a, int count); 6 | void random_1(int *a, int count); 7 | void random_1(int *a, int count){ 8 | int i; 9 | int tmp; 10 | int index; 11 | 12 | srand(time(NULL)); 13 | for(i = count; i > 0; i--){ 14 | index = rand()%i; 15 | tmp = a[index]; 16 | a[index] = a[i-1]; 17 | a[i-1] = tmp; 18 | } 19 | 20 | } 21 | void showArray(int *a, int count){ 22 | int i; 23 | 24 | for(i = 0; i < count; i++){ 25 | printf("%d ", a[i]); 26 | } 27 | printf("\n"); 28 | } 29 | 30 | int main(void){ 31 | int a[] = {4, 6, 8, 2, 0, 7, 1,}; 32 | int count = sizeof(a)/sizeof(int); 33 | 34 | showArray(a, count); 35 | random_1(a, count); 36 | showArray(a, count); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /algorithm/高频面试算法/2、10到M进制转换.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | // 将十进制转换为任意进制 7 | // 其他进制向十进制的转换--->进行每位的乘积求和即可 8 | // 在进制的转换当中十进制是中间的桥梁; 9 | int main(void){ 10 | vector v1; 11 | int number; 12 | int r; 13 | char tmp; 14 | 15 | printf("请输入要转换的数字: "); 16 | scanf("%d", &number); 17 | printf("请输入进制数: "); 18 | scanf("%d", &r); 19 | 20 | while(number){ 21 | tmp = "0123456789ABCDEF"[number%r]; 22 | v1.push_back(tmp); 23 | number /= r; 24 | } 25 | reverse(v1.begin(), v1.end()); 26 | vector::iterator it = v1.begin(); 27 | for(; it != v1.end(); it++){ 28 | cout<<*it; 29 | } 30 | cout< 2 | 3 | typedef unsigned char boolean; 4 | 5 | #define TRUE 1 6 | #define FALSE 0 7 | 8 | #define EIGHT 8 9 | 10 | void showChess(int (*chess)[EIGHT]); // 显示棋盘 11 | boolean isSafe(int (*chess)[EIGHT], int row, int col); // 判断这个位置是否安全 12 | void eightQueen(int (*chess)[EIGHT], int row); // 八皇后的递归程序 13 | 14 | void eightQueen(int (*chess)[EIGHT], int row){ 15 | int colIndex; 16 | 17 | if(row >= EIGHT){ 18 | showChess(chess); 19 | }else{ 20 | for(colIndex = 0; colIndex < EIGHT; colIndex++){ 21 | if(isSafe(chess, row, colIndex) == TRUE){ 22 | chess[row][colIndex] = 1; 23 | eightQueen(chess, row+1); 24 | chess[row][colIndex] = 0; 25 | } 26 | } 27 | } 28 | } 29 | 30 | boolean isSafe(int (*chess)[EIGHT], int row, int col){ 31 | int rowIndex; 32 | int colIndex; 33 | 34 | for(rowIndex = row-1; rowIndex >= 0; rowIndex--){ 35 | if(chess[rowIndex][col] == 1){ 36 | return FALSE; 37 | } 38 | } 39 | for(rowIndex = row-1, colIndex = col-1; rowIndex >= 0 && colIndex >= 0; rowIndex--, colIndex--){ 40 | if(chess[rowIndex][colIndex] == 1){ 41 | return FALSE; 42 | } 43 | } 44 | for(rowIndex = row-1, colIndex = col+1; rowIndex >= 0 && colIndex < EIGHT; rowIndex--, colIndex++){ 45 | if(chess[rowIndex][colIndex] == 1){ 46 | return FALSE; 47 | } 48 | } 49 | 50 | return TRUE; 51 | } 52 | 53 | void showChess(int (*chess)[EIGHT]){ 54 | int i; 55 | int j; 56 | int static count; 57 | 58 | printf("解:%d\n", ++count); 59 | for(i = 0; i < EIGHT; i++){ 60 | for(j = 0; j < EIGHT; j++){ 61 | printf("%4d ", chess[i][j]); 62 | } 63 | printf("\n"); 64 | } 65 | } 66 | 67 | void main(void){ 68 | int chess[EIGHT][EIGHT] = {0}; 69 | 70 | eightQueen(chess, 0); 71 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/4、饿汉式.c: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // 饿汉式,线程安全 5 | class Singelton{ 6 | private: 7 | Singelton(){ 8 | cout<<"Singelton 构造函数执行"< 2 | using namespace std; 3 | 4 | // 存在线程安全的问题;` 5 | class Singelton{ 6 | private: 7 | Singelton(){ 8 | cout<<"Singelton 构造函数执行"< 2 | 3 | int binOf1(int n); 4 | int binOf1(int n){ 5 | int count = 0; 6 | 7 | while(n){ 8 | count++; 9 | 10 | n = n & (n-1); 11 | } 12 | 13 | return count; 14 | } 15 | 16 | int main(void){ 17 | int num; 18 | int count = 0; 19 | 20 | scanf("%d", &num); 21 | 22 | count = binOf1(num); 23 | printf("%d\n", count); 24 | return 0; 25 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/7、斐波那契数列.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fibonacci(int n); 4 | 5 | int fibonacci(int n){ 6 | if(n <= 0){ 7 | return 0; 8 | } 9 | if(n == 1){ 10 | return 1; 11 | } 12 | 13 | return fibonacci(n-1)+fibonacci(n-2); 14 | } 15 | 16 | void main(void){ 17 | int number; 18 | int value; 19 | 20 | printf("请输入第几个斐波那契数:"); 21 | scanf("%d", &number); 22 | 23 | value = fibonacci(number); 24 | printf("%d\n", value); 25 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/8、斐波那契数列_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fibonacci(int n); 4 | 5 | int fibonacci(int n){ 6 | int firstNumber = 0; 7 | int secondNumber = 1; 8 | int finNumber; 9 | int i = 2; 10 | 11 | if(n == 1){ 12 | return firstNumber; 13 | } 14 | if(n == 2){ 15 | return secondNumber; 16 | } 17 | 18 | for(i = 3; i <= n; i++){ 19 | finNumber = firstNumber + secondNumber; 20 | firstNumber = secondNumber; 21 | secondNumber = finNumber; 22 | } 23 | 24 | return finNumber; 25 | } 26 | 27 | void main(void){ 28 | int number; 29 | int value; 30 | 31 | printf("请输入第几个斐波那契数:"); 32 | scanf("%d", &number); 33 | 34 | value = fibonacci(number); 35 | printf("%d\n", value); 36 | } -------------------------------------------------------------------------------- /algorithm/高频面试算法/9、高效查找自幂数.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int table[][10] = { // table[3][6]代表:6的3次方,做一张表直接查询,效率比较高; 4 | // 0 1 2 3 4 5 6 7 8 9 5 | /*0次方*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6 | /*1次方*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7 | /*2次方*/ 0, 1, 2*2, 3*3, 4*4, 5*5, 6*6, 7*7, 8*8, 9*9, 8 | /*3次方*/ 0, 1, 2*2*2, 3*3*3, 4*4*4, 5*5*5, 6*6*6, 7*7*7, 8*8*8, 9*9*9, 9 | /*4次方*/ 0, 1, 2*2*2*2, 3*3*3*3, 4*4*4*4, 5*5*5*5, 6*6*6*6, 7*7*7*7, 8*8*8*8, 9*9*9*9, 10 | /*5次方*/ 0, 1, 2*2*2*2*2, 3*3*3*3*3, 4*4*4*4*4, 5*5*5*5*5, 6*6*6*6*6, 7*7*7*7*7, 8*8*8*8*8, 9*9*9*9*9, 11 | /*6次方*/ 0, 1, 2*2*2*2*2*2, 3*3*3*3*3*3, 4*4*4*4*4*4, 5*5*5*5*5*5, 6*6*6*6*6*6, 7*7*7*7*7*7, 8*8*8*8*8*8, 9*9*9*9*9*9, 12 | /*7次方*/ 0, 1, 2*2*2*2*2*2*2, 3*3*3*3*3*3*3, 4*4*4*4*4*4*4, 5*5*5*5*5*5*5, 6*6*6*6*6*6*6, 7*7*7*7*7*7*7, 8*8*8*8*8*8*8, 9*9*9*9*9*9*9, 13 | /*8次方*/ 0, 1, 2*2*2*2*2*2*2*2, 3*3*3*3*3*3*3*3, 4*4*4*4*4*4*4*4, 5*5*5*5*5*5*5*5, 6*6*6*6*6*6*6*6, 7*7*7*7*7*7*7*7, 8*8*8*8*8*8*8*8, 9*9*9*9*9*9*9*9, 14 | /*9次方*/ 0, 1, 2*2*2*2*2*2*2*2*2, 3*3*3*3*3*3*3*3*3, 4*4*4*4*4*4*4*4*4, 5*5*5*5*5*5*5*5*5, 6*6*6*6*6*6*6*6*6, 7*7*7*7*7*7*7*7*7, 8*8*8*8*8*8*8*8*8, 9*9*9*9*9*9*9*9*9, 15 | }; 16 | 17 | void selfNumber(int num); 18 | int selfLen(int num); 19 | 20 | int selfLen(int num){ 21 | if(num > 0 && num < 10){ 22 | return 1; 23 | }else if(num > 10 && num < 100){ 24 | return 2; 25 | }else if(num >100 && num < 1000){ 26 | return 3; 27 | }else if(num > 1000 && num < 10000){ 28 | return 4; 29 | }else if(num > 10000 && num < 100000){ 30 | return 5; 31 | }else if(num > 100000 && num < 1000000){ 32 | return 6; 33 | }else if(num > 1000000 && num < 10000000){ 34 | return 7; 35 | }else if(num > 10000000 && num < 100000000){ 36 | return 8; 37 | }else if(num > 100000000 && num < 1000000000){ 38 | return 9; 39 | } 40 | 41 | return -1; 42 | } 43 | 44 | void selfNumber(int num){ 45 | int n; 46 | int len = selfLen(num); 47 | int sum =0; 48 | 49 | for(n = num; n; n/=10){ 50 | sum += table[len][n%10]; // 此处就是求每一位的n次幂的和,利用的就是在表中直接查询的方法; 51 | } 52 | 53 | if(sum == num){ 54 | printf("%d是自幂数\n", num); 55 | } 56 | } 57 | 58 | void main(void){ 59 | int i; 60 | int count; 61 | 62 | printf("请输出多少位以内的自幂数:"); 63 | scanf("%d", &count); 64 | for(i = 0; i < count; i++){ 65 | selfNumber(i); 66 | } 67 | } -------------------------------------------------------------------------------- /cs-basics/学习路线指南/Java学习路线_2019版.md: -------------------------------------------------------------------------------- 1 | - [一、Java 方向的思考](#一java-方向的思考) 2 | - [二、Java 学习路线](#二java-学习路线) 3 | - [1、Java 基础](#1java-基础) 4 | - [2、Java 进阶](#2java-进阶) 5 | - [3、JavaWeb](#3javaweb) 6 | - [4、Java 后台三大框架](#4java-后台三大框架) 7 | - [5、Java 中一些核心技术点(GC、JVM、redis 等)](#5java-中一些核心技术点gcjvmredis-等) 8 | - [6、大数据](#6大数据) 9 | - [三、总结](#三总结) 10 | - [四、说明](#四说明) 11 | 12 | 上次文章写了 Linux C/C++ 的学习路线,包括从基础、到 C++ 入门、进阶、提升的视频、书籍推荐,这些都是我大学期间真实走过的路,还没看过的,先看下上篇文章:[Linux C/C++ 学习路线(已拿腾讯、百度 offer)](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484210&idx=1&sn=7e4d20ad4fe125cce4c234330ad21125&chksm=fdb6f719cac17e0fce1be3acf1043cc6cbde353c75d37eeb0d78caa9d1cf6edd8ddb07c8bb9c&scene=21#wechat_redirect) 13 | 14 | 公众号、以及朋友圈下面留言,有不少读者希望我写一篇 Java 的学习路线,以及我对于 Java 方向的看法。 15 | 16 | 我仔细想了一下,虽然我只接触过 Java 基础,但是丝毫不影响我对于 Java 学习路线的思考,毕竟网上那么多资源(知乎、牛客、简书,学会自己搜索、自己规划路线)。 17 | 18 | 对于 Java 方向,我只会把我知道的,我看过的推荐出来,希望对于 Java 方向迷茫的同学有所帮助。 19 | 20 | ## 一、Java 方向的思考 21 | 22 | 目前最常见的三大后台开发语言,分别是 C++、Java、Go,C++ 现在学习的人比较少,偏底层而且入门较难;Go 才兴起,百度、滴滴、头条有部分架构转型 Go;而其中 Java 方向,是现阶段招聘需求最多,学的人也特别多,其应用场景特别的广,如果作为后台的学习方向,是没有问题的。 23 | 24 | 对于 Java 系的公司,阿里、京东、美团都是纯 Java 技术栈,百度、滴滴、头条、网易也有 Java 岗;我认识的很多同学,本科、研究生都有,其中选择走 Java 后台方向的,很多都去了大厂,从普遍情况看:**只能说在这个方向上,概率还是大一点**;对于其他方向,前端、测试、运维、安卓等,有兴趣也可以走。 25 | 26 | 对于要走 Java 方向的读者,基础是同等重要的(上篇文章写过基础了),选择 Java 方向,只是在方向上的深入;基础这块,我还想在强调一下,C 语言是基础,不是方向,有时间的话,把 C 语言加强加强,对于编程理念、底层的知识,能多了解一下,是有帮助的。 27 | 28 | **很多人由 Java 后台入门,在转型大数据、架构师方向,这个的根据自己的情况定就好了,对于自己感兴趣的公司,可以到招聘官网上,看看详细要求的技术栈有哪些,按照着准备、学习就好了。** 29 | 30 | ## 二、Java 学习路线 31 | 32 |
33 |

(黑马 java 后台路线 )

34 | 35 | **国内 Java 视频,黑马算是比较经典的了,按照路线图学习就好。** 36 | 37 | ### 1、Java 基础 38 | 39 | **Java 基础**:基本的数据类型、流程控制语句(if、for、while 等)、面向对象的理解(对象、封装、继承、多态)、一些关键字的理解(super、this 等)、接口、抽象类、ArrayList、String、Random、Math 等等;先把 Java 语言入门,Java 相关的基础打牢,熟练使用 Java,可以先完成一些小的 demo 作为实战。 40 | 41 | **对于初学 Java 的读者,可以先配置 java、javac 环境(熟悉熟悉 cmd 命令),建议先拿 .txt 文件写代码,一个一个字母敲,培养一下编程的感觉;刚开始接触编程,关键是找到一定的感觉和兴趣,在 Java 基础阶段,把每一个细节都要弄明白,对于 .txt 敲 Java 代码,可以保持三个月左右的时间,充分的让自己熟悉起来。** 42 | 43 | ### 2、Java 进阶 44 | 45 | **Java 进阶**:Date、StringBuilder、List、Set、Map、HashMap、异常、自定义异常、泛型、线程、线程同步、线程池、函数式思想、文件、字节流、网络编程相关等等;在这个阶段,不仅仅是会调用 Java 的一些 API,还需要把 List、Set、Map、HashMap 等底层源码看看,自己能掌握理解,核心代码能手写。 46 | 47 | **对于学习 Java,在校期间大部分都是用:eclipse 或 myeclipse,我当时初学 Java 用的就是 eclipse 写的代码,工欲善其事必先利其器,先把 eclipse 或 myeclipse 的使用技巧好好学学;对于工作了的,基本上都用 IntelliJ IDEA 写的 Java 项目,IDEA 是 Java 编程语言开发的集成环境,被公认是最好的 Java 开发工具之一,我也装的这个软件。** 48 | 49 | ### 3、JavaWeb 50 | 51 | **JavaWeb**:mysql、tomcat、nginx 的安装、配置、部署、jsoup 使用、xml 基础、html + css + js(前端基础、前端框架 jQuery 有时间可以学学)、maven 的常用命令,依赖管理等等;在这个阶段,就需要做一些简单的项目,项目中需要的技术点就是上面列出来的;前 3 个阶段,一步一步走,基本上走到这里,就可以做一些有意思的项目了,比如:扫雷、坦克大战、各种管理系统都是可以一个人完成的。 52 | 53 | 其实,对于学习 Java 后台开发的,多少的懂点前端知识,毕竟的做前后端的交互、接口协议的制定,会前端的,整个项目可以自己独立完成,对项目的认知会非常的深;学前端的,现在多少的懂点后台知识,才有更大的机会进入大厂,现在都是在往全栈方向发展。 54 | 55 | ### 4、Java 后台三大框架 56 | 57 | **Java 后台三大框架**:快速掌握之后,可以搭建出一个 MVC 模型出来,开发大型应用可以节省时间,spring,这个框架我是觉得最重要的,工作工程中使用较多(springmvc、spring-boot 这些)。 58 | 59 | 对于后台三大框架,不能只停留在调用 API 的阶段,对于底层源码的实现机制、系统调用模块之间的关系得梳理清楚(看时间安排,至少的熟悉一个框架的源码)。 60 | 61 | ### 5、Java 中一些核心技术点(GC、JVM、redis 等) 62 | 63 | **Java 中一些核心技术点(GC、JVM、redis 等)**:GC(垃圾收集器),对于执行机制、内存泄漏问题、回收原理等掌握;JVM 是虚拟机,实现了跨平台运行,是 Java 的核心,是 Java 一次编译到处运行的本质所在,对其组成、运行原理、内存管理、垃圾回收等各种算法都得掌握。 64 | 65 | redis 是开源,使用 C 语言编写的 k-v 数据库。 66 | 67 | 1. 对 redis 的持久化怎么理解?为什么读写速率快、性能好? 68 | 2. 什么场景下使用 redis?以及 redis 的优点有哪些? 69 | 3. redis 单线程、多线程相关 70 | 4. redis 集群 71 | 72 | ### 6、大数据 73 | 74 | **大数据**:Java 后台开发的能力具有了,大数据基础的掌握是亮点、是加分项。 75 | 76 | 毕竟我不是学 Java 出身的,对于 Java 的理解如上,大致的学习路线梳理,核心知识点都有写到,当然了,肯定缺失很多,需要你自己在学习的时候,查漏补缺,把相关的知识点都学到位。 77 | 78 | Java 相关的技术书籍。我看的很少,所以就不推荐书籍了,我有一个原则:我推荐的前提是,自己真的看过、对我很有帮助,就推荐给大家,自己没有看过的,只是听别人说的,就不推荐了。 79 | 80 | **对于 Java 经典的书籍,太多太多了,去 Google、牛客网、知乎上面搜一下,一大堆推荐的书籍;对于 Java 相关 API 的官方文档是个好东西,还有阿里巴巴 Java 的开发准则,对于变量的命名、开发的规范都有限制,这些最好都看看。** 81 | 82 | 视频推荐:黑马 Java 全套,包含上面 6 个阶段的所有视频。 83 | 84 | 链接: 85 | 86 | https://pan.baidu.com/s/1pg4lIeb4uaCzIaauQD3R6w 87 | 88 | 密码:s820 89 | 90 | ## 三、总结 91 | 92 |
93 |

(搜 java 面经)

94 | 95 | 牛客网搜 “java面经” 学习路线都有的,包括 Java 面经、书籍推荐、学习路线这些,要啥有啥,要学会自己搜索,主要是很多人不会用牛客网,这次教一下大家,需要什么搜什么,拿 java 面经举个例子。 96 | 97 | 不管你是选择什么方向,Linux C/C++、Java、Python、Go、算法、前端、测试、运维等,基础都是核心,没有哪个方向绝对工资高、没有哪个方向绝对好,关键不在于方向,在于你自己的技术能力。 98 | 99 | **说到底,不管走啥方向,都按照三步走战略、五大能力的提升走,这是我在大学时代实践过的,帮助很大,是最正确的打法(尤其对于学校不好的、非科班的学生),一定要有自己的打法。** 100 | 101 | **学习编程,一开始在于多接触不同的方向、领域,多去尝试;当你找准方向之后,再围绕一个点,先深扎下去,在某个技术点上,形成自己的技术优势,这就是最大的亮点,举个例子:我面试就敢说自己熟练掌握 C 语言中指针的方方面面,熟练掌握各种数据结构、常用算法等,这些其实就是我的技术优势。** 102 | 103 | **优势是什么,就是你跟别人最大不同的地方,就是为啥这么多面试者,要给你发 offer 的原因;数据结构很多人学的都是一知半解,C 语言中的指针都是不清不楚,而我真正的掌握了,我就敢说出来,一定是十分有把握的优势在说出来,不然问住了很尴尬,有时候得具有一点冒险精神,这些都是看情况而定的。** 104 | 105 | **现阶段,岗位需求最多的,最火的方向就是:Java 后台开发、算法岗(机器学习、cv、nlp。。。)。** 106 | 107 | **脚踏实地,一步一步走!** 108 | 109 | ## 四、说明 110 | 111 | 原创文章链接:[Java 学习路线(2019版)](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484226&idx=1&sn=f2767de92cba3e87e20ecdec4ccdb149&chksm=fdb6f769cac17e7f7cefeb89b3980e58a32be810b4197cfdc4d7b005a65176c2e10b6eabdca2&token=1026755469&lang=zh_CN#rd) 112 | -------------------------------------------------------------------------------- /cs-basics/学习路线指南/LinuxC_C++学习路线_2019版.md: -------------------------------------------------------------------------------- 1 | - [一、前言](#一前言) 2 | - [二、秋招 Linux C/C++ offer 情况](#二秋招-linux-cc-offer-情况) 3 | - [三、Linux C/C++ 方向的一些思考](#三linux-cc-方向的一些思考) 4 | - [1、](#1) 5 | - [2、](#2) 6 | - [3、](#3) 7 | - [四、计算机基础知识的梳理](#四计算机基础知识的梳理) 8 | - [1、数据结构](#1数据结构) 9 | - [2、算法](#2算法) 10 | - [3、操作系统](#3操作系统) 11 | - [4、计算机网络](#4计算机网络) 12 | - [5、数据库](#5数据库) 13 | - [6、Linux](#6linux) 14 | - [7、C 语言](#7c-语言) 15 | - [五、C++ 方向的深入学习路线](#五c-方向的深入学习路线) 16 | - [1、C++ 基础](#1c-基础) 17 | - [2、C++ 进阶](#2c-进阶) 18 | - [3、STL 源码](#3stl-源码) 19 | - [4、Linux 网络编程](#4linux-网络编程) 20 | - [5、内核源码剖析](#5内核源码剖析) 21 | - [6、开源网络库](#6开源网络库) 22 | - [六、项目 + 亮点 + 面试的一些思考](#六项目--亮点--面试的一些思考) 23 | - [1、项目](#1项目) 24 | - [2、亮点](#2亮点) 25 | - [3、面试](#3面试) 26 | - [七、总结](#七总结) 27 | - [八、说明](#八说明) 28 | 29 | ## 一、前言 30 | 31 | Linux C/C++ 从零基础到大神的学习路线,自己的真实学习路线,干货很多,建议收藏,认真阅读。 32 | 33 | 在校期间,我一直走的都是 Linux C/C++ 学习路线,历经暑期实习、秋招决战、校招期间投的大部分岗位都是 Linux C/C++ 后台方向,对于这个方向,有着自己的理解。 34 | 35 | 从接触 C++ 到我现在正式工作,大概有 2 年多的时间,对于这个方向的学习路线、以及学习编程的方法摸索出来了一些,看完本文,希望对于正在走 Linux C/C++ 路上的同学能有所帮助。 36 | 37 | ## 二、秋招 Linux C/C++ offer 情况 38 | 39 | 本人就读于双非院校、非科班本科学生,专业是偏硬件的(学校课程只有一门 C 语言与编程相关,其余的课程跟编程一点点的关系都没有),在校期间也没拿过什么大的奖项。 40 | 41 | 计算机基础为零,大二上学期接触 C 语言,大二一年学了 C 语言和数据结构,大三在学校的实验室开始学习计算机基础和学习 C++ 方向,一路自学编程,始终相信自己,也是拿到了大厂 offer。 42 | 43 | **秋招 offer 情况:** 44 | 45 | - 腾讯 后台开发工程师(实习转正) 46 | - 百度 手百 feeds 流,软件研发工程师 47 | - 美团 后台开发 (C++ 方向面试) 48 | - 作业帮 后台开发工程师 49 | - 好未来 后台开发工程师 50 | - 迅雷 后台开发工程师 51 | - 盛大游戏 C++ 开发工程师 52 | - 。。。 53 | 54 | 2017 年暑期实习腾讯,2018 年初实习百度,校招拿了十几个 Linux C/C++ 方向的 offer,最终的选择也很玄学,去了自己想去的公司,从事自己喜欢的岗位,现在在编程的路上越走越远。 55 | 56 | ## 三、Linux C/C++ 方向的一些思考 57 | 58 | ### 1、 59 | 60 | 对于方向的抉择,很多人都选择了 Java 或者 Python 方向,Java 或者 Python 方向确实学的人多,岗位需求很多,入门能比 Linux C/C++ 方向容易一些,但是往深了学,各有各的难度,先敲定了方向,再深入学习。 61 | 62 | Linux C/C++ 方向,国内真正掌握的人,其实是极少数,这个方向的学习人数也是相对比较少的,入门一般首选 C 语言或者 Python,C、C++ 在编程排行榜也是经久不衰的,排名靠前,如果喜欢,有兴趣,走这个方向是可以的。 63 | 64 | **Linux C/C++ 方向,国内很多大公司都有招聘这个方向的岗位,BAT 都有,尤其腾讯,底层架构都是 C++ 写的,百度核心搜索很多模块也是 C++ 写的,阿里云也在招聘 C++ 方向的工程师,这个方向,学的不错的,根本不用担心找工作的问题,学的一般的,其实就比较难找了。** 65 | 66 | Linux C/C++ 的效率是比 Java、Python 快一些的,更偏向于底层,能直接操作内存,对于编程思维、逻辑能力的提升是有帮助的;其实学习这个方向,是有一点枯燥的,不像 Python 爬虫、Java、前端能做出一些有趣的东西,小程序开发出一些产品,都能很快用于实战,获得编程的乐趣,进一步刺激自己学习。 67 | 68 | C++ 方向没有那么多有趣的东西可以做,在很长的一段时间内,要靠自己的兴趣去坚持学习。 69 | 70 | ### 2、 71 | 72 | 我在大三的时候,用 C++ 写过五子棋、内存监控工具、压缩工具、以及实现一些比较复杂的数据结构,实现网络编程的并发模型;当你学习 Linux C/C++ 方向到一定程度的时候,你会找到这个方向的乐趣,跟其他方向完全不一样的乐趣,**不过,前期真的很难,有一段时间极其痛苦,是要经过很长一段时间的学习,才能有一定的效果,如果对这个方向,真的没有啥兴趣,最好选择走前端、Java、Python 等是最好的选择。** 73 | 74 | Linux C/C++ 方向,入门稍微难一点,一旦选择了要走 C++ 方向的,在心态上面,要做好准备,一定不能有畏难心里,做好接触底层、复杂逻辑的分析、以及具备面向过程 + 面向对象的思想;就是退一步讲,我学习了 Linux C/C++ 方向,具备了编程思维和熟悉了 C++ 语言,以后去公司上班了,也能很快的上手 Java、Python 等方向(我说的上手指的是语言基础很快的学习,要想深入,还得花大把的时间)。 75 | 76 | 按照目前身边人找工作的情况,普遍来说,Java、Python、前端、数据分析、测试方向都要比 C++ 好找一些,更容易找到工作,虽然我是走的 Linux C/C++ 方向,但是对于对底层没有兴趣,对 C 语言没有兴趣的人,不建议走这个方向。 77 | 78 | ### 3、 79 | 80 | **我一路走过来,真的很痛苦,在校期间都想过放弃这个方向,曾经想学个 Java 可能会好一些(身边学习 Java 的人还是挺多的),每当快放弃的时候,又想到都学了这么长时间了,再坚持坚持,就这样一路走过来了;我是觉得自己真的挺幸运的,有时候,真的不一定非要头铁 C++ 方向,要看整个市场行情,顺势而为,选择好方向,在深入!** 81 | 82 | **对于 Java 还是 C++ 方向的选择,没有哪个方向一定好找工作,没有哪个方向一定工资待遇高,互联网这行,尤其是靠技术说话的,这些都取决于你自身的技术能力。** 83 | 84 | **选择走 C++ 方向的,一定要走 Linux C/C++,面向网络编程,学会 Linux 至关重要!** 85 | 86 | **大厂特别喜欢考察计算机基础知识,对于基础掌握的如何,在很大程度上将决定你是否能进入大厂,一定要重视基础知识的学习;秋招准备:基础 + 算法 + 项目,加上自己的方向(C++、Java、Python、前端等),其中每个环节都得准备到位,才能最大程度上拿到大厂 offer,意识很重要,有了意识,再看具体的学习路线。** 87 | 88 | ## 四、计算机基础知识的梳理 89 | 90 | **计算机基础:数据结构 + 算法、操作系统 + 计算机网络、数据库 + Linux、C 语言。** 91 | 92 | **工作必备工具:Linux + Git + Sql。** 93 | 94 | 不管你是学习什么方向的,Java、Python、前端、测试、运维等等,这些基础都不能忽视,有时间的话,一定要打扎实了,有了扎实的功底,在这行才能走的更远更快! 95 | 96 | ### 1、数据结构 97 | 98 | **数据结构**:对于常用的数据结构,链表、栈、队列、矩阵、树(BinTree、BST、AVL、RBtree、B+、B-)、跳表、图等,学习从定义--->原理--->实现--->应用,都要有不同程度的掌握。 99 | 100 | 靠前的数据结构一定要非常的熟练,对于树、图复杂的数据结构,最起码的掌握定义、原理、部分实现,我就记得:我在面试的时候,手写过红黑树的旋转算法,对于图的一些最短路径算法也是当面手写过,头条的面试基本上就是全程算法,难度不低(我个人博客上面有所有的数据结构的整理)。 101 | 102 | 书籍: 103 | 104 | - <大话数据结构>,适合入门学习; 105 | - <数据结构>,清华大学严蔚敏写的,作为进阶和深入。 106 | 107 | 视频: 108 | 109 | https://pan.baidu.com/s/1qQrHTdkvxMLSGv7G4nHWBw 密码:4o9p 110 | 111 | ### 2、算法 112 | 113 | **算法**:一定要保证掌握基础算法 + 常见算法,十大排序算法(冒泡、插入、选择、快排、希尔、堆排、归并、桶排、基数、计数)是最简单的,也是一定一定要熟练掌握的,另外还有字符串常见算法、数组常见算法、递归算法等等。 114 | 115 | 对于算法,从易到难,先把我列的一些算法掌握了,在去刷一些题,会有一些成就感,才能有自信,也要早早开始,一直刷一些算法题,保持住手感,对于五大算法,是要刷一定题量的,要及时的做好归纳整理、总结反思。 116 | 117 | 视频面试就是编译器上面直接敲代码,现场面试,大部分情况下都是手写代码,写一些核心的算法逻辑,要特别注意判断边界情况,与面试官边讨论边写,《剑指 offer》至少刷 2-3 遍,在刷刷 leetcode 上面 easy、medium 类型的题目就好了(我 github 上面有自己整理的常见算法题目)。 118 | 119 | **在算法方面的要求上,C++ 方向对于算法的要求明显更高,算法功底一定要扎实!** 120 | 121 | 书籍: 122 | 123 | - <啊哈算法>,适合入门学习; 124 | - <编程之美>、<算法导论>,进阶提升必看; 125 | - <剑指 offer>、leetcode 找实习/工作前,刷题就好。 126 | 127 | **对于算法导论,虽然比较难,数学公式很多,但是有视频的,有些学到了,真的不亏,可以学一部分的;** 128 | 129 | 视频:左神的算法视频推荐看看,讲的很清楚。 130 | 131 | 算法导论的视频: 132 | 133 | https://pan.baidu.com/s/1Bm34-92TwN5TbMOXfPkY6g 134 | 135 | 密码:1i38 136 | 137 | ### 3、操作系统 138 | 139 | **操作系统**:很常问的一些技术点,堆和栈、内存分区、虚拟内存 + 物理内存、进程 + 线程 + 协程、死锁、分片机制、五大组件、中断和系统调用 、同步和异步等等问题。 140 | 141 | 对于操作系统的理解,对于这些基础的计算机知识的掌握是必须深入学习,要花很大的功夫去理解清楚这些,工作中,对于真实线上系统的稳定性、对于底层技术的理解是有帮助的,操作系统是面试中常见问题之一。 142 | 143 | 书籍: 144 | 145 | - <现代操作系统> 146 | - <深入理解计算机系统> 147 | 148 | 是比较全面,写的比较好的书,极力推荐这 2 本。 149 | 150 | 视频: 151 | 152 | https://pan.baidu.com/s/1XiKe5e0UoI2Fp3Amn7aCCA 153 | 154 | 密码:y230 155 | 156 | ### 4、计算机网络 157 | 158 | **计算机网络**:OSI 七层模型和 TCP/IP 四层体系结构,TCP 三次握手与四次挥手、常见的网络协议(网桥、ARP、IP、ICMP、TCP、UDP、DNS、DHCP)、TCP 粘包、流量控制 + 拥塞控制、数字签名原理、http + https,http 的状态码,https 的安全机制,网络安全、输入 www.baidu.com 背后发生了什么等等问题。 159 | 160 | 其实工作中,有时就会出现,网络抖动、网络延迟,网络拥塞的情况,此时就需要具备一定的网络知识,及时的解决问题,计算机网络是面试中常见问题之一。 161 | 162 | 书籍: 163 | 164 | - <计算机网络>(谢希仁第 7 版); 165 | - (卷一) 166 | 167 | 视频: 168 | 169 | https://pan.baidu.com/s/1xRvWUlWzQ9c67XTo0Lkg-g 170 | 171 | 密码:c85g 172 | 173 | ### 5、数据库 174 | 175 | **数据库**:数据库作为存储数据的地方,其不同的数据结构、与应用的场景不一样,采取不同的数据库,对于 mysql 基本操作、写 sql 的优化、表的设计、索引优化、如何更快的查询、底层数据结构的设计原理等等问题。 176 | 177 | 常见的设计模式、主要是学习设计模式的思想、单例模式是必须写代码实现的,其他设计模式理解思想,作为了解内容,后台开发工程师与 mysql 打交道挺多的,也是面试常见问题之一。 178 | 179 | 书籍: 180 | 181 | - 182 | - <高性能 Mysql> 183 | - <大话设计模式> 184 | 185 | 数据库视频: 186 | 187 | https://pan.baidu.com/s/1yIT0nVwFazu0f7mJA0pBiA 188 | 189 | 密码:33n1 190 | 191 | ### 6、Linux 192 | 193 | **Linux**:Linux 的目录结构、文件系统、启动过程、用户环境,Linux 下常用命令(find、grep、awk、xargs)、正则表达式、软/硬链接、重定向、日志信息、网络配置(top、ps、ifconfig、ping 等)、简单的 shell 脚本会写(常见的脚本写一些自动化工具或者定时任务)。 194 | 195 | 熟练掌握 vim,用 C++ 写代码的话,还需要掌握 gcc、g++、gdb 调试,makefile 的编写,工作基本上离不开 Linux,也是面试常见问题之一。 196 | 197 | 书籍: 198 | 199 | - <鸟哥私房菜> 200 | 201 | 视频:Linux 这块的视频,目前最好的是:马哥的和老男孩的视频,建议大家去网上搜着找一下。 202 | 203 | https://pan.baidu.com/s/1y9Nw2sL0tcFzej2q6DzUwg 204 | 205 | 密码:3o32 206 | 207 | ### 7、C 语言 208 | 209 | **C 语言**:C 语言是我学习编程的第一门语言,是面向过程的语言,对于 C 语言中的数组、函数、指针、内存对其模式、大小端问题、野指针、内存泄露、static、register、define、typedef、struct、union 等一些关键字的考察。 210 | 211 | **我一直把 C 语言当做基础,不是方向,在 C 语言这里学到了很多编程的思想,对于 Linux C/C++ 方向,C 语言是基本功,也是必定考察的地方,当初我也是因为特别喜欢 C,走上了 C++ 的道路。** 212 | 213 | 书籍: 214 | 215 | - 216 | - 217 | - 218 | - 219 | 220 | 视频:b 站郝斌的 C 语言强烈推荐 221 | 222 | **C 语言可以学,C 语言是基础,不是方向,但是选择走 C++ 方向要慎重!** 223 | 224 | 对于上面的每一个模块,其实都能单拿出来,写的更为具体一些,后面有时间的话,我会写的尽量详细。 225 | 226 | ## 五、C++ 方向的深入学习路线 227 | 228 | ### 1、C++ 基础 229 | 230 | **C++ 基础**:C++ 是面向对象的语言,一定要理解清楚面向对象的思想,先把 C++ 的基础知识点打牢,刚从面向过程中转变过来,一定一定要适应面向对象的写法。 231 | 232 | 在学习面向对象的时候,也要考虑如何用面向过程去实现面向对象(其实也就是结构体中有一个成员是函数指针),对于 C++ 的基础知识,我简单罗列如下: 233 | 234 | 1. const的用法 235 | 2. 引用的用法 236 | 3. #define用法 237 | 4. 构造函数 238 | 5. 析构函数 239 | 6. 拷贝构造 240 | 7. new、delete 和 malloc、free 的区别 241 | 8. 访问限定符 public、private、protected 242 | 9. 深拷贝和浅拷贝 243 | 10. 友元函数 244 | 11. static 245 | 12. 内联函数 246 | 13. 继承、虚继承 247 | 14. 钻石继承问题 248 | 15. 同名覆盖问题 249 | 16. 虚函数表 250 | 17. 虚指针 251 | 18. 虚函数、纯虚函数 252 | 19. 接口 253 | 20. 多态 254 | 21. 重写 255 | 22. 重载 256 | 23. 函数重载 257 | 24. 运算符重载 258 | 25. 流类库和文件 259 | 260 | 书籍: 261 | 262 | 第 5 版先全面的了解清楚 C++ 的基础。 263 | 264 | ### 2、C++ 进阶 265 | 266 | **C++ 进阶**:函数模板、类模板,C++ 中对于异常的处理,对于继承和多态底层的理解,对于 virtual 底层的理解等。 267 | 268 | 对于 C++ 中 boost 库八大智能指针的掌握与理解,其核心是理解并且剖析过相应的源码,scoped_ptr/shared_ptr/weak_ptr 这三个是最核心的智能指针,理解清楚智能指针的本质是,内存的申请与释放全部交给了对象管理,以避免人为疏忽,造成内存泄露。 269 | 270 | 书籍: 271 | 272 | - 273 | - 274 | - <深度探索 C++ 对象模型> 275 | - 276 | 277 | ### 3、STL 源码 278 | 279 | **STL 源码**:对于 STL 中的容器剖析,常见容器有 list、vector、stack、queue、map 等,考察自动扩容的原理、map 的底层实现(RBtree),源码是必须手动至少剖析一遍的。 280 | 281 | 对于迭代器、空间配置器的理解,比如:一级空间配置器、二级空间配置器的运用场合分别是什么?一二级空间配置器的本质是什么,如何用内存池去管理?所存在的问题又有哪些,源码又是如何实现的等等,这些问题都需要去思考。 282 | 283 | 书籍: 284 | 285 | - 286 | - <泛型编程与STL> 287 | 288 | ### 4、Linux 网络编程 289 | 290 | **Linux 网络编程:** 291 | 292 | 1. Linux 进程环境:僵尸进程、孤儿进程、守护进程、进程组、会话、前台进程组、后台进程组; 293 | 2. Linux 进程七大通信方式:signal、file、pipe、shm、sem、msg、socket; 294 | 3. Linux 线程:互斥量、锁机制、条件变量、信号量、读写锁; 295 | 4. Linux 下并发模型:多进程、多线程、线程池; 296 | 5. Linux 下 I/O 复用:select、poll、epoll 高并发; 297 | 6. Linux 网络编程; 298 | 7. 静态库和动态库; 299 | 300 | 书籍: 301 | 302 | - 303 | - 304 | - 305 | - 306 | 307 | 视频: 308 | 309 | https://pan.baidu.com/s/1vSKPRpNEPSj59iASaZD38A 密码:e4q3 (陈硕的网络编程) 310 | 311 | ### 5、内核源码剖析 312 | 313 | **内核源码剖析**:对于 Linux 内核源码,可以先看 Linux 内核的设计与实现,了解清楚每部分的构造与原理,前期多看书、多看相关视频,对一些源码的解读,到一定程度,最好拿到 Linux 2.6 版本内核源码,我是用 Source Insight 工具辅助分析源码的。 314 | 315 | 这个工具对于源码的分析特别友好,很快定位变量、追踪函数,其实重点应该放在内核文件系统与内核数据结构的实现上面,多看看源码是如何实现的,比如:内核链表的源码实现,真的是一种非常独特的思想,没有看的可以去看看(没有源码的可以找我要)。 316 | 317 | 书籍: 318 | 319 | - 320 | - <深入理解 Linux 内核> 321 | 322 | 内核视频: 323 | 324 | https://pan.baidu.com/s/1jvLYQFJa5ZTZ0_E3kZ-pcQ 密码:yn06 325 | https://pan.baidu.com/s/1ZsngBAllXGEkThSVearOuQ 密码:h9qs 326 | 327 | **C++ 相关视频:推荐看黑马的 C+++ 视频,是全套的,讲的比较好,对于推进的书籍,先看看目录,就大概了解其内容了。** 328 | 329 | ### 6、开源网络库 330 | 331 | **开源网络库**:对于 Linux C/C++ 方向,还需要关注一些业内开源的网络库,比如:MemCached、libevent 等,在 github 上面可以直接搜,对于分布式、高并发、集群和负载均衡等知识,这部分作为了解,要是有兴趣,也可以深入看看,在深度的前提下,作为技术广度的扩充。 332 | 333 | **针对上面,从基础到 C++,我列出来的都是非常重要的知识点,当然了,也不可能全部列到,有很多技术问题,很多细节,我可能没有考虑到,没有写到,这个还需要在学习的时候,认真看看视频、看看书,把相应的知识都学到位,基础打扎实一些。** 334 | 335 | ## 六、项目 + 亮点 + 面试的一些思考 336 | 337 | ### 1、项目 338 | 339 | **项目**:对于暑期找实习,或者秋招找工作,除了基础跟方向,接下来就是项目的准备了,对于 C++ 方向,很多人不知道要准备什么项目?其实项目不在于有多大、有多难,在于项目是否是自己真正做的,自己是否完全消化了,项目中是否有什么亮点? 340 | 341 | **C++ 方面的实战项目,以数据结构 + 网络编程 + 实用工具为主;数据结构方面:可以实现红黑树、B+ 树,又或者用图解决什么实际问题,这些复杂的数据结构实现可以作为项目的。** 342 | 343 | **7 大进程间通信,6 大高并发模型,可以写线程池,select、poll、epoll等局域并发聊天项目。** 344 | 345 | **实现工具,以自己写个简单的压缩工具、编译器、内存泄露检测工具等,这些都是项目的来源,我的项目就有:网络编程实现在线群聊、压缩工具,对文件或者图片进行压缩、解压缩。** 346 | 347 | 对于项目这块,面试的常见问题有: 348 | 1. 做这个项目的背景是什么? 349 | 2. 项目中具体有哪些模块,都是怎么实现的? 350 | 3. 项目中你的技术亮点有哪些? 351 | 4. 项目中有什么难点,你是怎么解决的? 352 | 5. 要是重新做这个项目,你这个项目有什么不足,你会进行哪些改进? 353 | 354 | ### 2、亮点 355 | 356 | **亮点**:找实习或者找工作,必须的有自己的亮点,我觉得在那么多基础知识中,数据结构 + C 语言就是我的亮点之一,只要问到关于这 2 个方面的问题,尽量回答全面清楚一些,还有就是自己对于 Linux 内核数据结构的剖析也是亮点之一,总之,一定要找到自己的亮点,与别人不一样的地方,这个就是面试的加分项。 357 | 358 | **搜索引擎的底层原理、通讯的底层原理,对于这些底层的实现,有兴趣的可以了解看看,其实也没那么难,要是在面试的时候,能回答出对这些技术的了解,以及自己的一些思考,那就是加分项了。** 359 | 360 | ### 3、面试 361 | 362 | 面试:春招实习、秋招决战,我不知道投了多少家公司,也不知道面试了多少场,基本上都是海投的,有了面试机会,就要抓住每一次,面试完多做总结、归纳、反思;其实面试很玄学,有自身实力的原因,也有运气的成分,相信自己,好好表现就好。 363 | 364 | **对于面试,才开始我也是比较紧张的,但是当你面的多了,慢慢的就会调整过来,就会好很多,我现在把面试当做是,这是一次近距离和优秀的人交流的机会,是一次学习进步的机会,有了这种心态,其实就好的多了。** 365 | 366 | ## 七、总结 367 | 368 | **推荐一些好的视频网站:b 站、牛客网、极客时间、51cto、七月算法、网易云课程,基本上你所需要的视频资料都可以去找,实在不行上淘宝看看,有些视频文中没有给到,需要自己去找找,我的网盘满了,清空了一些,这些都很好找到的。** 369 | 370 | **对于实在自己找不到视频、书籍资源的读者,你私聊我,我有时间给你找找,视频其实核心就是:抓住黑马,找一个全套的,跟着看、跟着学、一直走下去。** 371 | 372 | **我走的是 Linux C/C++ 路线,秋招投递这个岗位也很多,对于没有我简历的、没有 Google C++ 编程规范的,你私聊我,把这些该有的资料都送给你。** 373 | 374 | **对于想走 Linux C/C++ 方向的同学,基本上按照上面的路线走,相应的书籍以及视频都有推荐,多实战操作。** 375 | 376 | **日积月累,终有所成!!!** 377 | 378 | 379 |
380 |

(我在 “2+2” 实验室座位)

381 | 382 |
383 |

(精选文章集)

384 | 385 | **大学期间的方向抉择、考研/就业抉择、暑期实习备战、秋招决战、offer 选择、学习编程方法、习惯等等等,共计 20 余万字的个人亲身经历,适合每一位在校大学生多读读,找准自己的方向,人生打法!** 386 | 387 | ## 八、说明 388 | 389 | 原创文章链接:[Linux C/C++ 学习路线(已拿腾讯、百度 offer)](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484210&idx=1&sn=7e4d20ad4fe125cce4c234330ad21125&chksm=fdb6f719cac17e0fce1be3acf1043cc6cbde353c75d37eeb0d78caa9d1cf6edd8ddb07c8bb9c&token=1026755469&lang=zh_CN#rd) 390 | -------------------------------------------------------------------------------- /cs-basics/学习路线指南/Linux学习路线.md: -------------------------------------------------------------------------------- 1 | - [一、Linux 方向的思考](#一linux-方向的思考) 2 | - [1、](#1) 3 | - [2、](#2) 4 | - [二、Linux 学习路线](#二linux-学习路线) 5 | - [1、](#1-1) 6 | - [2、](#2-1) 7 | - [三、说明](#三说明) 8 | 9 | 前面写了 C++、Java、数据分析的学习路线: 10 | 11 | 1. [Linux C/C++ 学习路线(已拿腾讯、百度 offer)](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484210&idx=1&sn=7e4d20ad4fe125cce4c234330ad21125&chksm=fdb6f719cac17e0fce1be3acf1043cc6cbde353c75d37eeb0d78caa9d1cf6edd8ddb07c8bb9c&scene=21#wechat_redirect) 12 | 2. [Java 学习路线](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484226&idx=1&sn=f2767de92cba3e87e20ecdec4ccdb149&chksm=fdb6f769cac17e7f7cefeb89b3980e58a32be810b4197cfdc4d7b005a65176c2e10b6eabdca2&scene=21#wechat_redirect) 13 | 3. [数据分析学习路线](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484247&idx=1&sn=4af78cfa4412f2439ea45fede042c25a&chksm=fdb6f77ccac17e6a73172270ed4259bfe696379e29dfbc579a6a43b1538257ff0b712a21dda8&scene=21#wechat_redirect) 14 | 15 | 对于 C 语言,我公众号不仅有学习路线,自己还写了 10 余篇 C 语言的入门文章,关于 C 语言的入门,把我写的文章中的都能看懂、吃透, C 就算入门了。 16 | 17 | **学习 C 语言或者 Python,都可以在 Linux 系统上面学习,刚入编程,可以先拿 win 熟悉,等你熟悉一段时间之后,Linux 是不得不接触的,Linux 真的至关重要!** 18 | 19 | ## 一、Linux 方向的思考 20 | 21 | ### 1、 22 | 23 | Linux 属于基础中的基础,是每一位程序员必备技能,跟你做后台、算法、大数据、前端、测试方向无关,要学 Linux 的这个意识必须有。 24 | 25 | Linux 下面的调试 C 和 Python 的代码特别方便,gdb 和 pdb,可以打断点进行调试,输出追踪,尽快的上手 Linux,熟悉 Linux,有利于编程的学习(尤其要走 Linux C/C++ 方向)。 26 | 27 | **我在校期间,真的是花了大量的时间折腾 Linux,在实验室,我的台式机是三系统,我的笔记本电脑装的是虚拟机 VM,是 8 系统,基本上各个 Linux 版本我都玩过,是真的很有意思。** 28 | 29 | **我工作中开发 C 或者 Python 代码,都用的是 Linux 下面的 vim,工作快一年了,基本上每天都要跟 Linux 打交道,在写 Python 的很多时候,还要跟 Linux 的系统环境、相关性能打交道。** 30 | 31 | ### 2、 32 | 33 | **对于 Linux 的学习,我是建议装虚拟机就好了(真没必要双系统),ubuntu 官网下载镜像,开个 VM,在桌面用 XShell 连接,绿色框框敲起代码来,特别爽!如果你是 Mac,就不存在装环境这些问题了。** 34 | 35 | Linux 方向的工作,有运维工程师、运维开发工程师、还有大数据、云计算运维工程师,Python 自动化运维等,现在基本上大厂招运维的多一些,很多小的企业都部署到云上去了,公司招运维没多大用处,以后在往自动化方向发展。 36 | 37 | **Linux 相关技能,不管是在面试中、还是工作中,都是大有用处的!** 38 | 39 | ## 二、Linux 学习路线 40 | 41 | ### 1、 42 | 43 | **国内知名马哥或者老男孩的视频讲的不错,初学者可以看看老男孩的视频、Linux 有一定基础,可以看看马哥讲的 Linux 视频,书籍:《鸟哥私房菜》结合着学习,关于视频资料,b 站、淘宝上面看看。** 44 | 45 | **初级**:Linux 需要掌握 Linux 相关系统环境、网络配置、以及常用命令:ln、grep、awk、find、vim 等,达到熟练使用 Linux 系统。 46 | 47 | **中级**:会写 shell 脚本、crontab 定时任务的执行、以及掌握 gcc 的预处理、编译、汇编、链接的理解,对于一些快速工具开发的掌握。 48 | 49 | **关于 Linux 的学习细节,抓住老男孩或者马哥的全套视频,定位好自己的方向,需要掌握 Linux 到什么程度,再选择性学习,问题就不大。** 50 | 51 | ### 2、 52 | 53 | 推荐极客时间一门 Linux 有关的课程:《Linux 性能优化实战》 54 | 55 | ## 三、说明 56 | 57 | 原创文章链接:[Linux 学习路线](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484254&idx=1&sn=b5654615ddf24d63914574fbe06781b8&chksm=fdb6f775cac17e63b7a7531d2eaedb23065ce4918ad6e4d9bba04f11bc69ae33e22182774be2&token=55747187&lang=zh_CN#rd) 58 | -------------------------------------------------------------------------------- /cs-basics/学习路线指南/五大能力提升.md: -------------------------------------------------------------------------------- 1 | - [一、检索能力](#一检索能力) 2 | - [1、](#1) 3 | - [2、](#2) 4 | - [3、](#3) 5 | - [二、判断力(信息识别)](#二判断力信息识别) 6 | - [1、](#1-1) 7 | - [2、](#2-1) 8 | - [三、我想说的](#三我想说的) 9 | - [四、说明](#四说明) 10 | 11 | >我走过山的时候山不说话 12 | 我路过海的时候海不说话 13 | 14 | >出自金庸《神雕侠侣》 15 | 16 | 上面这段话,是今天我看阿里创业史视频当中的第一句话,是我新人培训时候看过的,没想到现在分享出来了,这个视频我早上分享朋友圈了,大家一定要去看看,真的是心潮澎湃,自己特别喜欢,就写出来,思考思考其中的意味。 17 | 18 | 我作为一名非科班学生,作为一名 95 后,短短 2-3 年间,从通信行业先转后台,再转算法,先后去过腾讯、百度、阿里,一路走来,不仅仅是努力的结果,还有自己的战略、打法,以及人生的布局。 19 | 20 | 今天,我想把我的一些思考分享出来,这正是绝大部分人所不具备的,这也是改变我本质的原因,**我一直以来都是把自己亲身经历过的,最真实的记录下来**,以便于自己能够更快的成长,所以接下来的内容至关重要,希望你可以认真,带着思考去看。 21 | 22 | ***五大能力:检索能力、判断力、快速学习能力、应用业务能力、解决问题的能力。*** 23 | 24 | ## 一、检索能力 25 | 26 | ### 1、 27 | 28 | 总结其实就一句话:对于自己所需要的资料,一定要训练这种能力,一种快速的得到并且筛选出符合自己预期的能力。 29 | 30 | **信息检索能力 + 有效资料判断力** 31 | 32 | 由于关注我的读者,程序员较多,拿编程行业举个例子,先抛出一个问题:作为一个程序员,想翻墙 google、想去安装虚拟机双系统,想要搞点资料,就那么难吗? 33 | 34 | 看清问题,我说的是一个程序员,是一个已经入行的,不是指的刚刚入门的编程小白(编程小白多听听有经验的人),对于在这个行业摸爬滚打一年以上的程序员,如果不具备这个能力,我觉得是应该好好反思,先将最基础,最重要的能力培养起来。 35 | 36 | 我所说的信息检索能力:不仅仅指的是你会用个 Google,大部分人的思维误区就是,用 Google 搜就好了,就这么一句话,其实有很多人还不会使用 Google 搜索的正确姿势。 37 | 38 | 至于用百度去检索资料,我相信大部分的程序员已经抛弃了,确实百度上面打广告比较多,能搜出有用的信息真的很少,对于我们很不友好,建议以 Google 搜索为主。 39 | 40 | **记住:我现在说的不仅仅是编程行业,说的是作为一个职场人,各行各业,都需要这个能力,能快速检索出有用的信息,这个是最基础的能力,以便于找到自己想要的东西,具备了这种能力,才能更长远、更长久的发展下去。** 41 | 42 | ### 2、 43 | 44 | 我大学期间,想要看个付费电视剧,或者想要找编程视频,运营资料、PPT素材这类资料相关的,大二的自己,总是问别人,看看谁能不能给我提供这些,总想着别人帮我,自从进了实验室之后,**我用了快 2 年的时间,用来培养资料的检索能力,现在只要我想找什么资料、素材都可以通过自己,在短时间内快速的解决,这才是检索能力。** 45 | 46 | 检索能力:你想要的资料、素材,可以通过自己快速解决,总结就一句话,**短时间内,我想找的,就没有找不到的,这才是能力的提升。** 47 | 48 | 这个说来容易,但是真正的具备,是何其的难,只有通过了常年累月的摸索、学习,踩过了无数的坑,才能真正的掌握精髓,但是绝大部分人的意识正好是反的,能用钱解决的就用钱解决,那可以节约时间,用来学习技术。 49 | 50 | **关于技术的学习,我以前就说过,学好一个方向就行,在这个方向深入下去,我自己就是一个最真实的例子,以前我是深入的学习Linux C/C++ 方向的,来工作已经 3 个多月了,一行 C/C++ 代码都没写过,写的都是 Python 以及写组件相关的语言,对于没有接触过的,直接通过检索能力,干就完了,哪里能有时间去熟悉呢。** 51 | 52 | 我一直强调大家注重编程思维,编程习惯、与能力的提升,这将影响你生活的方方面面,这才是最受用一辈子的。 53 | 54 | 我认为能用钱解决的,往往是最容易的事情,难的是自身能力的提高,难的是长远的发展,避免了现阶段的坑,是暂时的,以后总会碰到,把问题放的越久,越难治好。 55 | 56 | ### 3、 57 | 58 | **很多看似做了无用功的事情,其实对以后的你成长至关重要。** 59 | 60 | 举个例子:我大学期间,喜欢自己去摸索,去尝试,我在大二的时候,对于装系统特别的感兴趣,我就给自己实验室的台式主机,安装了三系统,其实安装 10+ 系统都是可以的,只要磁盘分区设置正确、引导系统没什么问题就行,我给我的 VM 虚拟机安装了 8 系统。 61 | 62 | 你说我装那么多系统、那么多虚拟机,真的用不到吗?是的,用不到,我就是纯兴趣,但是这过程中,自己摸索、解决了不少问题,背后是动手能力的提升、这种能力的提升是潜移默化的,以后在碰到类似的事情,还是问题吗? 63 | 64 |
65 |

(VM安装8系统虚拟机)

66 | 67 | **很多看似节省了大量时间的事情,却没有得到本质上的成长。** 68 | 69 | 我在大学期间,所有的视频学习资料,以及PPT,都是自己通过各种方式,渠道,去获取,花费了很多时间,踩了不少坑,我觉得是值的,通过自己去检索一切,这的确锻炼我信息检索的能力,尤其是我工作之后,我真的觉得太重要了。 70 | 71 | 往往很多人忽视了检索能力,只关注于技术的学习,别人提供个 Java/Python 视频,我看就好了,我学习其中的语法,进阶,做项目就好了,但是最深层次的检索能力你没有锻炼出来,**每当你缺少什么资料的时候,东问西问,着急忙慌,你怎么不停留下来好好想想,为什么别人能给我提供这个资料,而我没有这个能力呢?** 72 | 73 | 有些坑必须要踩,越早踩越好,其代价也就越小,尤其在学生阶段,一定要多折腾,多探索,去锻炼出自己无所不能的检索能力。 74 | 75 | **我不这样认为,花些钱就能解决的问题,一定要节省时间花钱解决,靠别人给予的资料、素材,永远是弱者,自己永远无法具备强大的检索能力,经历、经验永远是最宝贵的财富,而这必须通过自己的实践才能培养起来。** 76 | 77 | 总有人以时间宝贵为借口,用钱来换取资源,看不上别人走了很多弯路,觉得他人是在浪费时间,但是我想说的是,**从长远来看,你只是一时的节约时间,时间一旦过去了,你没有得到根本上的成长才是最大的损失,能力的提升才是真正的成长,不仅仅指的是技术的提升**,用时间来填坑,能力在悄无声息中提升,这是我所认为的(这个跟知识付费不一样,知识付费我是很认可的)。 78 | 79 | ## 二、判断力(信息识别) 80 | 81 | ### 1、 82 | 83 | 我见过好多人,百度云盘都是几个 T 的编程资料,视频了、pdf了都多的很,而我的百度云盘呢,也就几十个 G 而已,没有存大量的视频,因为我不需要,一旦当我想要什么资料、插件、视频、我能很快速的得到最想要的那个。 84 | 85 | 我想不通的是,为什么大部分人要把资料、视频存在网盘中,明明自己又没时间看,也不会去学习这些,难道是心理自我安慰吗?我觉得,不用存那么多啊,我需要什么视频资料,去检索获取就好了啊,这才是正确的方式。 86 | 87 | 而很多人,存的那么多视频资料,我敢说,绝大部分自己都没有看过,别人需要资料的时候,就这么一推荐,能不说这个视频讲的很好吗?而绝大部分人,又没有最起码的判断力(辨识资料的好坏),就跟着看学习了,**这根源就是自己严重缺乏资料的检索能力,只能依赖别人**(我文中所推荐的都是我看过的,我是可以给大家负责的)。 88 | 89 | **以前踩过的坑,搜到了很多的资料,必须快速的浏览,以及判断,一定的有自己的有判断力,这些都是通过长时间的积累,能力锻炼出来的,我早就说了,培养自己的能力是最重要的。** 90 | 91 | ### 2、 92 | 93 | **判断力是很重要的,不仅仅在筛选资料方面,在人生的各个阶段,判断力将决定你的格局,我是从编程资料的筛选,建立起来强大准确的判断力。** 94 | 95 | 我在工作中,对这方面是真的深有体会,在大厂中,都有自己技术相关的沉淀,文档了,视频了,面对这么多的资料,必须有快速的查找和判断,以及学习,才能更快的适应工作的快节奏,举个例子:有次老大给我说,需要什么插件,让我自己去找一下,再安装好,顺便在给组里面需要的都提供一下,**我当时很迅速的就完成了,得到了老大的称赞,说这么快就搞定了,我说就这么快,在这就是你检索能力的体现,迅速的解决了问题,得到了认可。** 96 | 97 | 快速的检索资料,以及判断是不是对自己有用,这个能力真的被大部分人所忽视,这就相当于把半条命交给了别人,**优秀的程序员是有着极强的检索信息的能力以及判断哪些信息有用的能力(判断力)。** 98 | 99 | ## 三、我想说的 100 | 101 | **别人能帮的了你一时,但帮不了你一世,人只有依靠自己,才能更加强大起来。** 102 | 103 | 快速学习能力、应用业务能力、解决问题的能力,这些基础能力,大部分人都有这个意识,**唯独信息检索能力以及判断力是很容易被忽视的**,这个是我再三强调的,因为很重要,我的多说几遍。 104 | 105 | 从长远发展来看,培养出这种能力是当务之急,外界总有不稳定因素,靠谁都靠不住,自己必须具备这种能力,才是最放心的。 106 | 107 | **快速的检索资料的能力,以及快速的判断力,快字不可忽略啊,天下武功,唯快不破,就是要快。** 108 | 109 | 知识可以去学习,但是经验,能力的提升,必须通过动手、去实践,去踩一系列的坑,**我很明确,我就是要通过踩坑,来进行最快速的成长,得到能力的锻炼、提升。** 110 | 111 | **能力即潜力,我举一个例子,我有了能力,相当于我守了一个核武器库,你所需要的任何技术、任何业务,我可以在短短的几周内,迅速的开发,解决这个问题,原因无乎其外,五大能力的体系建立,是你任何解决问题的保证。** 112 | 113 | 相信我,一开始很痛苦,经过长时间的沉淀,你的能力将极大的提升,以后的道路将越走越宽。 114 | 115 | 强者无敌,大爱无疆!!! 116 | 117 | ## 四、说明 118 | 119 | 原创文章链接:[五大能力提升](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247483896&idx=1&sn=ab4aa5b0620c5fe6e8ded4356710ed5e&chksm=fdb6f5d3cac17cc5216e05c2537d0cfc41a316ec60ececd3af8ecce1d25056cfe48bfa0eb5e9&token=1469515448&lang=zh_CN#rd) 120 | -------------------------------------------------------------------------------- /cs-basics/学习路线指南/数据分析学习路线.md: -------------------------------------------------------------------------------- 1 | - [一、数据分析方向的思考](#一数据分析方向的思考) 2 | - [1、](#1) 3 | - [2、](#2) 4 | - [二、数据分析学习路线](#二数据分析学习路线) 5 | - [1、基础](#1基础) 6 | - [2、进阶](#2进阶) 7 | - [3、拔高](#3拔高) 8 | - [4、推荐资料](#4推荐资料) 9 | - [三、数据分析工作中](#三数据分析工作中) 10 | - [四、说明](#四说明) 11 | 12 | 最近,写了 Linux C/C++、Java 的学习路线,对于要走这个方向的读者,看看文章,大致方向不会错的,在看的过程中,要慢慢培养自己的技术栈: 13 | 14 | 1. [Linux C/C++ 学习路线(已拿腾讯、百度 offer)](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484210&idx=1&sn=7e4d20ad4fe125cce4c234330ad21125&chksm=fdb6f719cac17e0fce1be3acf1043cc6cbde353c75d37eeb0d78caa9d1cf6edd8ddb07c8bb9c&scene=21#wechat_redirect) 15 | 2. [Java 学习路线](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484226&idx=1&sn=f2767de92cba3e87e20ecdec4ccdb149&chksm=fdb6f769cac17e7f7cefeb89b3980e58a32be810b4197cfdc4d7b005a65176c2e10b6eabdca2&scene=21#wechat_redirect) 16 | 17 | 对于 Java 学习路线,上篇文章说到的框架那块,有些过时了,现在直奔 spring 或 springboot 即可,另外 2 个框架不用学了。 18 | 19 | 后台三大主力,C++、Java、Go,Go 语言的学习路线不打算写了,目前走 Go 方向的人很少,看之后发展如何吧;上次读者留言,提到了数据分析,对于目前大火的 Python,在数据分析方面,是有一定的优势的。 20 | 21 | ## 一、数据分析方向的思考 22 | 23 | ### 1、 24 | 25 | 对于 Python,可以从事的方向有:爬虫、后台、web、数据分析、算法岗,目前来说,要是选择 Python 的话,走数据分析、算法岗是比较好的;**当然了,Python 最适合的场景就是 AI,要是能直接走算法岗是最佳选择。** 26 | 27 | 走数据分析的,大部分人本身可能只熟悉 Python,有一部分人是真的喜欢这个方向,有一部分人其实是被动选择,想找后台方向,不熟悉 C++、Java、Go,没法投递,想找算法岗,对于机器学习十大算法以及算法方向的能力暂时不具备,只能选择数据分析这么一个岗位了。 28 | 29 | 对于数据分析,国内招聘的需求岗位远不如后台、算法岗多,加上现在 Python 大火,很多人都走的 Python 路线,其竞争非常激烈,对于数据分析岗的技术含量,远没有算法岗那么多,要求也没那么严,其薪资待遇也不算高。 30 | 31 | 数据分析其实很实用,可以通过对大量数据的观察、分析、得到一定的规律,对于现在的大数据、云计算,尤其是面对海量数据,就需要一些快速处理的方法,数据分析岗位在公司中有一定的重要性,这个方向可以作为走向 AI 算法岗的跳板。 32 | 33 | ### 2、 34 | 35 | 对于技术没多大追求的,还想踏入互联网行业的,完全可以选择走数据分析,数据分析这个方向相对而言,跟业务挂钩比较大,熟悉了业务背景,还是很好上手的,**如果一开始不具备算法岗的能力,也可以从数据分析入手,慢慢转向算法岗。** 36 | 37 | **我要清醒的告诉大家一点:数据分析的技术含量是比较低的,如果你想长期从事技术方面的工作,还是需要走后台或者算法岗,很多人投递这个方向,其实是被动与无奈的选择,都不知道在工作中,数据分析到底是干啥的,一定要想好自己的职业方向。** 38 | 39 | **如果真的喜欢数据分析,对数据比较敏感,一直从事在这个岗位也是挺好的,关键是要做自己喜欢的事情!** 40 | 41 | ## 二、数据分析学习路线 42 | 43 | 数据分析,我在工作中有过简单的接触,自己目前入门较浅,根据自己的思考,分享一下我认为的学习路线、资料推荐,其中肯定有不足之处,希望大家在学习的时候,慢慢完善自己的技术栈就好了。 44 | 45 | 数据分析岗位,简单理解,就是对于数据的处理、分析,得到结果,所以这个方向需要学习数据分析的 2 个方面:工具 + 方法 (数据处理的工具以及数据处理的常见方法)。 46 | 47 | 数据分析最完整的流程:数据获取--->数据存储--->数据预处理--->数据分析--->数据可视化。 48 | 49 | ### 1、基础 50 | 51 | **Excel** :最基础的数据处理工具,偏向于运营岗位的数据分析,作为一个数据分析师,Excel 无条件的熟练掌握,对于数据量较少,拿 Excel 进行分析、转换、运算即可,而且数据分析师很大一部分时间是在与 Excel 在打交道。 52 | 53 | **SQL**:sql 语句的熟练掌握,这就是跟数据库打交道了,利用 sql 把数据进行提取,分析是很常见的一种方法(说句实话:算法岗也有一部分时间是在写 sql),不管你从事数据分析、还是算法岗,sql 都非常的重要,因为这是跟数据库打交道最直接的语句了。 54 | 55 | **我前面说过,不管你是啥方向,工作中最重要的三项技能,必须非常非常熟练的掌握起来:Linux + Git + Sql。** 56 | 57 | **Python**:Python 基础知识的掌握,主要是 Python 非常擅长处理数据,Python 有很多包、方法都是可以直接调用的,作为一名数据分析师,对于一些复杂的场景,会用脚本语言进行数据分析。 58 | 59 | **Python 爬虫**:对于这项技术的理解,掌握了会更好,不会也不影响你作为数据分析师的日常工作,数据分析师的主要工作是对于数据的理解、处理,拿到结果;对于 R 语言,也是一门脚本语言,方便处理数据的,有时间可以接触,学习学习,Python 在这方面的需求是远大于 R。 60 | 61 | **数据分析师的基本功:Excel + Sql + Python,加上对于业务的理解,日常需求还是能完成的,对于那些计算机基础知识,肯定是掌握了更好啊!** 62 | 63 | ### 2、进阶 64 | 65 | **Python 科学计算**:pandas、numpy、scipy 等,pandas 常用于数据的清洗(重复、缺失、异常值等),把这些缺失的数据处理好,才能获得更加准确的分析;numpy 支持数组和矩阵的运算,提供了大量的数学函数库;scipy 是一个高级的科学计算库,很多数学统计的相关函数都在其中。 66 | 67 | 对于科学计算包 pandas、numpy、scipy 等,作为数据分析师的进阶是最好要掌握的,花些时间,把这些都得熟悉掌握起来。 68 | 69 | **概率论及统计知识:** 70 | 71 | 1. 基本的概念:均值、中位数、众数、极值等; 72 | 2. 统计量:方差、标准差、显著性等; 73 | 3. 概率论知识:条件概率、贝叶斯等; 74 | 4. 。。。 75 | 76 | 有了统计学的基本知识,就可以拿上面的量化数据,来描述数据的指标,观察数据规律,得到一些结论性的总结,以及一些变化趋势的预估,这块数据分析做的就是有些技术含量的东西了。 77 | 78 | ### 3、拔高 79 | 80 | **数据分析师的拔高,就是在慢慢的走向机器学习方向,慢慢的转为算法岗。** 81 | 82 | - 特征工程的基础:如何统计数据特征、选用不同的特征,做模型的优化; 83 | - 基本的分类算法:决策树、随机森林等; 84 | - 基本的聚类算法、数据挖掘、常见的机器学习算法的了解; 85 | 86 | 做到这步的话,慢慢就会有数据挖掘、机器学习的感觉,一个优秀的数据分析师,数学功底是扎实的,就是在潜移默化的转向数据挖掘岗。 87 | 88 | ### 4、推荐资料 89 | 90 | 书籍: 91 | 92 | - 《对比Excel,轻松学习Python数据分析》:易懂易学的好书,强烈推荐! 93 | - 《利用Python进行数据分析》 94 | - 《深入浅出统计学》 95 | 96 | MySQL-菜鸟教程: 97 | 98 | https://www.runoob.com/mysql/mysql-tutorial.html 99 | 100 | 视频:极客时间有一门数据分析课程,去搜搜看。 101 | 102 | ## 三、数据分析工作中 103 | 104 |
105 |

(2019 年腾讯暑期实习招聘)

106 | 107 | 看看投递数据分析方向的比例是多么的吓人(50:1),岗位少,投递人多,竞争太激烈了;看看腾讯对于数据分析师要求的技术栈:数学功底 + Python 脚本,基本上就是这些。 108 | 109 | **当你对于一个岗位,不知道学啥、不知道怎么构建自己技术栈的时候,你就多去官网看看,对于这个方向的要求,会给你指明一个大体的方向,按照着学习、准备、提升自己的技术能力就好。** 110 | 111 | 为啥大部分人都投递这个方向呢?我上面都说了,无奈与被迫的选择,如果计算机水平足够,大部分人还是愿意选择后台或者算法岗,多想想,时刻保持独立思考的能力。 112 | 113 | **对于大部分数据分析师,在工作中,掌握:Excel + Sql + Python 足够了,并没有多大的技术含量,拿的钱相对较少;我这边工作中接触的数据分析工程师,主要就是统计数据、效果追踪、报表可视化展示等。** 114 | 115 | **每家公司的数据分析做的工作是完全不一样的,有的感觉很无聊,有的还有些技术含量,这取决于你的业务与场景,大厂和小厂的数据分析也有差别,不管咋样,时刻保持不断学习的劲头就好了。** 116 | 117 | **面对新的领域,不在于我是否走这条路线,在于我是否思考、查资料、解决这些问题,能快速的给自己规划学习路线,这就是能力。** 118 | 119 | **数据分析未来岗位还会增加,看看是否适合自己,认清自己在技术方面的能力,做好选择。** 120 | 121 | **认真的人,自带光芒!** 122 | 123 | ## 四、说明 124 | 125 | 原创文章链接:[数据分析学习路线](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484247&idx=1&sn=4af78cfa4412f2439ea45fede042c25a&chksm=fdb6f77ccac17e6a73172270ed4259bfe696379e29dfbc579a6a43b1538257ff0b712a21dda8&token=55747187&lang=zh_CN#rd) 126 | -------------------------------------------------------------------------------- /cs-basics/学习路线指南/算法工程师学习路线_NLP 方向.md: -------------------------------------------------------------------------------- 1 | - [一、传统 NLP](#一传统-nlp) 2 | - [1、文本相似度算法](#1文本相似度算法) 3 | - [2、text similarity](#2text-similarity) 4 | - [二、深度学习 NLP](#二深度学习-nlp) 5 | - [1、词向量发展过程,及相应 papers](#1词向量发展过程及相应-papers) 6 | - [2、词向量讲解的相关文章 + 博客](#2词向量讲解的相关文章--博客) 7 | - [三、视频 + 库 + 书籍](#三视频--库--书籍) 8 | - [四、说明](#四说明) 9 | 10 | 对于算法工程师,常见方向有:NLP、搜索推荐、知识图谱、CV、机器学习算法工程师等等,不同领域在求职时岗位是会细化的。 11 | 12 | NLP 技术主要是和数据打交道,通过 SQL + Python 写脚本处理简单文本内容,复杂问题需要跑模型进行处理,常用在搜索召回链路、用户语义识别等场景。 13 | 14 | 我个人比较熟悉 NLP + 推荐相关技术,本文只谈 NLP 相关技术栈,会推荐相关学习资料。 15 | 16 | ## 一、传统 NLP 17 | 18 | - 中文分词技术 19 | - 词性标注 20 | - 命名实体识别 21 | - 词汇权重计算技术:TFIDF、SIF等 22 | - 搜索相关,索引方法:倒排索引,query 与文档相似度计算方法:BM25,文档排序方法:PageRank 23 | - 文本相似度衡量方法:LCS、Levenshtein 距离、杰卡德指数、w2v、wmd 等 24 | 25 | ### 1、文本相似度算法 26 | 27 | **最长公共子序列**(LCS:动态规划思想,与最长公共子串有些不一样) 28 | 29 | - http://www.kancloud.cn:8080/digest/pieces-algorithm/163624 30 | - 得到公共子序列长度后,相似度 = 公共子序列length/min(length(x), length(y)),之所以要除以两个串中短串的长度,是因为需要将相似度进行 normalize,而且当串 y 完全包含 x 时,相似度为 1,所以要除以短串的长度。 31 | - 适用于计算简称和全称之间的相似度。 32 | 33 | **最小编辑距离**(Levenshtein距离,动态规划思想) 34 | 35 | - https://www.dreamxu.com/books/dsa/dp/edit-distance.html 36 | - 可以使用 python Levenshtein 包的 Levenshtein.ratio() 37 | 38 | **jaccard index**(杰卡德指数) 39 | 40 | - 度量两个集合之间的相似性,它被定义为两个集合交集的元素个数除以并集的元素个数。 41 | - 若 A、B 两个集合都为空,则指数为 1。 42 | - 将两个文本进行分词,分词后的集合,计算 jaccard index 43 | 44 | **bm25** 45 | 46 | - https://www.jianshu.com/p/1e498888f505 47 | 48 | **w2v** 49 | 50 | - 对文本进行分词,分词后的每个词,查询词向量表得到词向量,文本词向量为单词词向量的平均。可利用 TFIDF 或者 SIF 等方法对单词进行加权,得单词词向量的加权平均,最后计算两个文本词向量的相似度,可以用 cosine similarity 等方法。 51 | 52 | ### 2、text similarity 53 | 54 | **Jaccard Similarity** 55 | 56 | 做法 57 | - size of intersection divided by size of union of two sets 58 | 59 | 具体做法 60 | 61 | - lemmatization:单词变成 root 形式,譬如has,have,had均变成have形式; 62 | - 计算两个 text 中,交集的单词量/并集的单词量。 63 | 64 | 例子 65 | 66 | - Sentence 1: AI is our friend and it has been friendly 67 | - Sentence 2: AI and humans have always been friendly 68 | - after lemmatization, Jaccard Similarity = 5/(5+3+2) 69 | 70 | **bag of words** 71 | 72 | 做法 73 | - 将所有 texts 所出现的词汇整理成词汇表,利用词汇表表达 text,text 出现过某个词,特征对应维度为 1(出现多次可为 n,为 n 的方式叫做 bag of words + tf ,也叫 Count Vectorizer 方法) 74 | 75 | 具体做法 76 | 77 | - text preprocessing:去除特殊字符,空格等,然后进行word的tokenize; 78 | - preprocessing后的 words,整理成词汇表; 79 | - 利用词汇表,每个 text 表达为 len(词汇表)长度的向量,出现word 的坐标为 1(多次为n)。 80 | - 计算相似性:利用 bag of words + cosine similarity,计算相似性即可。 81 | 82 | **bag of ngram** 83 | 84 | 做法 85 | - 将连续 n 个 words 作为一个 word,然后做 bag of words。 86 | 87 | 具体做法 88 | 89 | - text preprocessing:去除特殊字符,空格等,然后进行 word 的 tokenize; 90 | - 对每个处理后的 text,连续 n 个 words 看做一个 word,加入词汇表; 91 | - 利用词汇表,每个 text 表达为 len(词汇表)长度的向量,出现 word 的坐标为 1(多次为n)。 92 | - 计算相似性:利用 bag of words + cosine similarity,计算相似性即可。 93 | 94 | **TF-IDF** 95 | 96 | 做法 97 | 98 | - 将所有 texts 中所出现的词汇整理成词汇表,利用词汇表表达 text,其中 text 出现过某个词,则计算该词的 tf-idf 作为特征值。 99 | 100 | 具体做法 101 | 102 | - text preprocessing:去除特殊字符,空格等,然后进行 word的 tokenize; 103 | - preprocessing 后的 words,整理成词汇表; 104 | - 针对text中每个出现在词汇表中的词,计算该词的 tf-idf; 105 | - tf:词频(term frequency,tf)指的是某一个给定的词语在该 text 中出现的频率。这个数字是对词数(term count)的归一化,以防止它偏向长的 text 106 | 107 |
108 | 109 | - 其中分子 nij 表示词 ti 在 textj 中出现的次数,分母表示 textj 所有词出现的次数之和。 110 | - idf:逆向文件频率(inverse document frequency,idf)是一个词语普遍重要性的度量。某一特定词语的 idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以 10 为底的对数得到 111 |
112 | 113 | - 其中分子表示语料库中的 texts 的总数,分母表示出现过词汇 ti 的 texts 的数量。 114 | - tf-idf:tf * idf,tf-idf 倾向于过滤掉常见的词语,保留重要的词语。 115 | - 计算相似性:利用 bag of words + cosine similarity,计算相似性即可。 116 | 117 | **SIF(Smooth Inverse Frequency)** 118 | 119 | 做法 120 | 121 | - 利用预测的词频,计算每个 word 的权重,根据词的权重,加权求得 text 的 embedding,针对多个 texts 组成的矩阵,计算第一个主成分向量,计算每个 text embedding 在该主成分向量上的投影,并减去投影的值,得到最终的 embedding。 122 | 123 | 具体做法 124 | 125 | - 既可以用从海量文本中统计的词频,也可以使用自身应用的 texts,统计每个词的词频。词频是词的出现次数除以所有词出现的总次数。 126 | - 算出 text 的 embedding 之后,针对多个 texts,计算一个主成分向量,然后计算每个 text embedding 在这个主成分的投影,减去投影值,得到最终每个 text 的 embedding。 127 | - https://github.com/PrincetonML/SIF 128 | - 计算相似性:利用 bag of words + cosine similarity,计算相似性即可。 129 | 130 | **WMD(word mover distance)** 131 | 132 | - 直接计算texts之间的similarity,需要利用word embedding。 133 | - 做法:找出 textA 向 textB 迁移的最小花费。 134 | 135 | 具体做法 136 | 137 | - textA和textB表示成 normalized bag of words(nBow),分别为dA,dB,其中 138 | 139 |
140 | 141 | - 计算 textA 和 textB 中每个单词 xi 与 xj 之间的距离 cij 142 | 143 |
144 | 145 | - 其中单词之间的距离是利用 word embedding 的欧氏距离衡量的。 146 | 147 | - WMD 的目标是从 dA 迁移到 dB,其中花费最小,其中 Tij 表示从 dA 中的 wordi 迁移到 dB 中的 wordj 的量,因此问题的数学形式为 148 | 149 |
150 | 151 | - WMD 算法是 earth mover distance 的一个特例,缺点是解法的时间复杂度高。但是可以通过减少一定的下界近似和剪枝的方式加快求解。 152 | 153 | ## 二、深度学习 NLP 154 | 155 | ### 1、词向量发展过程,及相应 papers 156 | 157 | - NNLM:📎2003-NNLM.pdf 158 | - CBOW、Skip-gram:📎skipgram.pdf 159 | - Glove:📎glove.pdf 160 | - ELMO:📎ELMO.pdf 161 | - GPT:📎GPT.pdf 162 | - Bert: 📎BERT Pre-training of Deep Bidirectional Transformers for Language Understanding.pdf 163 | 164 | ### 2、词向量讲解的相关文章 + 博客 165 | 166 | - 从 Word Embedding 到 Bert 模型—自然语言处理中的预训练技术发展史:https://zhuanlan.zhihu.com/p/49271699 167 | 168 | - 语言模型演化历史:从 N-gram 到 BERT。 169 | 170 | - Transformer 图解:http://fancyerii.github.io/2019/03/09/transformer-illustrated/#layernorm 171 | 172 | - Transformer 代码阅读:http://fancyerii.github.io/2019/03/09/transformer-codes/ 173 | 174 | ## 三、视频 + 库 + 书籍 175 | 176 | - stanford cs224n:https://web.stanford.edu/class/cs224n/ 177 | - Allennlp open library:https://allennlp.org/ 178 | - 李宏毅的机器学习中文课程:https://www.youtube.com/channel/UC2ggjtuuWvxrHHHiaDH1dlQ/videos 179 | - NLP town:https://github.com/nlptown/nlp-notebooks 180 | - Snorkel:帮助做弱监督的库 181 | - 传统NLP:统计自然语言处理基础 182 | - NLP实战:Python自然语言处理实战核心技术与算法 183 | 184 | 文中给出了很多链接以及视频资料,**有些是需要 google 才能访问**,对于这部分内容需要认真去看、去消化下。 185 | 186 | ## 四、说明 187 | 188 | 原创文章链接:[算法工程师学习路线(NLP 方向)](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247484978&idx=1&sn=4ad2361454fd613f125a8e77e233c5ea&chksm=fdb6f219cac17b0fd713e1bb9231a6ed569ce3620cc56138e7abada2996f78952addcc54eac6&token=1698861862&lang=zh_CN#rd) 189 | -------------------------------------------------------------------------------- /cs-basics/学习路线指南/算法成神之路.md: -------------------------------------------------------------------------------- 1 | - [一、三个原因](#一三个原因) 2 | - [二、数据结构](#二数据结构) 3 | - [三、资料推荐](#三资料推荐) 4 | - [3.1 数据结构](#31-数据结构) 5 | - [3.2 算法](#32-算法) 6 | - [3.3 隆重推荐](#33-隆重推荐) 7 | - [四、算法之路](#四算法之路) 8 | - [1、](#1) 9 | - [2、](#2) 10 | - [3、](#3) 11 | - [五、强调三点](#五强调三点) 12 | - [六、我想说的](#六我想说的) 13 | - [七、说明](#七说明) 14 | 15 | 随着自己写的越来越多,慢慢的就会有人和我主动交流,现在好多人希望我写一篇考研、就业的选择、零基础如何学习编程,秋招如何选择 offer 等等。 16 | 17 | 我以前写过一篇初入阿里---10 天,我自己还想写一篇在阿里的三个月,将中间的点点滴滴分享给大家,还想写一篇自己的思考、和打法战略,以及你们 99% 的人欠缺的一种能力,还有自己的技术路线的分享,目前是 C 之旅。 18 | 19 | 要写的东西实在太多了,而我目前写公众号的时间,按一周时间计算,不能超过我睁眼时间的 1%,我 99% 的精力在其他地方,希望大家可以理解我,刚入职还需要各方面能力的提升。 20 | 21 | 今天在这里着分享一波:数据结构与算法怎么学,以及今天为什么会写这块,真的是应了大部分读者的要求。 22 | 23 | ## 一、三个原因 24 | 25 | 1、数据结构与算法真的是至关重要,我可是当年在写基础知识的时候,放到了第一位,公众号历史文章都有啊,你们要好好看。 26 | 27 |
28 |

(基础知识)

29 | 30 | 2、不断的有人私聊问我在这方面的学习经验,我觉得是时候给你们分享一波了。 31 | 32 | 3、前一段时间总有人私聊我,给我推荐什么 google 的数据结构与算法课程,让我报名,我都很客气的说了一声:谢谢啊,暂时不需要,还一直说是特别好,一定要报,我之前忙于工作,今天就统一回复一下。 33 | 34 | 不是一两个人私聊我,从半个月前到现在,大概十几个人吧,我真的是醉了,课程好,你自己觉得合适,报名就对了,给我推荐,也没问题,我自己不报,还一直说做活动,便宜,讲的特别好,不报对我是一种巨大的损失之类的话,对于这部分人,我都直接拉黑、删除掉了。 35 | 36 | 好多人我都没回,在这里我说一声,我真的是不需要,**我相信,我应该比绝大部分人检索资料、信息的能力要强,以及接触信息的渠道要多,有些事情,不是我不知道,是我不需要,选择性的过滤了**,有什么好的,我也希望大家多多给我分享,但是不要强人所难。 37 | 38 | 说真的,数据结构与算法,我的水平还算可以吧,给我点时间,准备准备,也是可以讲讲的,我当年在实验室,可是经常的给学第、学妹讲过这方面的课程,自己对其理解也是很深刻的。 39 | 40 | ## 二、数据结构 41 | 42 | 对于我自己来说,秋招中的众多知识点,比如:操作系统、计算机网络、Linux、数据库、C、C++、数据结构、算法、项目之类,我自己最最最擅长的就是数据结构与算法。 43 | 44 | 举个例子:面试官问我,红黑树了解吗? 45 | 46 | 我的回答是:**我会从树-->二叉树-->完全二叉树-->AVL树-->红黑树-->B+/B-/B*树,以及四叉树、八叉树等等;** 47 | 48 | **我先讲为什么需要这种数据结构,出现的背景是什么,解决什么问题,将关于树的整个体系系统都讲出来。** 49 | 50 | 我在秋招的时候,是可以手写 AVL 树、红黑树、B+/B-/B*,图的邻接矩阵、邻接表,最短路径、迪杰斯特拉算法(Dijkstra算法)弗洛伊德算法(Floyd算法)等,所以自己对于数据结构是特别的自信,对于面试官问我,我都是说自己数据结构掌握的还不错,**一定的有自己擅长的技术栈,这才是你与别人不一样的地方,是你自己的优势所在。** 51 | 52 | ## 三、资料推荐 53 | 54 | ### 3.1 数据结构 55 | 56 | **书籍:** 57 | 58 | - <大话数据结构> 新手 59 | - 清华大学严蔚敏的 <数据结构>,C C++版都有 进阶提升 60 | 61 | 这 2 本书都不错,上面的适合新手入门,下面的书籍适合进阶提升; 62 | 63 | **视频:** 64 | 65 | 黑马郝斌的 C 语言、数据结构,我都看过,讲的是真不错,特别适合Linux C/C++ 方向的同学去学习。 66 | 67 | C 语言:https://www.bilibili.com/video/av8074534/?p=180 68 | 69 | 数据结构: 70 | 71 | https://pan.baidu.com/s/1qQrHTdkvxMLSGv7G4nHWBw 72 | 73 | 密码:4o9p 74 | 75 | **说真的,B 站还是有很多的好东西,一定要善于去发掘、去寻找好的资源。** 76 | 77 | ### 3.2 算法 78 | 79 | **书籍:** 80 | 81 | - <啊哈算法>,入门级别学习合适 82 | - <编程之美>、<算法导论>,进阶提升必看 83 | - <剑指offer>,LeetCode 找工作必备,刷至少 2 遍 84 | 85 | **视频:** 86 | 87 | 推荐一个网站:七月算法 88 | 89 | 算法导论: 90 | 91 | https://pan.baidu.com/s/1Bm34-92TwN5TbMOXfPkY6g 92 | 93 | 密码:1i38 94 | 95 | ### 3.3 隆重推荐 96 | 97 | 适合于C/C++ Java Python 任何方向去学习数据结构与算法,我大学期间,学习与找工作,最常去学习的地方。 98 | 99 | **牛客网,左神,应届生找工作的,逛过牛客网的,应该都知道左神的大名吧。** 100 | 101 |
102 |

(左神)

103 | 104 | 在看看下面的课程: 105 | 106 |
107 |

(左神算法课程)

108 | 109 | 左神的一本神书: 110 | 111 | - <程序员代码面试指南:IT名企算法与数据结构题目最优解 左程云著>,Java 写的,有需要的可以买一本学习。 112 | 113 | 我首先说明一下,我没有给任何网站打广告,**我就是把自己当年走过的路,自己通过什么资料,什么视频,在什么网站进行学习,真实的分享给大家**,有用的,你们借鉴,没用的,觉得我这个方法过时了,完全可以不必理会的。 114 | 115 | 网址:https://www.nowcoder.com/courses/semester/algorithm-elementary 116 | 117 | ## 四、算法之路 118 | 119 | **三步走战略:看视频 + 看书 + 刷算法** 120 | 121 | ### 1、 122 | 123 | 我是在大二的下半学期开始接触的数据结构,我一开始的学习,是看书理解里面的简单逻辑,和听视频的讲解,也是边摸索边进行学习,对于那时候的自己,完全是小白水平。 124 | 125 | 大二的下学期,可以说是在找学习编程的感觉,让自己激发兴趣,兴趣是最好的老师,**一定的让自己喜欢上数据结构与算法**,实现了什么数据结构或者做出了哪道算法,会对自己是一个正向的激励,会让自己有更大的兴趣,去解决更难的问题,记住:**在什么阶段做什么难度的题。** 126 | 127 | 不要光刷题,一直想不出来,是很痛苦的一件事情,**要学会用数据结构或者算法去解决项目中的实际问题,去做优化与改进**,这块在大三的时候,结合着来,我不建议,太有针对性的去刷题。 128 | 129 | ### 2、 130 | 131 | 大三的上学期以及寒假,是我主要学习数据结构与算法的大半年时间,在这个阶段,我逐渐脱离了视频(视频适合初级阶段,适合于大二学习),对于数据结构与算法,学到后期,必须的靠自己,不能在一味的依赖于视频中的讲解。 132 | 133 | 我是这样的,通过看书,来实现一些数据结构,以及开始有针对性的提高自己的算法能力,数据结构,来回就那些东西,只要理清了之间的逻辑,思路清晰,反复的去实现几遍就好,难度相对于算法还是简单一些,数据结构,关键是理解数据与数据之间的存储关系,多做笔记,整理,疏通关系。 134 | 135 | 算法,我觉得是挺有难度的,挺考验人的智商的,因为算法的实现思路,很奇特,刷过算法的,就懂,有些思路是取巧,有些是剑走偏锋,根本想不到,只能的先去看别人的思想,理解好,在实现出来。 136 | 137 | 经常看别人的思路,不要觉得很丢人,这是正常的,不会了,实在想不出来了,就去看别人的实现思路,**对于同一个问题,用不同的算法实现,带来的可是本质的区别,一定要有对时间复杂度有着极致的追求,去寻找最完美的解决方法,多思考,多花时间去理解清楚。** 138 | 139 | ### 3、 140 | 141 | **我当时,是拿小本本,对于数据结构和算法中,不清晰的地方,拿本子画清楚,不要光想,一定要动手去画,想明白了,理清了各种逻辑,代码的实现是很容易的,关键就是担心没思路,脑子是乱的。** 142 | 143 | 当时自己的时间安排,就是每天都会抽时间去学会数据结构,做几道算法题,去 leetcode 或者牛客网上面,从最简单的题刷起,说白了,**这个就在于坚持,和自己有没有决心去学好。** 144 | 145 | **快找工作的时候,是必须要刷一波算法题的,刷的时间久了,你会慢慢的爱上它的,很有趣,很奇妙的感觉,以及带给自己莫名的快感,慢慢的你就会刷上瘾了,着迷其中。** 146 | 147 | ## 五、强调三点 148 | 149 | 1. 需要明确一下:数据结构、算法需要掌握哪些知识点,这块你翻看书的目录,以及看一些课程大纲都有写到,那块会很详细的有说明。 150 | 151 | 数据结构:链表、栈、队列、字符串、矩阵、树、图 152 | 153 | 算法:排序、字符串、数组、递归、五大算法(动态规划、贪心。。。) 154 | 155 | 2. 对于数据结构与算法的实现,不要纠结于C、C++、java、python、语言是其次,关键是实现的细节以及方法,选一门自己喜欢的语言,去学习数据结构与算法就好; 156 | 157 | 3. 书、视频,我都已经推荐过了,对于小白的话,建议先看看视频,理解理解,多听听别人思路,看看是怎么解题的,初步阶段,一定要选择简单的、自己能很快理解的去学习,由浅入深,慢慢的给自己信心; 158 | 159 | ## 六、我想说的 160 | 161 | **算法的学习,别人帮不了你多少,主要还是的靠自己悟,靠自己花时间去理解,师傅领进门,修行在个人,算法讨论,思路分享,去牛客网看看,各路大神,各种解决思路,你一定会有进步的。** 162 | 163 | **一开始,学习数据结构与算法,是枯燥的,是乏味的,因为你还不够了解到它的魅力,但是时间久了,你真的会爱上它,离不开它,与你血肉相连,伴你编程终生,在以后的学习道路中(不仅仅是技术方面),都会潜移默化的对你产生影响。** 164 | 165 | **数据结构与算法,给我带来的是,逻辑缜密性的提升,对我的性格、做人都产生了影响,我是强烈的建议,大家一定的好好学习,悟出自己的学习之道,那么你的路将会走的更远,更久。** 166 | 167 | 10 月 1 号,休整了一天,现在的我在回家的路上,各位,假期快乐! 168 | 169 | ## 七、说明 170 | 171 | 原创文章链接:[算法成神之路](https://mp.weixin.qq.com/s?__biz=MzU4MjQ3NzEyNA==&mid=2247483872&idx=1&sn=3c6af181bfe4e9471c7052bdb09006a6&chksm=fdb6f5cbcac17cdd5420bc21948d49b9bfe8d43cada0306d587f3a5dfa88fe0a6c27766231ef&token=1469515448&lang=zh_CN#rd) 172 | --------------------------------------------------------------------------------