├── .gitignore ├── 2015_bishi ├── README.md ├── baidu_bishi.md ├── chuangxin.md ├── hengshengdianzi_bishi.md ├── lifangwang_bishi.md ├── mogujie_bishi.md ├── pptv_bishi.md ├── qingting_bishi.md ├── qunshuo_bishi.md ├── shenxinfu_bishi.md ├── trendmicro_bishi.md └── xiecheng_bishi.md ├── 2015_interview ├── README.md ├── alibaba.md ├── chuangxin.md ├── sougou.md └── tencent.md ├── LeetCode ├── 195_tenth_line.md ├── add_binary.cpp ├── anagrams.cpp ├── balanced_binary_tree.cpp ├── binary_tree_inorder_traversal.cpp ├── binary_tree_level_order_II.cpp ├── binary_tree_maximum_path_sum.cpp ├── binary_tree_preorder_postorder_traversal.cpp ├── binary_tree_zigzag_level_order_traversal.cpp ├── btree_from_inorder_and_postorder.cpp ├── btree_from_preorder_and_inorder.cpp ├── count_and_say.cpp ├── decode_ways.cpp ├── evaluate_reverse_polish_notation.cpp ├── flatten_binary_tree_to_linked_list.cpp ├── generate_parentheses.cpp ├── gray_code.cpp ├── important ├── insert_interval.cpp ├── integer_to_roman.cpp ├── k_sum.cpp ├── length_last_word.cpp ├── letter_combinations_phone_number.cpp ├── linked_list_cycle.cpp ├── longest_common_prifix.cpp ├── longest_consecutive_sequence.cpp ├── longest_substring_without_repeating_characters.cpp ├── max_depth_btree.c ├── maximum_subarray.c ├── merge_intervals.cpp ├── merge_two_sorted_lists.c ├── minimum_depth_binary_tree.cpp ├── minimum_path_sum.cpp ├── n_queens.cpp ├── next_permutation.cpp ├── next_right_pointers_each_node.c ├── partition_list.cpp ├── pascal_triangle.cpp ├── pascal_triangle_II.cpp ├── permutation_sequence.cpp ├── permutations.cpp ├── plus_one.cpp ├── remove_duplicates_from_sorted_list_II.cpp ├── restore_ip_address.cpp ├── reverse_integer.c ├── reverse_linked_list_II.cpp ├── reverse_words_in_string.cpp ├── roman_to_integer.cpp ├── rotate_image.cpp ├── rotate_list.cpp ├── same_tree.c ├── search_2D_matrix.cpp ├── set_matrix_zeroes.cpp ├── single_number.c ├── single_number_II.cpp ├── sort_colors.cpp ├── sort_list.cpp ├── spiral_matrix.cpp ├── spiral_matrix_II.cpp ├── string_to_integer.cpp ├── subsets.cpp ├── sudoku_solver.cpp ├── sudoku_solver2.cpp ├── sudoku_solver3.cpp ├── sum_root_to_leaf_numbers.cpp ├── template.cpp ├── three_sum.cpp ├── three_sum_closest.cpp ├── trapping_rain_water.cpp ├── triangle.cpp ├── two_sum.c ├── two_sum.cpp ├── unique_binary_search_trees.cpp ├── valid_parentheses.cpp ├── valid_sudoku.cpp ├── word_break.cpp └── word_break_II.cpp ├── ProjectEuler ├── 1_Euler.c ├── 2_Euler.c ├── 3_Euler.c ├── 4_Euler.c └── 5_Euler.c ├── README.md ├── apue ├── 10_chapter │ ├── 10.10_4_5.c │ ├── 10_1.c │ ├── 10_10.c │ ├── 10_11.c │ ├── 10_12_13.c │ └── 10_2.c ├── 11_chapter │ ├── 11.4_1.c │ ├── 11.5_1.c │ ├── 11.5_2.c │ ├── 11_4.c │ ├── 11_5.c │ ├── 11_8.c │ ├── 11_9.c │ └── 11_exercise_3.c ├── 12_chapter │ ├── 12_1.c │ ├── 12_2.c │ ├── 12_3&12_4.c │ ├── 12_5.c │ ├── 12_6.c │ └── 12_7.c ├── 13_chapter │ ├── 10.16_3.c │ ├── 13_1_daemonize.c │ └── 13_2.c ├── 14_chapter │ ├── 14.5_epoll.c │ ├── 14.5_select.c │ ├── 14_1.c │ ├── 14_11.c │ ├── 14_12.c │ ├── C_14.c │ ├── client.c │ ├── epoll.md │ └── server_poll.c ├── 15_chapter │ ├── 15_1.c │ ├── 15_11.c │ ├── 15_2.c │ ├── 15_3.c │ ├── 15_4.c │ ├── 15_6.c │ └── 15_7.c ├── 16_chapter │ ├── 16_exercise4_tcp_server.c │ ├── 16_exercise_1.c │ ├── 16_exercise_2.c │ ├── 16_exercise_4_client.c │ ├── 16_exercise_4_server.c │ ├── 16_exercise_4_tcp_client.c │ └── 16_exercise_4_tcp_server.c ├── 3_chapter │ ├── 3.9_55.cpp │ └── 3_exercise_2.c ├── 6_chapter │ └── 6.2.c ├── 8_chapter │ ├── 8.13.c │ ├── 8.16.c │ ├── 8.3_1.c │ ├── 8_ex_2.c │ └── 8_ex_6.c ├── 9_chapter │ ├── 9_1.c │ └── 9_exercise_2.c ├── README.md ├── network │ └── poll.md ├── reentrant&signal.txt ├── rpc │ ├── echo │ │ ├── Makefile │ │ ├── client.c │ │ ├── echo.h │ │ ├── echo.x │ │ ├── echo_clnt.c │ │ ├── echo_svc.c │ │ ├── echo_xdr.c │ │ └── server_func.c │ └── square │ │ ├── README.md │ │ ├── client.c │ │ ├── server.c │ │ ├── square.h │ │ ├── square.x │ │ ├── square_clnt.c │ │ ├── square_svc.c │ │ └── square_xdr.c └── threadpool │ ├── Makefile │ ├── test_threadpool.c │ ├── threadpool.c │ ├── threadpool.h │ └── threadpool.txt ├── bop ├── 2.16.md ├── 2.19.md ├── 3.1.md ├── 3.10.md ├── 3.11.md ├── 3.3.md ├── 3.6.md ├── 3.7.md ├── 3.8.md ├── 3.9.md └── README.md ├── config git ├── cpp_primer ├── auto_ptr.cpp ├── chapter10_textquery.cpp ├── chapter15_handle.cpp ├── chapter15_textquery.cpp ├── more_effective_cpp │ ├── auto_ptr.cpp │ └── smart_ptr.txt └── vector_test.cpp ├── crack_coding └── README.md ├── data_struct ├── sort │ ├── README.md │ ├── bubble_sort.cpp │ ├── heap_sort.cpp │ ├── insert_sort.cpp │ ├── merge_sort.cpp │ ├── quick_sort.cpp │ ├── select_sort.cpp │ └── shell_sort.cpp └── vector │ └── vector.h ├── graduate └── paper.md ├── hdu_oj ├── 1003_max_sum.cpp └── hdu_oj_categories ├── hihocoder ├── 1.md ├── 2.md ├── 3.md ├── 4.md └── README.md ├── interviewOffer ├── 1.md ├── 10.md ├── 11.md ├── 12.md ├── 13.md ├── 14.md ├── 15.md ├── 16.md ├── 17.md ├── 18.md ├── 19.md ├── 2.md ├── 20.md ├── 21.md ├── 22.md ├── 23.md ├── 24.md ├── 25.md ├── 26.md ├── 27.md ├── 28.md ├── 29.md ├── 3.md ├── 30.md ├── 31.md ├── 32.md ├── 33.md ├── 34.md ├── 35.md ├── 36.md ├── 37.md ├── 38.md ├── 39.md ├── 4.md ├── 40.md ├── 41.md ├── 42.md ├── 43.md ├── 44.md ├── 45.md ├── 46.md ├── 47.md ├── 48.md ├── 5.md ├── 6.md ├── 7.md ├── 8.md ├── 9.md └── README.md ├── intro_algorithm ├── Binary_Tree │ ├── avl.cpp │ ├── bst.cpp │ └── rbt.cpp ├── Graph │ ├── graph_bfs.cpp │ └── graph_dfs.cpp ├── LCS.cpp └── kmp.cpp ├── jobdu_oj ├── 1006_zoj.cpp └── 1023_excel_sort.cpp ├── july_100 ├── 11.cpp ├── 15.cpp ├── 25.cpp ├── 29.cpp ├── 4.cpp ├── 51.md ├── 52.md ├── 9.cpp ├── README.md └── btree.hpp ├── misc ├── bisearch.cpp ├── calendar.cpp ├── longest_palindromic_substring.c ├── metrix.c ├── move_all_zeroes_end.c ├── once_in_array.cpp └── runtime_duration.c ├── myalgo ├── README.md ├── about_test.md ├── automake_help.md ├── bdb_operation.md ├── diff_patch.md ├── fdisk_mkfs.md ├── fopen_error.md ├── get_arguments_from_cmd.md ├── hadoop_wordcount.md ├── java_run.md ├── linux_limits.md ├── nonrecursion_traversal.md ├── permutation.md ├── pics │ ├── about_test.png │ ├── about_test_1.png │ ├── about_test_2.png │ ├── about_test_3.png │ ├── about_test_4.png │ ├── about_test_5.png │ ├── about_test_6.png │ ├── about_test_7.png │ ├── fdisk_p.png │ ├── pic1.png │ └── sublime_layout.png ├── qsort_sort.md ├── rpc_example.md ├── sublime_plugins.md └── vim_color.md ├── project ├── capfs_client.txt └── losf.txt ├── sgi_stl ├── 1.8.3.cpp ├── 1.9.3.cpp ├── 1.9.4.cpp ├── 1.9.6.cpp ├── 1config.cpp ├── 2chapter │ ├── 2.1.1.cpp │ └── 2.1.1.hpp └── 4chapter │ └── 4.4.5.cpp ├── simple_markdown.md ├── skill.md ├── sort ├── bubble_sort.c ├── heap_sort.c ├── insert_sort.c ├── merge_sort.c ├── quick_sort.c ├── select_sort.c └── shell_sort.c ├── stack ├── stack.c ├── stack.h ├── status.h ├── template.c └── test.c ├── summary ├── 2016.md └── README.md ├── sys_install.md └── tcpl ├── README.md ├── heap_stack_object.md ├── object_oriented_features.md └── reserve_resize.md /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.[ao] 3 | a.out 4 | -------------------------------------------------------------------------------- /2015_bishi/README.md: -------------------------------------------------------------------------------- 1 | ## 2015年校园招聘笔试题 2 | 3 | [回到主目录](https://github.com/luofengmacheng/algorithms) 4 | 5 | 1 [创新工厂(2014/9/10)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/chuangxin.md) 6 | 7 | 2 [倾听(2014/9/15)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/qingting_bishi.md) 8 | 9 | 3 [百度(2014/9/21)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/baidu_bishi.md) 10 | 11 | 4 [趋势科技(2014/9/23)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/trendmicro_bishi.md) 12 | 13 | 5 [携程旅行网(2014/9/24)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/xiecheng_bishi.md) 14 | 15 | 6 [群硕(2014/10/8)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/qunshuo_bishi.md) 16 | 17 | 7 [立方网(2014/10/9)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/lifangwang_bishi.md) 18 | 19 | 8 [PPTV聚力(2014/10/9)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/pptv_bishi.md) 20 | 21 | 9 [恒生电子(2014/10/11)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/hengshengdianzi_bishi.md) 22 | 23 | 10 [蘑菇街(2014/10/11)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/mogujie_bishi.md) 24 | 25 | 11 [深信服(2014/10/12)](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/shenxinfu_bishi.md) 26 | 27 | -------------------------------------------------------------------------------- /2015_bishi/baidu_bishi.md: -------------------------------------------------------------------------------- 1 | ## 百度(笔试[武汉]2014/9/21) 2 | 3 | 1.1 写出六种排序算法,并给出它们的时间复杂度和稳定性。 4 | 5 | 1.2 多线程中的同步互斥方法有哪些。 6 | 7 | 1.3 进程通信有哪些方式,哪种是效率最高的。 8 | 9 | 2.1 找出二叉树中最低公共父节点 10 | 11 | 2.2 删除链表中重复的元素,只剩下出现一次的元素。 12 | 13 | 2.3 判断一棵二叉树是不是平衡二叉树。 -------------------------------------------------------------------------------- /2015_bishi/lifangwang_bishi.md: -------------------------------------------------------------------------------- 1 | ## 立方网(笔试[武汉]2014/10/9) 2 | 3 | 1 汉诺塔问题。有三根柱子,第一个柱子上有5个圆盘,现在要将这五个圆盘移动到第二根柱子上去,要求在移动的过程中可以借助第二根和第三根柱子,但是必须小的圆盘在大的圆盘上面,请问最少需要多少步。 4 | 5 | 下面是汉诺塔问题的代码: 6 | 7 | ``` C++ 8 | void hanoi(int n, char src, char pass, char dst) 9 | { 10 | if(n == 1) { 11 | cout << "move " << n << " from " << src << " to " << dst << endl; 12 | return; 13 | } 14 | 15 | hanoi(n-1, src, dst, pass); 16 | cout << "move " << n << " from " << src << " to " << dst << endl; 17 | hanoi(n-1, pass, src, dst); 18 | } 19 | ``` 20 | 21 | 题目只要求求最少步数,因此有f(5) = 2 * f(4) + 1 = 4 * f(3) + 3 = 8 * f(2) + 7 = 16 * f(1) + 15 = 31。 22 | 23 | 2 加油站问题。一个小猴子边上有100根香蕉,它要走过50米才能到家,每次它最多搬50根,每走1米就要吃掉一根,请问它最多能把多少根香蕉搬到家里。 24 | 25 | 3 四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2,线程3的功能就是输出3,线程4的功能就是输出4。现有四个文件ABCD。初始都为空。现要让四个文件内容如下格式: 26 | 27 | A:1 2 3 4 1 2 ... 28 | 29 | A:2 3 4 1 2 3... 30 | 31 | A:3 4 1 2 3 4... 32 | 33 | A:4 1 2 3 4 1... -------------------------------------------------------------------------------- /2015_bishi/mogujie_bishi.md: -------------------------------------------------------------------------------- 1 | ## 蘑菇街(笔试[武汉]2014/10/11) 2 | 3 | 1 逆波兰表示是一种数学表达式方式,所有操作符都置于操作数后面,因此也被称为后缀表示法。编程实现一个函数,能够计算逆波兰表示法表示的字符串,操作数只限于小于100的正整数,操作符只限于加、减、乘、除。 4 | 5 | ``` C++ 6 | int op(int op1, int op2, char oper) 7 | { 8 | switch(oper) { 9 | case '+': 10 | return op1 + op2; 11 | case '-': 12 | return op1 - op2; 13 | case '*': 14 | return op1 * op2; 15 | case '/': 16 | return op1 / op2; 17 | default: 18 | break; 19 | } 20 | } 21 | 22 | int compute(const string &str) 23 | { 24 | stack sta; 25 | bool flag = false; 26 | int data = 0; 27 | 28 | for(size_t i = 0; i < str.size(); ++i) { 29 | if(isdigit(str[i])) { 30 | if(flag) { 31 | data = data * 10 + str[i] - '0'; 32 | } 33 | else { 34 | data = str[i] - '0'; 35 | flag = true; 36 | } 37 | } 38 | else if(isspace(str[i])) { 39 | if(flag) { 40 | sta.push(data); 41 | flag = false; 42 | } 43 | } 44 | else if(str[i] == '+' || 45 | str[i] == '-' || 46 | str[i] == '*' || 47 | str[i] == '/') { 48 | int op2 = sta.top(); 49 | sta.pop(); 50 | int op1 = sta.top(); 51 | sta.pop(); 52 | sta.push(op(op1, op2, str[i])); 53 | } 54 | } 55 | return sta.top(); 56 | } 57 | ``` 58 | 59 | 2 有两个较长的单向链表A和B,为了找出节点node,满足node in A且node in B,请设计空间复杂度尽量小的算法,并且编程实现。 -------------------------------------------------------------------------------- /2015_bishi/pptv_bishi.md: -------------------------------------------------------------------------------- 1 | ## PPTV聚力(笔试[武汉]2014/10/9) 2 | 3 | 1 最大子段和。数组A[]保存的整数有正有负,求其中的某个序列A[i]~A[j]的和最大,求出这个最大的和。 4 | 5 | ``` C++ 6 | int max_sum(int A[], size_t size) 7 | { 8 | if(A == NULL || size <= 0) { 9 | throw string("invalid array"); 10 | } 11 | 12 | int max_s = numeric_limits::min(), sum = 0; 13 | 14 | for(size_t i = 0; i < size; ++i) { 15 | if(sum >= 0) { 16 | sum += A[i]; 17 | } 18 | else { 19 | sum = A[i]; 20 | } 21 | 22 | if(sum > max_s) { 23 | max_s = sum; 24 | } 25 | } 26 | 27 | return max_s; 28 | } 29 | ``` 30 | 31 | 2 栈。给定一个整数n,表示入栈顺序是[1, 2, ..., n],给定一个出栈序列B[],判断出栈序列是否是入栈序列的合法序列。 32 | 33 | ``` C++ 34 | bool is_pop_seq(int n, int B[]) 35 | { 36 | stack sta; 37 | int i = 1, j = 0; 38 | 39 | while(i <= n && j < n) { 40 | while(i <= n && (sta.empty() || sta.top() != B[j])) { 41 | sta.push(i++); 42 | } 43 | 44 | if(!sta.empty() && sta.top() == B[j]) { 45 | sta.pop(); 46 | ++j; 47 | } 48 | } 49 | 50 | if(i == n + 1 && j == n && sta.empty()) { 51 | return true; 52 | } 53 | return false; 54 | } 55 | ``` 56 | 57 | 3 海量数据处理。有海量的日志数据,查找某天访问的次数最多的IP。(系统内存为2GB) 58 | 59 | 获取当天的日志数据。对IP进行哈希,映射到1000个小文件中,统计每个小文件中次数最多的IP,然后在这1000个次数最多的IP中选择最多次数的IP。进行映射时,每个小文件的大小小于2GB,如果映射时,某个文件的大小大于2GB,就再对这个文件进行映射,使得每个文件大小都小于2GB。 -------------------------------------------------------------------------------- /2015_bishi/qingting_bishi.md: -------------------------------------------------------------------------------- 1 | ## 蜻蜓FM(笔试[武汉]2014/9/15) 2 | 3 | ### 1 求复杂度 4 | 5 | 求下面函数的时间复杂度 6 | 7 | ``` C 8 | int f(unsigned int n) 9 | { 10 | if(n <= 0) 11 | return 0; 12 | 13 | if(n == 1) 14 | return 1; 15 | 16 | return 5 * f(n - 1) - 7 * f(n - 2); 17 | } 18 | ``` 19 | 20 | 解答: 21 | 22 | 通过上式,可以知道: 23 | 24 | 当n <= 1时,T(n) = O(1); 25 | 26 | 当n > 1 时,T(n) = 5 * T(n - 1) + 7 * T(n - 2) + O(1); 27 | 28 | 因此,有 29 | 30 | ![](递归式图片) 31 | 32 | 由上图可以知道: 33 | 34 | ``` 35 | T(n) = O(1) + 12 * O(1) + 12 ^ 2 * O(1) + 12 ^ 3 * O(1) + ... 36 | T(n) = 12 ^ n * O(1) 37 | ``` 38 | 39 | 因此T(n) = O(12 ^ n) 40 | 41 | ### 2 编程题 42 | 43 | 2.1 已知无序数组A[N],其中N是一个很大的正整数,但不超出整型范围,数组元素值的范围是[0, N-1]。请找出A中任意一个值重复的元素,若不存在重复,则返回-1。要求空间复杂度为O(1)。(如3, 2, 4, 0, 2, 3...,输出2或3均正确) 44 | 45 | 2.2 假设我们提供某种脚本语言MS,它只支持int数据类型但是不支持负数。它只支持如下运算: 46 | 47 | ``` 48 | (1) 清零:X = 0; 49 | (2) 变量赋值:X1 = X2; 50 | (3) 嵌套循环: 51 | Loop(X1) 52 | ... 53 | Loop(X2) 54 | ... 55 | END 56 | END 57 | ``` 58 | 59 | 请注意: 60 | 1 常量不能出现“0”以外的数字。 61 | 2 该脚本不支持任何比较运算或if语句。 62 | 63 | 如下程序循环执行了两次: 64 | 65 | ``` 66 | X = 0; 67 | X++; 68 | X++; 69 | Loop(x) 70 | X = 0; 71 | END 72 | ``` 73 | 74 | (1) 请用该脚本实现功能X = X -1; 75 | (2) 如果已经实现(1),请实现功能X1 = X1 - X2,若X1 < X2,执行完后X1 = 0;(可利用已经实现的功能) 76 | (3) 如果已经实现(3),请实现功能X3 = X1 / X2,若X1 < X2,执行完后X3 = 0,不需要考虑X2= 0的情况。(可利用已经实现的功能) -------------------------------------------------------------------------------- /2015_interview/README.md: -------------------------------------------------------------------------------- 1 | ## 2015年校园招聘面试题 2 | 3 | [回到主目录](https://github.com/luofengmacheng/algorithms) 4 | 5 | 1 [创新工厂(2014/9/11)](https://github.com/luofengmacheng/algorithms/blob/master/2015_interview/chuangxin.md) 6 | 7 | 2 [阿里巴巴(2014/9/12)](https://github.com/luofengmacheng/algorithms/blob/master/2015_interview/alibaba.md) 8 | 9 | 3 [腾讯(2014/9/16)](https://github.com/luofengmacheng/algorithms/blob/master/2015_interview/tencent.md) 10 | 11 | 4 [搜狗(2014/9/25)](https://github.com/luofengmacheng/algorithms/blob/master/2015_interview/sougou.md) 12 | -------------------------------------------------------------------------------- /2015_interview/alibaba.md: -------------------------------------------------------------------------------- 1 | ## 阿里巴巴一面(挂掉)2014/9/12 2 | 3 | > 给定一个存储数字的数组,将数组按照频度排序,相同频度的数字按照第一个出现的相对顺序进行排序。 4 | 5 | 基本思想:pair保存某个数字和它的频度,用一个顺序容器vector保存这些数字和它们的频度。依次访问数组中的元素,访问到某个元素时,在vector中查找该元素是否存在,如果存在,频度自增,如果不存在,就将该数字和频度1放到vector中。然后按照频度进行稳定的排序。再将数字部分输出到结果数组中即可。 6 | 7 | ``` C++ 8 | struct cnt_comp { 9 | bool operator()(pair p1, pair p2) 10 | { 11 | return p1.second > p2.second; 12 | } 13 | }; 14 | 15 | void cnt_sort(vector &num, vector &res) 16 | { 17 | vector > mp; 18 | 19 | for(vector::iterator viter = num.begin(); 20 | viter != num.end(); ++viter) { 21 | vector >::iterator iter; 22 | for(iter = mp.begin(); iter != mp.end(); ++iter) { 23 | if(*viter == (iter->first)) { 24 | iter->second++; 25 | break; 26 | } 27 | } 28 | 29 | if(iter == mp.end()) { 30 | mp.push_back(make_pair(*viter, 1)); 31 | } 32 | } 33 | 34 | stable_sort(mp.begin(), mp.end(), cnt_comp()); 35 | 36 | for(vector >::iterator iter = mp.begin(); 37 | iter != mp.end(); ++iter) { 38 | res.push_back(iter->first); 39 | } 40 | } 41 | ``` 42 | 43 | 备注: 44 | 45 | 面试问到的其它问题: 46 | 47 | 1 如何查看CPU的负载? 48 | 49 | 2 如何使用tcpdump打印某个时间段的数据包? 50 | 51 | 3 如果让你设计一个购物网站,你如何做? 52 | 53 | 同学面试问到的问题: 54 | 55 | 1 top命令的作用? 56 | 57 | 2 如何杀死一个进程?kill命令的3和9的作用? 58 | 59 | 3 当在浏览器中输入域名后发生了什么? 60 | 61 | 4 HTTP中404是什么意思?重定向是什么意思? 62 | 63 | 5 mysql中有两种存储引擎,它们的优缺点和应用场景?视图和触发器? 64 | 65 | 6 如何保证网站的安全? 66 | 67 | 7 如何查看系统负载?load的三个参数的意义? 68 | 69 | 8 三个线程,一个线程必须等待其它两个线程结束? 70 | 71 | 9 C++中静态函数可以是虚函数吗? -------------------------------------------------------------------------------- /2015_interview/chuangxin.md: -------------------------------------------------------------------------------- 1 | ## 创新工场一面(挂掉)2014/9/11 2 | 3 | > 二维数组arr[m][m]表示一个棋盘,在该棋盘中设定起点arr[a][b]和终点arr[c][d],求棋子从起点到终点的最小步数,并且棋子只能走日(如象棋中的马)。 -------------------------------------------------------------------------------- /LeetCode/195_tenth_line.md: -------------------------------------------------------------------------------- 1 | ## 195 第十行 2 | 3 | ### 1 问题描述 4 | 5 | 文件file.txt有一些文本,需要写一个脚本获取这个文本的第十行。 6 | 7 | ### 2 方案1(head&tail) 8 | 9 | 个人想到的最简单的方法就是:先获取开始的十行,然后再获取最后一行: 10 | 11 | ``` shell 12 | head -n 10 file.txt | tail -n 1 13 | ``` 14 | 15 | 提交后发现结果不对,根据提示上面的命令在文件行数少于10行时结果不对。因此,正确的思路应该是,先打印开始十行及以上的行,然后再获取第一行: 16 | 17 | ``` shell 18 | tail -n +10 file.txt | head -n 1 19 | ``` 20 | 21 | 这里用到了tail的-n参数的另一种含义: 22 | 23 | 当-n参数后面是+k时,则从第k行打印到文件末尾。 24 | 25 | 同样,head也有类似的含义: 26 | 27 | 当-n后面参数是-k时,则打印除最后k行以外的行。 28 | 29 | ### 3 方案2(sed) 30 | 31 | ``` shell 32 | sed -n 10p file.txt 33 | ``` 34 | 35 | ### 4 方案3(awk) 36 | 37 | ``` shell 38 | awk 'NR==10' file.txt 39 | ``` 40 | -------------------------------------------------------------------------------- /LeetCode/binary_tree_preorder_postorder_traversal.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/LeetCode/binary_tree_preorder_postorder_traversal.cpp -------------------------------------------------------------------------------- /LeetCode/decode_ways.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/27 4 | * source: LeetCode OJ 5 | * title: Decode Ways 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | class Solution { 16 | public: 17 | int numDecodings(string s) 18 | { 19 | if(s.size() == 0) { 20 | return 0; 21 | } 22 | 23 | vector num; 24 | num.resize(s.size()); 25 | 26 | size_t i = 0; 27 | for(i = 0; i < s.size(); ++i) { 28 | if(s[i] < '0' || s[i] > '9') { 29 | num[i] = 0; 30 | return 0; 31 | } 32 | if(i == 0) { 33 | if(s[i] == '0') { 34 | num[i] = 0; 35 | return 0; 36 | } 37 | else { 38 | num[i] = 1; 39 | } 40 | continue; 41 | } 42 | if(s[i] == '0') { 43 | if(s[i-1] == '1' || s[i-1] == '2') { 44 | num[i] = (i >= 2 ? num[i-2] : 1); 45 | } 46 | else { 47 | num[i] = 0; 48 | return 0; 49 | } 50 | } 51 | else { 52 | if(s[i-1] == '1' || s[i-1] == '2' && s[i] >= '1' && s[i] <= '6') { 53 | num[i] = (i >= 2 ? num[i-2] : 1) + num[i-1]; 54 | } 55 | else { 56 | num[i] = num[i-1]; 57 | } 58 | } 59 | } 60 | 61 | return num[i-1]; 62 | } 63 | }; 64 | 65 | int main(int argc, const char *argv[]) 66 | { 67 | string str("110"); 68 | Solution sol; 69 | cout << sol.numDecodings(str) << endl; 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /LeetCode/generate_parentheses.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/LeetCode/generate_parentheses.cpp -------------------------------------------------------------------------------- /LeetCode/gray_code.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/24 4 | * source: LeetCode OJ 5 | * title: Gray Code 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | class Solution { 15 | public: 16 | vector grayCode1(int n) 17 | { 18 | vector vec; 19 | 20 | if(n == 0) { 21 | vec.push_back(0); 22 | return vec; 23 | } 24 | 25 | vec = grayCode(n-1); 26 | int size = vec.size(); 27 | int i = 0; 28 | for(i = size-1; i >= 0; i--) { 29 | vec.push_back(vec.at(i) | (1<<(n-1))); 30 | } 31 | 32 | return vec; 33 | } 34 | 35 | vector grayCode(int n) 36 | { 37 | vector vec; 38 | 39 | if(n == 0) 40 | return vector(0); 41 | 42 | if(n == 1) { 43 | vec.push_back(0); 44 | vec.push_back(1); 45 | return vec; 46 | } 47 | 48 | vec = grayCode(n-1); 49 | vector::iterator iter; 50 | for(iter = vec.begin(); iter != vec.end(); ++iter) { 51 | (*iter) <<= 1; 52 | } 53 | 54 | int i = 0; 55 | int size = vec.size(); 56 | for(i = size-1; i >= 0; i--) { 57 | vec.push_back(vec.at(i)+1); 58 | } 59 | return vec; 60 | } 61 | }; 62 | 63 | int main(int argc, char *argv[]) 64 | { 65 | vector ivec; 66 | Solution sol; 67 | ivec = sol.grayCode1(3); 68 | int i = 0; 69 | for(i = 0; i < ivec.size(); i++) 70 | cout<321,在提示中说要考虑翻转后溢出的问题,但是,在提交代码的时候却不需要。 4 | 5 | 2 Best Time to Buy and Sell Stock II 要求买卖股票的最大收益,不过题目的意思还是不太明白 6 | 7 | 3 Unique Binary Search Trees 8 | 9 | 4 Populating Next Right Pointers in Each Node 10 | 最简单的办法是用队列进行层次遍历,但是这样队列需要很大的存储空间,因此,在该树是完全二叉树时,可以用两个指针进行遍历,一个指针从第一个节点开始,每次都取左孩子,另一个指针从之前的指针的孩子开始,遍历该层节点 11 | 12 | 5 Climbing Stairs 13 | 14 | 6 Maximum Subarray 15 | 最大子段和,最简单的方法是计算任意区间的和,并与最大和进行比较;第二种方法是分治法,即二分法;第三种方法是动态规划 16 | 17 | 7 Convert Sorted Array to Binary Search Tree 18 | 要求是得到高度平衡的二叉搜索树,于是,每次从中间分开,左边是左子树,右边是右子数 19 | 20 | 8 Symmetric Tree 21 | 对称树,判断一棵树是否是对称的 22 | 23 | 9 Maximum Subarray 24 | Manacher's algorithm 25 | 26 | 10 Binary Tree Inorder Traversal 27 | 二叉树的非递归中序遍历 28 | 29 | 11 Gray Code 30 | 格雷码 31 | 32 | 12 Permutations 33 | 全排列 34 | 35 | 13 Container With Most Water 36 | 贪心算法 37 | 38 | 14 Minimum Path Sum 39 | 40 | 15 Unique Paths 41 | 42 | 16 Single Number II 43 | 44 | 17 Generate Parentheses 45 | 46 | 18 Remove Nth Node From End of List 47 | -------------------------------------------------------------------------------- /LeetCode/k_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/13 4 | * source: LeetCode 5 | * title: K sum 6 | * reference: http://tech-wonderland.net/blog/summary-of-ksum-problems.html 7 | * language: C++ 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class Solution { 16 | public: 17 | vector > findZeroSumInSortedArr(vector num, int begin, int count, int target) 18 | { 19 | vector > ret; 20 | vector tuple; 21 | set visited; 22 | if(count == 2) { 23 | int i = begin, j = num.size() - 1; 24 | while(i < j) { 25 | int sum = num[i] + num[j]; 26 | if(sum == target && visited.find(num[i]) == visited.end()) { 27 | tuple.clear(); 28 | visited.insert(num[i]); 29 | visited.insert(num[j]); 30 | tuple.push_back(num[i]); 31 | tuple.push_back(num[j]); 32 | ret.push_back(tuple); 33 | ++i; 34 | --j; 35 | } 36 | else if(sum < target) { 37 | ++i; 38 | } 39 | else { 40 | --j; 41 | } 42 | } 43 | } 44 | else { 45 | for(int i = begin; i < num.size(); ++i) { 46 | if(visited.find(num[i]) == visited.end()) { 47 | visited.insert(num[i]); 48 | vector > subret = findZeroSumInSortedArr(num, i + 1, count - 1, target - num[i]); 49 | if(!subret.empty()) { 50 | for(int j = 0; j < subret.size(); ++j) { 51 | subret[j].insert(subret[j].begin(), num[i]); 52 | } 53 | 54 | ret.insert(ret.end(), subret.begin(), subret.end()); 55 | } 56 | } 57 | } 58 | } 59 | 60 | return ret; 61 | } 62 | }; 63 | 64 | int main(int argc, char const *argv[]) 65 | { 66 | 67 | 68 | return 0; 69 | } -------------------------------------------------------------------------------- /LeetCode/length_last_word.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/11/8 4 | * source: LeetCode OJ 5 | * title: Length of Last Word 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | class Solution { 13 | public: 14 | int lengthOfLastWord(const char *s) 15 | { 16 | int len = 0; 17 | 18 | while(*s) { 19 | if(*s == ' ') { 20 | len = 0; 21 | while(*s && *s == ' ') 22 | ++s; 23 | } 24 | ++len; 25 | ++s; 26 | } 27 | 28 | return len; 29 | } 30 | }; 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | Solution sol; 35 | cout << sol.lengthOfLastWord("Hello World") << endl; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /LeetCode/linked_list_cycle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/3/26 4 | * source: LeetCode OJ 5 | * title: LRU Cache 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | class Solution { 13 | public: 14 | bool hasCycle(ListNode *head) 15 | { 16 | ListNode *fast = head, *slow = head; 17 | 18 | while(fast && fast->next) { 19 | slow = slow->next; 20 | fast = fast->next->next; 21 | if(slow == fast) { 22 | break; 23 | } 24 | } 25 | return ((fast == NULL) || (fast->next == NULL)); 26 | } 27 | }; 28 | 29 | int main() 30 | { 31 | 32 | } -------------------------------------------------------------------------------- /LeetCode/longest_common_prifix.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/11/8 4 | * source: LeetCode OJ 5 | * title: Longest Common Prefix 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class Solution { 16 | public: 17 | string strprefix(string str1, string str2) 18 | { 19 | int i = 0; 20 | string str; 21 | 22 | while(i < str1.size() && i < str2.size() && str1.at(i) == str2.at(i)) { 23 | str += str1.at(i); 24 | ++i; 25 | } 26 | 27 | return str; 28 | } 29 | 30 | string longestCommonPrefix(vector &strs) 31 | { 32 | if(strs.size() == 0) 33 | return string(); 34 | 35 | string str = strs[0]; 36 | 37 | for(vector::iterator iter = strs.begin(); 38 | iter != strs.end(); ++iter) { 39 | str = strprefix(str, *iter); 40 | } 41 | 42 | return str; 43 | } 44 | }; 45 | 46 | int main(int argc, char *argv[]) 47 | { 48 | string strs[] = {"abc", "abcd", "ab"}; 49 | vector vec(strs, strs+3); 50 | Solution sol; 51 | cout << sol.longestCommonPrefix(vec) << endl; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /LeetCode/longest_consecutive_sequence.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/8 4 | * source: LeetCode OJ 5 | * title: Longest Consecutive Sequence 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class Solution { 16 | unordered_set hash; 17 | public: 18 | enum DIRECTION{ 19 | forward, backward 20 | }; 21 | 22 | int find_consecutive(int cur, DIRECTION dir) 23 | { 24 | int len = 0; 25 | 26 | unordered_set::iterator iter; 27 | while((iter = hash.find(cur)) != hash.end()) { 28 | ++len; 29 | hash.erase(iter); 30 | if(dir == forward) { 31 | ++cur; 32 | } 33 | else if(dir == backward) { 34 | --cur; 35 | } 36 | } 37 | 38 | return len; 39 | } 40 | 41 | int longestConsecutive(vector &num) 42 | { 43 | for(vector::iterator iter = num.begin(); 44 | iter != num.end(); ++iter) { 45 | hash.insert(*iter); 46 | } 47 | 48 | int len = 0; 49 | 50 | for(vector::iterator iter = num.begin(); 51 | iter != num.end(); ++iter) { 52 | len = max(find_consecutive(*iter, forward) + find_consecutive(*iter - 1, backward), len); 53 | } 54 | 55 | return len; 56 | } 57 | }; 58 | 59 | int main(int argc, char const *argv[]) 60 | { 61 | int arr[] = {100, 4, 200, 1, 3, 2}; 62 | vector ivec(arr, arr + sizeof(arr) / sizeof(arr[0])); 63 | Solution sol; 64 | cout << sol.longestConsecutive(ivec) << endl; 65 | 66 | return 0; 67 | } -------------------------------------------------------------------------------- /LeetCode/longest_substring_without_repeating_characters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | class Solution { 8 | public: 9 | int lengthOfLongestSubstring(string s) 10 | { 11 | if(s.empty()) 12 | return 0; 13 | 14 | set hash; 15 | unsigned long n = 0; 16 | string::iterator start = s.begin(); 17 | string::iterator iter = s.begin(); 18 | 19 | while(start != s.end()) { 20 | if(iter != s.end() && hash.find(*iter) == hash.end()) { 21 | hash.insert(*iter); 22 | ++iter; 23 | } 24 | else { 25 | if(hash.size() > n) { 26 | n = hash.size(); 27 | } 28 | if(iter == s.end()) 29 | break; 30 | hash.clear(); 31 | ++start; 32 | iter = start; 33 | } 34 | } 35 | return n; 36 | } 37 | 38 | int lengthOfLongestSubstring2(string s) 39 | { 40 | if(s.empty()) 41 | return 0; 42 | 43 | unsigned long n = 0; 44 | string::iterator start = s.begin(); 45 | string::iterator iter = s.begin(), find_iter; 46 | 47 | while(start != s.end()) { 48 | if(iter != s.end() && (find_iter = find(start, iter, *iter)) == iter) { 49 | ++iter; 50 | } 51 | else { 52 | if(iter - start > n) { 53 | n = iter - start; 54 | } 55 | if(iter == s.end()) 56 | break; 57 | start = find_iter + 1; 58 | iter = start; 59 | } 60 | } 61 | return n; 62 | } 63 | }; 64 | 65 | int main() 66 | { 67 | string str("chzdflilrjqfnxz"); 68 | Solution sol; 69 | cout << sol.lengthOfLongestSubstring(str) << endl; 70 | cout << sol.lengthOfLongestSubstring2(str) << endl; 71 | 72 | return 0; 73 | } -------------------------------------------------------------------------------- /LeetCode/minimum_path_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/11/19 4 | * source: LeetCode OJ 5 | * title: Minimum Path Sum 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class Solution { 16 | public: 17 | int minPathSum(vector > &grid) 18 | { 19 | vector >::size_type grid_size = grid.size(); 20 | 21 | if(grid_size == 0) 22 | return 0; 23 | 24 | vector >::size_type arr_size = grid[0].size(); 25 | int *e = new int[arr_size]; 26 | int *tmp = new int[arr_size]; 27 | 28 | for(int i = 0; i < grid_size; ++i) { 29 | for(int j = 0; j < arr_size; ++j) { 30 | if(i == 0 && j == 0) { 31 | tmp[j] = grid[i][j]; 32 | } 33 | else if(i == 0) { 34 | tmp[j] = tmp[j-1] + grid[i][j]; 35 | } 36 | else if(j == 0) { 37 | tmp[j] = e[j] + grid[i][j]; 38 | } 39 | else { 40 | tmp[j] = min(tmp[j-1], e[j]) + grid[i][j]; 41 | } 42 | } 43 | copy(tmp, tmp+arr_size, e); 44 | } 45 | 46 | int minsum = e[arr_size-1]; 47 | 48 | delete[] e; 49 | delete[] tmp; 50 | 51 | return minsum; 52 | } 53 | }; 54 | 55 | int main(int argc, char *argv[]) 56 | { 57 | 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /LeetCode/next_permutation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/11/19 4 | * source: LeetCode OJ 5 | * title: Next Permutation 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class Solution { 16 | public: 17 | void nextPermutation(vector &num) 18 | { 19 | int tmp = 0; 20 | vector::iterator iter, viter; 21 | 22 | for(viter = num.end()-1; 23 | viter != num.begin(); --viter) { 24 | if(*viter > *(viter-1)) { 25 | iter = viter; 26 | while(iter != num.end() && *iter > *(viter-1)) 27 | ++iter; 28 | --iter; 29 | tmp = *iter; 30 | num.erase(iter); 31 | iter = num.insert(viter-1, tmp); 32 | sort(iter+1, num.end()); 33 | break; 34 | } 35 | } 36 | 37 | if(viter == num.begin()) { 38 | sort(num.begin(), num.end()); 39 | } 40 | } 41 | }; 42 | 43 | int main(int argc, char *argv[]) 44 | { 45 | int arr[] = {1, 3, 2}; 46 | int len = sizeof(arr) / sizeof(arr[0]); 47 | 48 | vector n(arr, arr+len); 49 | Solution sol; 50 | sol.nextPermutation(n); 51 | 52 | for(vector::iterator iter = n.begin(); 53 | iter != n.end(); ++iter) { 54 | cout << *iter << endl; 55 | } 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /LeetCode/pascal_triangle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/24 4 | * source: LeetCode OJ 5 | * title: Pascal's Triangle 6 | */ 7 | 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | class Solution { 13 | public: 14 | vector > generate(int numRows) 15 | { 16 | if(numRows == 0) 17 | return vector >(0); 18 | 19 | vector > ivec; 20 | int i = 0, j = 0; 21 | for(i = 0; i < numRows; i++) { 22 | vector vec; 23 | for(j = 0; j < i+1; j++) { 24 | if(j == 0 || j == i) 25 | vec.push_back(1); 26 | else 27 | vec.push_back(ivec[i-1][j-1] + ivec[i-1][j]); 28 | } 29 | ivec.push_back(vec); 30 | } 31 | for(i = 0; i < numRows; i++) { 32 | for(j = 0; j < i+1; j++) { 33 | cout< > vec; 44 | Solution sol; 45 | vector > vec(sol.generate(5)); 46 | cout<<"ab"< 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | void print_vec(vector vec) 15 | { 16 | for(vector::iterator iter = vec.begin(); 17 | iter != vec.end(); iter++) 18 | cout<<*iter<<" "; 19 | cout< getRow(int rowIndex) 25 | { 26 | vector ivec; 27 | vector ivec2; 28 | 29 | if(rowIndex == 0) 30 | return vector(1, 1); 31 | int i = 0, j = 0; 32 | ivec.push_back(1); 33 | for(i = 1; i <= rowIndex; i++) { 34 | for(j = 0; j <= ivec.size(); j++) { 35 | if(j == 0 || j == ivec.size()) { 36 | ivec2.push_back(1); 37 | } 38 | else { 39 | ivec2.push_back(ivec[j-1]+ivec[j]); 40 | } 41 | } 42 | ivec = ivec2; 43 | ivec2.clear(); 44 | print_vec(ivec); 45 | } 46 | return ivec; 47 | } 48 | }; 49 | 50 | int main(int argc, char *argv[]) 51 | { 52 | Solution sol; 53 | vector vec = sol.getRow(3); 54 | for(vector::iterator iter = vec.begin(); 55 | iter != vec.end(); iter++) { 56 | cout<<*iter<<" "; 57 | } 58 | cout< 10 | #include 11 | using namespace std; 12 | 13 | class Solution { 14 | string s; 15 | public: 16 | int factorial(int n) 17 | { 18 | if(n == 1) 19 | return n; 20 | return n * factorial(n- 1); 21 | } 22 | 23 | string get_per(int n, int k) 24 | { 25 | if(n == 1) 26 | return string(1, s[n - 1]); 27 | int group = 0, n_tmp = n, fac = factorial(n - 1); 28 | string str; 29 | if(k % fac) 30 | group = k / fac + 1; 31 | else 32 | group = k / fac; 33 | k -= fac * (group - 1); 34 | str += s[group - 1]; 35 | s.erase(s.begin() + group - 1); 36 | str += get_per(--n, k); 37 | return str; 38 | } 39 | 40 | string getPermutation(int n, int k) 41 | { 42 | int n_tmp = n; 43 | char ch = '1'; 44 | s.clear(); 45 | while(n_tmp--) { 46 | s += ch; 47 | ++ch; 48 | } 49 | return get_per(n, k); 50 | } 51 | }; 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | Solution sol; 56 | for(int i = 1; i <= 24; ++i) { 57 | string str = sol.getPermutation(4, i); 58 | cout << str << endl; 59 | } 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /LeetCode/reverse_integer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/21 4 | * source: LeetCode OJ 5 | * title: Reverse Integer 6 | * remark: 本题题目给的提示是前面的0和溢出的问题,不过在提交题目的时候并不需要考虑这些问题,that's so funny 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | void int_to_arr(int num, char *arr, int *size) 13 | { 14 | int data = num; 15 | int i = 0; 16 | 17 | if(num < 0) { 18 | arr[0] = '-'; 19 | data = -num; 20 | } 21 | else 22 | arr[0] = '+'; 23 | i = 1; 24 | while(data) { 25 | arr[i++] = data%10; 26 | data /= 10; 27 | } 28 | *size = i; 29 | } 30 | 31 | int reverse(int x) 32 | { 33 | char arr[15]; 34 | int n = 0, i = 0; 35 | int result = 0, temp = 1; 36 | memset(arr, 0, 15); 37 | 38 | int_to_arr(x, arr, &n); 39 | /*for(i = 0; i < n; i++) 40 | printf("%d\n", arr[i]);*/ 41 | 42 | for(i = n-1; i >= 1; i--) { 43 | result += arr[i]*temp; 44 | temp *= 10; 45 | } 46 | if(arr[0] == '-') 47 | result = -result; 48 | return result; 49 | } 50 | 51 | int reverse1(int x) 52 | { 53 | int flag = x>0 ? -1 : 1; 54 | 55 | int X = abs(x); 56 | int result = 0; 57 | 58 | while(X) { 59 | result = result*10+X%10; 60 | X /= 10; 61 | } 62 | 63 | return flag*result; 64 | } 65 | 66 | int main(int argc, char *argv[]) 67 | { 68 | printf("%d\n", reverse1(1000000003)); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /LeetCode/reverse_words_in_string.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/3/18 4 | * source: LeetCode OJ 5 | * title: Reverse Words in a String 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class Solution { 16 | public: 17 | void reverseWords(string &s) { 18 | if(s.size() == 0) 19 | return; 20 | 21 | stack sta; 22 | string str; 23 | string::iterator beg = s.begin(); 24 | while(beg != s.end() && *beg == ' ') 25 | ++beg; 26 | while(beg != s.end()) { 27 | if(*beg == ' ') { 28 | sta.push(str); 29 | str.clear(); 30 | ++beg; 31 | while(beg != s.end() && *beg == ' ') 32 | ++beg; 33 | } 34 | else { 35 | str += *beg; 36 | ++beg; 37 | } 38 | } 39 | if(str.size()) 40 | sta.push(str); 41 | s.clear(); 42 | while(!sta.empty()) { 43 | str = sta.top(); 44 | sta.pop(); 45 | s.append(str.begin(), str.end()); 46 | s += " "; 47 | } 48 | if(s.size()) 49 | s.erase(s.end() - 1); 50 | } 51 | }; 52 | 53 | int main() 54 | { 55 | Solution sol; 56 | string str(" 1 "); 57 | sol.reverseWords(str); 58 | cout << str << endl; 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /LeetCode/rotate_image.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/29 4 | * source: LeetCode OJ 5 | * title: Rotate Image 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | class Solution { 14 | public: 15 | void rotate(vector > &matrix) 16 | { 17 | int n = matrix.size(); 18 | 19 | int temp = 0; 20 | int i = 0, j = 0; 21 | int start = 0, end = n-1; 22 | int index = 0; 23 | int width = 0; 24 | width = n-1; 25 | while(start < end) { 26 | for(j = start; j < end; j++) { 27 | temp = matrix[index][j]; 28 | matrix[index][j] = matrix[width-j][index]; 29 | matrix[width-j][index] = matrix[width-index][width-j]; 30 | matrix[width-index][width-j] = matrix[j][width-index]; 31 | matrix[j][width-index] = temp; 32 | } 33 | index++; 34 | start++; 35 | end--; 36 | } 37 | } 38 | }; 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | Solution sol; 43 | vector > vec; 44 | vector ivec; 45 | 46 | int i = 0, j = 0; 47 | for(i = 0; i < 5; i++) { 48 | ivec.clear(); 49 | for(j = 0; j < 5; j++) { 50 | ivec.push_back(i*10+j); 51 | cout<val == q->val && 19 | isSameTree(p->left, q->left) && 20 | isSameTree(p->right, q->right)) 21 | return true; 22 | else 23 | return false; 24 | } 25 | -------------------------------------------------------------------------------- /LeetCode/single_number.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/16 4 | * source: LeetCode OJ 5 | * title: Single Number 6 | * solution: 利用异或运算符的特性,相同为0,相异为1 7 | */ 8 | 9 | #include 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int arr[] = {1, 4, 6, 4, 7, 1, 7}; 14 | int len = sizeof(arr)/sizeof(int); 15 | 16 | int i = 0; 17 | int res = 0; 18 | for(i = 0; i < len; i++) { 19 | res ^= arr[i]; 20 | } 21 | printf("single number: %d\n", res); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /LeetCode/single_number_II.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/30 4 | * source: LeetCode OJ 5 | * title: Single Number II 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | class Solution { 13 | public: 14 | int singleNumber(int A[], int n) 15 | { 16 | int one = 0, two = 0, three = 0; 17 | 18 | int i = 0; 19 | for(i = 0; i < n; ++i) { 20 | two |= one & A[i]; 21 | one ^= A[i]; 22 | three = one & two; 23 | one &= ~three; 24 | two &= ~three; 25 | } 26 | 27 | return one; 28 | } 29 | }; 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | int a[] = {1, 5, 1, 1}; 34 | int len = sizeof(a) / sizeof(a[0]); 35 | 36 | Solution sol; 37 | int single = sol.singleNumber(a, len); 38 | cout<<"single number: "< 10 | using namespace std; 11 | 12 | class Solution { 13 | public: 14 | void swap(int &a, int &b) 15 | { 16 | int temp = a; 17 | a = b; 18 | b = temp; 19 | } 20 | 21 | void sortColors(int A[], int n) 22 | { 23 | int i = 0; 24 | int j = 0, k = n-1; 25 | 26 | while(i <= k) { 27 | if(A[i] == 0) { 28 | if(i != j) { 29 | swap(A[i], A[j]); 30 | ++j; 31 | continue; 32 | } 33 | else { 34 | ++j; 35 | } 36 | } 37 | else if(A[i] == 2) { 38 | if(i != k) { 39 | swap(A[i], A[k]); 40 | --k; 41 | continue; 42 | } 43 | else { 44 | --k; 45 | } 46 | } 47 | ++i; 48 | } 49 | } 50 | }; 51 | 52 | int main(int argc, char *argv[]) 53 | { 54 | int a[] = {2, 1, 0, 1, 0, 2}; 55 | int len = sizeof(a) / sizeof(a[0]); 56 | 57 | Solution sol; 58 | sol.sortColors(a, len); 59 | for(int i = 0; i < len; ++i) 60 | cout< 10 | #include 11 | using namespace std; 12 | 13 | class Solution { 14 | public: 15 | vector > generateMatrix(int n) 16 | { 17 | vector > vec(n, vector(n)); 18 | 19 | int i = 0, j = 0; 20 | int count = 1; 21 | int index = 0; 22 | int start = 0, end = n-1; 23 | while(count <= n*n) { 24 | for(i = index, j = start; j <= end && count <= n*n; j++) 25 | vec[i][j] = count++; 26 | 27 | for(j = n-1-index, i = start+1; i < end && count <= n*n; i++) 28 | vec[i][j] = count++; 29 | 30 | for(i = n-1-index, j = end; j >= start && count <= n*n; j--) 31 | vec[i][j] = count++; 32 | 33 | for(j = index, i = end-1; i >= start+1 && count <= n*n; i--) 34 | vec[i][j] = count++; 35 | 36 | index++; 37 | start++; 38 | end--; 39 | } 40 | 41 | return vec; 42 | } 43 | }; 44 | 45 | int main(int argc, char *argv[]) 46 | { 47 | Solution sol; 48 | vector > vec; 49 | vec = sol.generateMatrix(4); 50 | 51 | int i = 0, j = 0; 52 | for(i = 0; i < 4; i++) { 53 | for(j = 0; j < 4; j++) 54 | cout< 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | void set_sudoku(vector > &board) 16 | { 17 | ifstream is("../../current/sudoku"); 18 | vector ln; 19 | int i = 9, j = 9; 20 | while(i--) { 21 | ln.clear(); 22 | j = 9; 23 | while(j--) { 24 | ln.push_back(is.get()); 25 | } 26 | board.push_back(ln); 27 | } 28 | } 29 | 30 | void print_cell(char ch) 31 | { 32 | cout << ch << " "; 33 | } 34 | 35 | void print_sudoku(vector ln) 36 | { 37 | for_each(ln.begin(), ln.end(), print_cell); 38 | cout << endl; 39 | } 40 | 41 | class Solution { 42 | public: 43 | static const int MAXN = 9; 44 | static const int TRI = 3; 45 | 46 | void solveSudoku(vector > &board) 47 | { 48 | int i = 0, j = 0; 49 | 50 | for(i = 0; i < MAXN; ++i) { 51 | for(j = 0; j < MAXN; ++j) { 52 | 53 | } 54 | } 55 | } 56 | }; 57 | 58 | int main(int argc, char *argv[]) 59 | { 60 | vector > board; 61 | set_sudoku(board); 62 | for_each(board.begin(), board.end(), print_sudoku); 63 | cout << endl; 64 | Solution sol; 65 | sol.solveSudoku(board); 66 | for_each(board.begin(), board.end(), print_sudoku); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /LeetCode/template.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/ 4 | * source: LeetCode OJ 5 | * title: 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | class Solution { 15 | public: 16 | 17 | }; 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /LeetCode/three_sum_closest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/13 4 | * source: LeetCode 5 | * title: 3Sum Closest 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | class Solution { 13 | public: 14 | int threeSumClosest(vector &num, int target) 15 | { 16 | sort(num.begin(), num.end()); 17 | 18 | int ret = 0; 19 | 20 | for(int i = 0; i < num.size(); ++i) { 21 | int j = i + 1; 22 | int k = num.size() - 1; 23 | 24 | while(j < k) { 25 | int sum = num[i] + num[j] + num[k]; 26 | if(first) { 27 | ret = sum; 28 | first = false; 29 | } 30 | else { 31 | if(abs(sum - target) < abs(ret - target)) { 32 | ret = sum; 33 | } 34 | } 35 | 36 | if(ret == target) { 37 | return ret; 38 | } 39 | 40 | if(sum > target) { 41 | --k; 42 | } 43 | else { 44 | ++j; 45 | } 46 | } 47 | } 48 | 49 | return ret; 50 | } 51 | }; 52 | 53 | int main(int argc, char const *argv[]) 54 | { 55 | 56 | 57 | return 0; 58 | } -------------------------------------------------------------------------------- /LeetCode/trapping_rain_water.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/11/7 4 | * source: LeetCode OJ 5 | * title: Trapping Rain Water 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | class Solution { 13 | public: 14 | int trap(int A[], int n) { 15 | int sum = 0, m = 0; 16 | int i = 0, j = 0, k = 0; 17 | 18 | for(i = 0; i < n; ++i) { 19 | j = i + 1; 20 | while(j < n && A[j] < A[i]) 21 | ++j; 22 | 23 | if(j == n) { 24 | for(j = n - 1; j > i; --j) { 25 | k = j - 1; 26 | while(k >= i && A[k] < A[j]) 27 | --k; 28 | m = j - 1; 29 | while(m > k) { 30 | if(A[j] > A[m]) 31 | sum += A[j] - A[m]; 32 | --m; 33 | } 34 | j = k + 1; 35 | } 36 | return sum; 37 | } 38 | 39 | k = i + 1; 40 | while(k < j) { 41 | if(A[i] > A[k]) 42 | sum += A[i] - A[k]; 43 | ++k; 44 | } 45 | 46 | i = j - 1; 47 | } 48 | 49 | return sum; 50 | } 51 | }; 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | int arr[] = {4, 9, 4, 5, 3, 2}; 56 | int len = sizeof(arr) / sizeof(arr[0]); 57 | 58 | Solution sol; 59 | cout << sol.trap(arr, len) < 9 | 10 | void two_sum(int nums[], int size, int target, int *index1, int *index2) 11 | { 12 | int i = 0, j = 0; 13 | 14 | *index1 = i; 15 | *index2 = j; 16 | for(i = 0; i < size; i++) 17 | for(j = i+1; j < size; j++) 18 | if(nums[i]+nums[j] == target) { 19 | *index1 = i; 20 | *index2 = j; 21 | } 22 | } 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | int arr[] = {2, 7, 11, 15}; 27 | int len = sizeof(arr)/sizeof(int); 28 | 29 | int index1 = 0, index2 = 0; 30 | int target = 16; 31 | two_sum(arr, len, target, &index1, &index2); 32 | if(index1 == 0 && index2 == 0) 33 | printf("cannot find two numbers in the array that they add up to %d\n", target); 34 | else 35 | printf("index1 = %d, index2 = %d\n", index1+1, index2+1); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /LeetCode/two_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/12 4 | * source: APUE 5 | * title: Two Sum 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | bool compare(pair lh, pair rh) 16 | { 17 | return lh.first < rh.first; 18 | } 19 | 20 | class Solution { 21 | public: 22 | vector twoSum(vector &numbers, int target) 23 | { 24 | vector > num; 25 | int index = 1; 26 | for(vector::iterator iter = numbers.begin(); 27 | iter != numbers.end(); ++iter, ++index) { 28 | num.push_back(make_pair(*iter, index)); 29 | } 30 | sort(num.begin(), num.end(), compare); 31 | int i = 0, j = num.size() - 1; 32 | vector res; 33 | for(; i < j;) { 34 | if(num[i].first + num[j].first == target) { 35 | res.push_back(num[i].second); 36 | res.push_back(num[j].second); 37 | ++i; 38 | } 39 | else if(num[i].first + num[j].first < target) { 40 | ++i; 41 | } 42 | else { 43 | --j; 44 | } 45 | } 46 | return res; 47 | } 48 | }; 49 | 50 | void print(int i) 51 | { 52 | cout << i << "\t"; 53 | } 54 | 55 | int main(int argc, char const *argv[]) 56 | { 57 | int arr[] = {5, 6, 1, 4, 7, 9, 8}; 58 | vector vec(arr, arr + sizeof(arr) / sizeof(arr[0])); 59 | Solution sol; 60 | int target = 10; 61 | vector res = sol.twoSum(vec, target); 62 | for_each(res.begin(), res.end(), print); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /LeetCode/unique_binary_search_trees.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/23 4 | * source: LeetCode OJ 5 | * title: Unique Binary Search Trees 6 | */ 7 | 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | class Solution { 13 | public: 14 | int numtree(int left, int right) 15 | { 16 | int i = 0, num = 0; 17 | if(left >= right) 18 | return 1; 19 | 20 | for(i = left; i <= right; i++) { 21 | num += numtree(left, i-1) * numtree(i+1, right); 22 | } 23 | return num; 24 | } 25 | 26 | int numTrees(int n) 27 | { 28 | return numtree(0, n-1); 29 | } 30 | }; 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | int n = 0; 35 | cin>>n; 36 | Solution sol; 37 | cout< 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | class Solution { 15 | public: 16 | bool isValid(string s) 17 | { 18 | stack sta; 19 | 20 | for(string::iterator iter = s.begin(); 21 | iter != s.end(); ++iter) { 22 | switch(*iter) { 23 | case '(': case '{': case '[': 24 | sta.push(*iter); 25 | break; 26 | case ')': 27 | if(sta.empty() || !sta.empty() && sta.top() != '(') 28 | return false; 29 | sta.pop(); 30 | break; 31 | case '}': 32 | if(sta.empty() || !sta.empty() && sta.top() != '{') 33 | return false; 34 | sta.pop(); 35 | break; 36 | case ']': 37 | if(sta.empty() || !sta.empty() && sta.top() != '[') 38 | return false; 39 | sta.pop(); 40 | break; 41 | default: 42 | break; 43 | } 44 | } 45 | 46 | if(sta.empty()) 47 | return true; 48 | else 49 | return false; 50 | } 51 | }; 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | string s("([)]"); 56 | Solution sol; 57 | 58 | if(sol.isValid(s)) { 59 | cout<<"Valid Parentheses!"< 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | int sum = 0; 18 | int up = 1000-1; 19 | 20 | while(up > 0) { 21 | if(!(up%3) | !(up%5)) 22 | sum += up; 23 | up--; 24 | } 25 | 26 | printf("multiples of 3 and 5: %d\n", sum); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /ProjectEuler/2_Euler.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/15 4 | * source: Problem 2 of Project Euler.net 5 | * title: Even Fibonacci numbers 6 | * info: 7 | 8 | Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 9 | 10 | 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 11 | 12 | By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. 13 | 14 | */ 15 | 16 | #include 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | unsigned int item1 = 1, item2 = 2; 21 | unsigned long long cur = item1+item2; 22 | unsigned long long sum = item2; 23 | unsigned int up = 4000000; 24 | 25 | while(cur < up) { 26 | if(!(cur%2)) { 27 | sum += cur; 28 | } 29 | printf("%d\n", cur); 30 | item1 = item2; 31 | item2 = cur; 32 | cur = item1+item2; 33 | } 34 | 35 | printf("sum of the even-valued terms: %ld\n", sum); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /ProjectEuler/3_Euler.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/16 4 | * source: Problem 3 of Project Euler.net 5 | * title: Largest prime factor 6 | * remark: 本题最终得到了正确结果,但是运行了28984404.55ms,大约8个小时,所以,该程序有很大的改进空间,比如,如何判断素数 7 | * info: 8 | 9 | The prime factors of 13195 are 5, 7, 13 and 29. 10 | 11 | What is the largest prime factor of the number 600851475143 ? 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | unsigned int is_prime(unsigned long long num) 19 | { 20 | unsigned long long i = 2; 21 | 22 | if(num == 1) 23 | return 0; 24 | 25 | while(i < num) { 26 | if(num%i == 0) 27 | return 0; 28 | i++; 29 | } 30 | 31 | return 1; 32 | } 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | long start_sec, finish_sec, start_usec, finish_usec; 37 | struct timeval tv; 38 | struct timezone tz; 39 | 40 | gettimeofday(&tv, &tz); 41 | start_sec = tv.tv_sec; 42 | start_usec = tv.tv_usec; 43 | 44 | unsigned long long num = 600851475143; 45 | unsigned long long factor = num; 46 | 47 | while(factor > 1) { 48 | if(num%factor == 0 && is_prime(factor)) { 49 | printf("%lld\n", factor); 50 | break; 51 | } 52 | else 53 | factor--; 54 | } 55 | 56 | gettimeofday(&tv, &tz); 57 | finish_sec = tv.tv_sec; 58 | finish_usec = tv.tv_usec; 59 | 60 | double duration = (double)(finish_usec-start_usec)/1000+(finish_sec-start_sec)*1000; 61 | printf("Runtime: %.2fms\n", duration); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /ProjectEuler/5_Euler.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/18 4 | * source: Problem 5 of Project Euler.net 5 | * title: Smallest multiple 6 | * solution URL:http://m.blog.csdn.net/blog/acmjk/9767779 7 | * remark: 最简单的方法是采用迭代的方式逐个两两求最小公倍数, 8 | * info: 9 | 10 | 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. 11 | 12 | What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20? 13 | 14 | */ 15 | 16 | #include 17 | 18 | #define max(a, b) (a)>(b) ? (a) : (b) 19 | #define min(a, b) (a)>(b) ? (b) : (a) 20 | 21 | /* a和b的最小公倍数 */ 22 | int lcm(int a, int b) 23 | { 24 | int big = max(a, b); 25 | int small = min(a, b); 26 | int max = a*b; 27 | 28 | int i = big; 29 | for(i = big; i < max; i += big) { 30 | if(i%small == 0) 31 | return i; 32 | } 33 | return max; 34 | } 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | int a = 1, b = 2; 39 | int lcm_val = 0; 40 | 41 | while(b <= 20) { 42 | lcm_val = lcm(a, b); 43 | printf("a and b lcm is: %d\n", lcm_val); 44 | a = lcm_val; 45 | b++; 46 | } 47 | printf("%d\n", lcm_val); 48 | 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### [2015年校园招聘笔试题集锦](https://github.com/luofengmacheng/algorithms/blob/master/2015_bishi/README.md) 2 | 3 | ### [2015年校园招聘面试题集锦](https://github.com/luofengmacheng/algorithms/blob/master/2015_interview/README.md) 4 | 5 | ### [Linux](https://github.com/luofengmacheng/algorithms/blob/master/apue/README.md) 6 | 7 | ### [C++语言程序设计](https://github.com/luofengmacheng/algorithms/blob/master/tcpl/README.md) 8 | 9 | ### [排序算法(C++版)](https://github.com/luofengmacheng/algorithms/blob/master/data_struct/sort/README.md) 10 | 11 | ### [剑指Offer笔记](https://github.com/luofengmacheng/algorithms/blob/master/interviewOffer/README.md) 12 | 13 | ### [编程之美笔记](https://github.com/luofengmacheng/algorithms/blob/master/bop/README.md) 14 | 15 | ### [hihoCoder](https://github.com/luofengmacheng/algorithms/blob/master/hihocoder/README.md) 16 | 17 | ### [July微软面试100题系列笔记](https://github.com/luofengmacheng/algorithms/blob/master/july_100/README.md) 18 | 19 | ### [知识点集锦](https://github.com/luofengmacheng/algorithms/blob/master/myalgo/README.md) 20 | 21 | ### [年终总结](https://github.com/luofengmacheng/algorithms/blob/master/summary/README.md) 22 | -------------------------------------------------------------------------------- /apue/10_chapter/10.10_4_5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/6/11 4 | * source: APUE 5 | * title: 10.10 10_4 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | /* 13 | * problem1:如果调用这先调用了alarm(),那么在调用sleep1()后会擦除用户调用的alarm()。 14 | * solution:检查sleep1()中第一次调用alarm的返回值,如果返回值小于本次的参数nsecs,则忽略。 15 | * 如果返回值大于nsecs,则在sleep1()返回之前,复位此闹钟,使其在上次闹钟的设定时间再次发生超时。 16 | * problem2:sleep1()中修改了SIGALRM的配置。 17 | * solution:调用signal函数时保存返回值,然后在sleep1()返回之前再次修改SIGALRM的配置。 18 | * problem3:sleep1()中alarm()与pause()产生了竞争,有可能alarm在pause()之前就超时了,之后再调用pause(),则程序永远休眠。 19 | * solution:见sleep2()。 20 | */ 21 | 22 | static void 23 | sig_alrm(int signo) 24 | { 25 | } 26 | 27 | unsigned int 28 | sleep1(unsigned int nsecs) 29 | { 30 | if(signal(SIGALRM, sig_alrm) == SIG_ERR) { 31 | return nsecs; 32 | } 33 | 34 | alarm(nsecs); 35 | pause(); 36 | 37 | return alarm(0); 38 | } 39 | 40 | static jmp_buf env_alarm; 41 | 42 | static void 43 | sig_alrm(int signo) 44 | { 45 | longjmp(env_alarm, 1); 46 | } 47 | 48 | unsigned int 49 | sleep2(unsigned int nsecs) 50 | { 51 | if(signal(SIGALRM, sig_alrm) == SIG_ERR) { 52 | return nsecs; 53 | } 54 | 55 | if(setjmp(env_alarm) == 0) { 56 | alarm(nsecs); 57 | pause(); 58 | } 59 | 60 | return alarm(0); 61 | } -------------------------------------------------------------------------------- /apue/10_chapter/10_1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/6/9 4 | * source: APUE 5 | * title: 10.3 10-1 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | static void 13 | sig_usr(int signo) 14 | { 15 | if(signo == SIGUSR1) { 16 | printf("recevied SIGUSR1 %d\n", signo); 17 | } 18 | else if(signo == SIGUSR2) { 19 | printf("recevied SIGUSR2 %d\n", signo); 20 | } 21 | else if(signo == SIGCLD) { 22 | printf("recevied SIGTERM %d\n", signo); 23 | } 24 | else { 25 | printf("recevied signal %d\n", signo); 26 | } 27 | } 28 | 29 | int main(int argc, char const *argv[]) 30 | { 31 | if(signal(SIGUSR1, sig_usr) == SIG_ERR) { 32 | fprintf(stderr, "can't catch SIGUSR1 %d\n", __LINE__); 33 | } 34 | if(signal(SIGUSR2, sig_usr) == SIG_ERR) { 35 | fprintf(stderr, "can't catch SIGUSR2 %d\n", __LINE__); 36 | } 37 | if(signal(SIGCLD, sig_usr) == SIG_ERR) { 38 | fprintf(stderr, "can't catch SIGTERM %d\n", __LINE__); 39 | } 40 | for( ; ; ) { 41 | pause(); 42 | } 43 | 44 | return 0; 45 | } -------------------------------------------------------------------------------- /apue/10_chapter/10_10.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/6/11 4 | * source: APUE 5 | * title: 10.12 10-10 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | void 13 | pr_mask(const char *str) 14 | { 15 | sigset_t sigset; 16 | int errno_save; 17 | 18 | errno_save = errno; 19 | if(sigprocmask(0, NULL, &sigset) < 0) { 20 | fprintf(stderr, "sigprocmask error\n"); 21 | } 22 | 23 | printf("%s\n", str); 24 | 25 | if(sigismember(&sigset, SIGINT)) { 26 | printf("SIGINT\n"); 27 | } 28 | if(sigismember(&sigset, SIGQUIT)) { 29 | printf("SIGQUIT\n"); 30 | } 31 | if(sigismember(&sigset, SIGUSR1)) { 32 | printf("SIGUSR1\n"); 33 | } 34 | if(sigismember(&sigset, SIGALRM)) { 35 | printf("SIGALRM\n"); 36 | } 37 | 38 | printf("\n"); 39 | errno = errno_save; 40 | } -------------------------------------------------------------------------------- /apue/10_chapter/10_11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/6/11 4 | * source: APUE 5 | * title: 10.13 10-11 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | /* 13 | * 首先设置SIGQUIT的信号处理函数,然后阻塞SIGQUIT。接着休眠5秒钟。 14 | * 如果在这5秒钟之内产生了SIGQUIT信号,该信号就会被阻塞,并不递送至进程。 15 | * 5秒钟之后,检查阻塞的信号中是否有SIGQUIT。 16 | * 然后调用sigprocmask对信号屏蔽字进行复位,因此,SIGQUIT变成了非阻塞的, 17 | * 在sigporcmask返回之前,如果有未决信号,该信号就会被递送至接收进程, 18 | * 即在sigporcmask返回之前,会将之前在sleep(5)过程中的产生的未决信号递送至进程, 19 | * 然后就会调用SIGQUIT的信号处理程序。 20 | */ 21 | 22 | static void sig_quit(int signo) 23 | { 24 | printf("caught SIGQUIT\n"); 25 | if(signal(SIGQUIT, SIG_DFL) == SIG_ERR) { 26 | fprintf(stderr, "cannot reset SIGQUIT\n"); 27 | } 28 | } 29 | 30 | int main(int argc, char const *argv[]) 31 | { 32 | sigset_t newmask, oldmask, pendmask; 33 | 34 | /* 设置SIGQUIT的捕获函数 */ 35 | if(signal(SIGQUIT, sig_quit) == SIG_ERR) { 36 | fprintf(stderr, "cannot catch SIGQUIT\n"); 37 | } 38 | 39 | /* 阻塞SIGQUIT */ 40 | sigemptyset(&newmask); 41 | sigaddset(&newmask, SIGQUIT); 42 | if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { 43 | fprintf(stderr, "SIG_BLOCK error\n"); 44 | } 45 | 46 | sleep(5); 47 | 48 | 49 | if(sigpending(&pendmask) < 0) { 50 | fprintf(stderr, "sigpending error\n"); 51 | } 52 | if(sigismember(&pendmask, SIGQUIT)) { 53 | printf("SIGQUIT pending\n"); 54 | } 55 | 56 | if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { 57 | fprintf(stderr, "SIG_SETMASK error\n"); 58 | } 59 | printf("SIGQUIT unblocked\n"); 60 | 61 | sleep(5); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /apue/10_chapter/10_12_13.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/6/11 4 | * source: APUE 5 | * title: 10.14 10-12 6 | * language: C 7 | */ 8 | 9 | Sigfunc * 10 | signal(int signo, Sigfunc *func) 11 | { 12 | struct sigaction act, oact; 13 | 14 | act.sa_handler = func; 15 | sigemptyset(&act.sa_mask); 16 | act.sa_flags = 0; 17 | 18 | if(signo == SIGALRM) { 19 | #ifdef SA_INTERRUPT 20 | act.sa_flags |= SA_INTERRUPT; 21 | #endif 22 | } 23 | else { 24 | #ifdef SA_RESTART 25 | act.sa_flags |= SA_RESTART; 26 | #endif 27 | } 28 | 29 | if(sigaction(signo, &act, &oact) < 0) { 30 | return SIG_ERR; 31 | } 32 | return oact.sa_handler; 33 | } -------------------------------------------------------------------------------- /apue/10_chapter/10_2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/6/9 4 | * source: APUE 5 | * title: 10.6 10-2 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | static void 14 | my_alarm(int signo) 15 | { 16 | struct passwd *rootptr; 17 | 18 | printf("in signal handler\n"); 19 | if((rootptr = getpwnam("root")) == NULL) { 20 | fprintf(stderr, "getpwnam(root) error %d\n", __LINE__); 21 | } 22 | alarm(1); 23 | } 24 | 25 | int main(int argc, char const *argv[]) 26 | { 27 | struct passwd *ptr; 28 | 29 | signal(SIGALRM, my_alarm); 30 | alarm(1); 31 | 32 | for( ; ; ) { 33 | if((ptr = getpwnam("root")) == NULL) { 34 | fprintf(stderr, "getpwnam error %d\n", __LINE__); 35 | } 36 | printf("pw_name = %s\n", ptr->pw_name); 37 | } 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /apue/11_chapter/11.4_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | pthread_t ntid; 6 | 7 | void printids(const char *s) 8 | { 9 | pid_t pid; 10 | pthread_t tid; 11 | 12 | pid = getpid(); 13 | tid = pthread_self(); 14 | printf("%s pid %u tid %u(0x%x)\n", s, (unsigned int)pid, (unsigned int)tid, (unsigned int)tid); 15 | } 16 | 17 | void *thr_fn(void *arg) 18 | { 19 | printids("new thread: "); 20 | return ((void*)0); 21 | } 22 | 23 | int main() 24 | { 25 | int err; 26 | 27 | err = pthread_create(&ntid, NULL, thr_fn, NULL); 28 | if(err != 0) 29 | printf("can't create thread"); 30 | printids("main thread:"); 31 | sleep(1); 32 | 33 | exit(0); 34 | } -------------------------------------------------------------------------------- /apue/11_chapter/11.5_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void *thr_fn1(void *arg) 6 | { 7 | printf("thread1 returning\n"); 8 | return ((void *)1); 9 | } 10 | 11 | void *thr_fn2(void *arg) 12 | { 13 | printf("thread2 returning\n"); 14 | return ((void *)2); 15 | } 16 | 17 | int main() 18 | { 19 | int err; 20 | pthread_t tid1, tid2; 21 | void *tret; 22 | 23 | err = pthread_create(&tid1, NULL, thr_fn1, NULL); 24 | if(err != 0) { 25 | printf("can't create thread 1\n"); 26 | } 27 | 28 | err = pthread_create(&tid2, NULL, thr_fn2, NULL); 29 | if(err != 0) { 30 | printf("can't create thread 2\n"); 31 | } 32 | 33 | err = pthread_join(tid1, &tret); 34 | if(err != 0) { 35 | printf("can't join with thread 1\n"); 36 | } 37 | printf("thread 1 exit code %d\n", (int)tret); 38 | 39 | err = pthread_join(tid2, &tret); 40 | if(err != 0) { 41 | printf("can't join with thread 2\n"); 42 | } 43 | printf("thread 2 exit code %d\n", (int)tret); 44 | exit(0); 45 | } -------------------------------------------------------------------------------- /apue/11_chapter/11.5_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct foo { 6 | int a, b, c, d; 7 | }; 8 | 9 | void printfoo(const char *s, const struct foo *fp) 10 | { 11 | printf("%s\n", s); 12 | printf("structure at 0x%x\n", (unsigned)fp); 13 | printf("foo.a = %d\n", fp->a); 14 | printf("foo.b = %d\n", fp->b); 15 | printf("foo.c = %d\n", fp->c); 16 | printf("foo.d = %d\n", fp->d); 17 | } 18 | 19 | void *thr_fn1(void *arg) 20 | { 21 | struct foo f = {1, 2, 3, 4}; 22 | printfoo("thread 1 : \n", &f); 23 | pthread_exit((void*)&f); 24 | } 25 | 26 | void *thr_fn2(void *arg) 27 | { 28 | pthread_t tid; 29 | tid = pthread_self(); 30 | printf("thread 2 : ID is %u\n", (unsigned int)tid); 31 | pthread_exit((void*)0); 32 | } 33 | 34 | int main() 35 | { 36 | int err; 37 | pthread_t tid1, tid2; 38 | struct foo *fp; 39 | 40 | err = pthread_create(&tid1, NULL, thr_fn1, NULL); 41 | if(err != 0) { 42 | printf("can't create thread 1\n"); 43 | } 44 | 45 | err = pthread_join(tid1, (void*)&fp); 46 | if(err != 0) { 47 | printf("can't join with thread 1\n"); 48 | } 49 | 50 | sleep(1); 51 | printf("parent starting second thread\n"); 52 | err = pthread_create(&tid2, NULL, thr_fn2, NULL); 53 | if(err != 0) { 54 | printf("can't create thread 2\n"); 55 | } 56 | 57 | sleep(1); 58 | printfoo("parent:\n", fp); 59 | 60 | exit(0); 61 | } 62 | 63 | /* 64 | * 首先创建一个线程,在这个线程中分配一个局部结构体并将它作为返回值返回,然后在主线程中等待这个线程结束,获取线程的返回值,然后主线程休眠1s。 65 | * 接着创建第二个线程,然后打印之前获取线程的结束状态,那么,此时这个指针指向的就是在之前已经结束的线程的局部空间,因此,打印的就是垃圾信息。 66 | */ 67 | -------------------------------------------------------------------------------- /apue/11_chapter/11_4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void cleanup(void *arg) 5 | { 6 | printf("cleanup %s\n", (char *)arg); 7 | } 8 | 9 | void *thr_fn1(void *arg) 10 | { 11 | printf("thread 1 start\n"); 12 | pthread_cleanup_push(cleanup, "thread 1 first handler"); 13 | pthread_cleanup_push(cleanup, "thread 1 second handler"); 14 | printf("thread 1 push complete\n"); 15 | if(arg) 16 | return ((void *)1); 17 | pthread_cleanup_pop(0); 18 | pthread_cleanup_pop(0); 19 | return ((void *)1); 20 | } 21 | 22 | void *thr_fn2(void *arg) 23 | { 24 | printf("thread 2 start\n"); 25 | pthread_cleanup_push(cleanup, "thread 2 first handler"); 26 | pthread_cleanup_push(cleanup, "thread 2 second handler"); 27 | printf("thread 2 push complete\n"); 28 | if(arg) 29 | pthread_exit((void *)2); 30 | pthread_cleanup_pop(1); 31 | pthread_cleanup_pop(2); 32 | pthread_exit((void *)2); 33 | } 34 | 35 | int main(int argc, char const *argv[]) 36 | { 37 | int err; 38 | pthread_t tid1, tid2; 39 | void *tret; 40 | 41 | err = pthread_create(&tid1, NULL, thr_fn1, (void *)1); 42 | if(err != 0) { 43 | printf("can't create thread 1\n"); 44 | } 45 | 46 | err = pthread_create(&tid2, NULL, thr_fn2, (void *)2); 47 | if(err != 0) { 48 | printf("can't create thread 2\n"); 49 | } 50 | 51 | err = pthread_join(tid1, &tret); 52 | if(err != 0) { 53 | printf("can't join with thread 1\n"); 54 | } 55 | printf("thread 1 exit code %d\n", (int)tret); 56 | 57 | err = pthread_join(tid2, &tret); 58 | if(err != 0) { 59 | printf("can't join with thread 2\n"); 60 | } 61 | printf("thread 2 exit code %d\n", (int)tret); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /apue/11_chapter/11_9.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct msg { 4 | struct msg *m_next; 5 | }; 6 | 7 | struct msg *workq; 8 | pthread_cond_t qready = PTHREAD_COND_INITIALIZER; 9 | pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER; 10 | 11 | void process_msg() 12 | { 13 | struct msg *mp; 14 | for(;;) { 15 | pthread_mutex_lock(&qlock); 16 | while(workq == NULL) 17 | pthread_cond_wait(&qready, &qlock); 18 | mp = workq; 19 | workq = mp->m_next; 20 | pthread_mutex_unlock(&qlock); 21 | } 22 | } 23 | 24 | void enqueue_msg(struct msg *mp) 25 | { 26 | pthread_mutex_lock(&qlock); 27 | mp->m_next = workq; 28 | workq = mp; 29 | pthread_mutex_unlock(&qlock); 30 | pthread_cond_signal(&qready); 31 | } -------------------------------------------------------------------------------- /apue/12_chapter/12_3&12_4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/16 4 | * source: APUE 5 | * title: 重入 6 | * language: C 7 | * 这里实现了一个getenv函数的非可重入版本和可重入版本。用mutex来保护environ只能被一个getenv函数使用,其它使用getenv的函数都会被阻塞。 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | static char envbuf[ARG_MAX]; 16 | 17 | extern char **environ; 18 | 19 | char *getenv(const char *name) 20 | { 21 | int i, len; 22 | 23 | len = strlen(name); 24 | for(i = 0; environ[i] != NULL; i++) { 25 | if((strncmp(name, environ[i], len) == 0) && 26 | environ[i][len] == '=') { 27 | strcpy(envbuf, &environ[i][len+1]); 28 | return envbuf; 29 | } 30 | } 31 | return NULL; 32 | } 33 | 34 | pthread_mutex_t env_mutex; 35 | static pthread_once_t init_done = PTHREAD_ONCE_INIT; 36 | 37 | static void thread_init() 38 | { 39 | pthread_mutexattr_t attr; 40 | 41 | pthread_mutexattr_init(&attr); 42 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 43 | pthread_mutex_init(&env_mutex, &attr); 44 | pthread_mutexattr_destroy(&attr); 45 | } 46 | 47 | int getenv_r(const char *name, char *buf, int buflen) 48 | { 49 | int i, len, olen; 50 | 51 | pthread_once(&init_done, thread_init); 52 | len = strlen(name); 53 | pthread_mutex_lock(&env_mutex); 54 | for(i = 0; environ[i] != NULL; i++) { 55 | if((strncmp(name, environ[i], len) == 0) && 56 | environ[i][len] == '=') { 57 | olen = strlen(&&environ[i][len+1]); 58 | if(olen >= buflen) { 59 | pthread_mutex_unlock(&env_mutex); 60 | return ENOSPC; 61 | } 62 | strcpy(buf, &environ[i][len+1]); 63 | pthread_mutex_unlock(&env_mutex); 64 | return 0; 65 | } 66 | } 67 | pthread_mutex_unlock(&env_mutex); 68 | return ENOENT; 69 | } 70 | -------------------------------------------------------------------------------- /apue/14_chapter/14.5_epoll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/28 4 | * source: APUE 5 | * title: epoll 6 | * language: C 7 | */ 8 | 9 | #include 10 | 11 | #define MAX_EVENTS 10 12 | 13 | struct epoll_event ev, events[MAX_EVENTS]; 14 | int listen_sock, conn_sock, nfds, epollfd; 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | socket(); 19 | bind(); 20 | listen(); 21 | 22 | epollfd = epoll_create(10); 23 | if(epollfd == -1) { 24 | perror("epoll_create"); 25 | exit(EXIT_FAILURE); 26 | } 27 | 28 | ev.events = EPOLLIN; 29 | ev.data.fd = listen_sock; 30 | if(epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) { 31 | perror("epoll_ctl : listen_sock"); 32 | exit(EXIT_FAILURE); 33 | } 34 | 35 | for(;;) { 36 | nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); 37 | if(nfds == -1) { 38 | perror("epoll_wait"); 39 | exit(EXIT_FAILURE); 40 | } 41 | 42 | for(n = 0; n < nfds; ++n) { 43 | if(events[n].data.fd == listen_sock) { 44 | conn_sock = accept(listen_sock, 45 | (struct sockaddr *)&local, &addrlen); 46 | if(conn_sock == -1) { 47 | perror("accept"); 48 | exit(EXIT_FAILURE); 49 | } 50 | setnonblocking(conn_sock); 51 | ev.events = EPOLLIN | EPOLLET; 52 | ev.data.fd = conn_sock; 53 | if(epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1) { 54 | perror("epoll_ctl : conn_sock"); 55 | exit(EXIT_FAILURE); 56 | } 57 | } 58 | else { 59 | do_use_fd(events[n].data.fd);/* read or write */ 60 | } 61 | } 62 | } 63 | 64 | return 0; 65 | } -------------------------------------------------------------------------------- /apue/14_chapter/14.5_select.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char const *argv[]) 6 | { 7 | int ret; 8 | int fd_size, i; 9 | fd_set fset; 10 | struct timeval interval; 11 | char buf[5]; 12 | int nbytes; 13 | 14 | FD_ZERO(&fset); 15 | FD_SET(STDIN_FILENO, &fset); 16 | fd_size = 1; 17 | interval.tv_sec = 5; 18 | interval.tv_usec = 0; 19 | 20 | ret = select(fd_size, &fset, NULL, NULL, &interval); 21 | if(ret > 0) { 22 | if(FD_ISSET(STDIN_FILENO, &fset)) { 23 | if(nbytes = read(STDIN_FILENO, buf, 5)) { 24 | printf("read %d bytes\n", nbytes); 25 | } 26 | } 27 | } 28 | else if(ret == 0) { 29 | printf("no fd is ready\n"); 30 | } 31 | else if(ret == -1) { 32 | printf("something is error\n"); 33 | } 34 | 35 | return 0; 36 | } -------------------------------------------------------------------------------- /apue/14_chapter/14_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | char buf[50000]; 7 | 8 | void set_fl(int fd, int flags) 9 | { 10 | int val; 11 | 12 | if((val = fcntl(fd, F_GETFL, 0)) < 0) { 13 | printf("fcntl F_GETFL error\n"); 14 | } 15 | 16 | val |= flags; 17 | 18 | if((fcntl(fd, F_SETFL, val)) < 0) { 19 | printf("fcntl F_SETFL error\n"); 20 | } 21 | } 22 | 23 | void clr_fl(int fd, int flags) 24 | { 25 | int val; 26 | 27 | if((val = fcntl(fd, F_GETFL, 0)) < 0) { 28 | printf("fcntl F_GETFL error\n"); 29 | } 30 | 31 | val &= ~flags; 32 | 33 | if((fcntl(fd, F_SETFL, val)) < 0) { 34 | printf("fcntl F_SETFL error\n"); 35 | } 36 | } 37 | 38 | int main(int argc, char const *argv[]) 39 | { 40 | int ntowrite, nwrite; 41 | char *ptr; 42 | 43 | ntowrite = read(STDIN_FILENO, buf, sizeof(buf)); 44 | fprintf(stderr, "read %d bytes\n", ntowrite); 45 | 46 | set_fl(STDOUT_FILENO, O_NONBLOCK); 47 | 48 | ptr = buf; 49 | while(ntowrite > 0) { 50 | errno = 0; 51 | nwrite = write(STDOUT_FILENO, ptr, ntowrite); 52 | fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno); 53 | 54 | if(nwrite > 0) { 55 | ptr += nwrite; 56 | ntowrite -= nwrite; 57 | } 58 | } 59 | 60 | clr_fl(STDOUT_FILENO, O_NONBLOCK); 61 | 62 | return 0; 63 | } -------------------------------------------------------------------------------- /apue/14_chapter/14_11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/28 4 | * source: APUE 5 | * title: 14.8 readn & writen 6 | * language: C 7 | */ 8 | 9 | #include 10 | 11 | ssize_t readn(int fd, void *ptr, size_t n) 12 | { 13 | size_t nleft; 14 | ssize_t nread; 15 | 16 | nleft = n; 17 | while(nleft > 0) { 18 | if((nread = read(fd, ptr, nleft)) < 0) { 19 | if(nleft == n) { 20 | return -1; 21 | } 22 | else { 23 | break; 24 | } 25 | } 26 | else if(nread == 0) { 27 | break; 28 | } 29 | nleft -= nread; 30 | ptr += nread; 31 | } 32 | 33 | return n - nleft; 34 | } 35 | 36 | ssize_t writen(int fd, const void *ptr, size_t n) 37 | { 38 | size_t nleft; 39 | ssize_t nwritten; 40 | 41 | nleft = n; 42 | while(nleft > 0) { 43 | if((nwritten = write(fd, ptr, nleft)) < 0) { 44 | if(nleft == n) { 45 | return -1; 46 | } 47 | else { 48 | break; 49 | } 50 | } 51 | else if(nwritten == 0) { 52 | break; 53 | } 54 | nleft -= nwritten; 55 | ptr += nwritten; 56 | } 57 | 58 | return n - nleft; 59 | } 60 | 61 | int main(int argc, char const *argv[]) 62 | { 63 | 64 | 65 | return 0; 66 | } -------------------------------------------------------------------------------- /apue/14_chapter/14_12.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/28 4 | * source: APUE 5 | * title: 14.9 mmap 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char const *argv[]) 16 | { 17 | int fdin, fdout; 18 | void *src, *dst; 19 | struct stat statbuf; 20 | 21 | if(argc != 3) { 22 | perror("usage : programname "); 23 | exit(EXIT_FAILURE); 24 | } 25 | 26 | if((fdin = open(argv[1], O_RDONLY)) < 0) { 27 | perror("open file for reading failed"); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | if((fdout = open(argv[2], O_RDWR | O_CREAT | O_TRUNC)) < 0) { 32 | perror("open file for writing failed"); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | if(fstat(fdin, &statbuf) < 0) { 37 | perror("fstat failed"); 38 | exit(EXIT_FAILURE); 39 | } 40 | 41 | if(lseek(fdout, statbuf.st_size - 1, SEEK_SET) == -1) { 42 | perror("lseek failed"); 43 | exit(EXIT_FAILURE); 44 | } 45 | 46 | if(write(fdout, "", 1) == -1) { 47 | perror("write failed"); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | if((src = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, 52 | fdin, 0)) == MAP_FAILED) { 53 | perror("mmap error for input"); 54 | exit(EXIT_FAILURE); 55 | } 56 | 57 | if((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, 58 | MAP_SHARED, fdout, 0)) == MAP_FAILED) { 59 | perror("mmap error for output"); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | 64 | 65 | close(fdin); 66 | close(fdout); 67 | memcpy(dst, src, statbuf.st_size); 68 | 69 | exit(EXIT_SUCCESS); 70 | } -------------------------------------------------------------------------------- /apue/14_chapter/C_14.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/28 4 | * source: APUE 5 | * title: exercise 14.8 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | void set_fl(int fd, int flags) 14 | { 15 | int val; 16 | 17 | if((val = fcntl(fd, F_GETFL, 0)) < 0) { 18 | perror("fcntl F_GETFL"); 19 | } 20 | 21 | val |= flags; 22 | 23 | if(fcntl(fd, F_SETFL, val) < 0) { 24 | perror("fcntl F_SETFL"); 25 | } 26 | } 27 | 28 | int main(int argc, char const *argv[]) 29 | { 30 | int i, n; 31 | int fd[2]; 32 | 33 | if(pipe(fd) < 0) { 34 | perror("pipe"); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | set_fl(fd[1], O_NONBLOCK); 39 | 40 | for(n = 0; ; n++) { 41 | if((i = write(fd[1], "a", 1)) != 1) { 42 | printf("write ret %d\n", i); 43 | break; 44 | } 45 | } 46 | printf("pipe capacity = %d\n", n); 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /apue/14_chapter/client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/9 4 | * source: APUE 5 | * title: exercise 4(TCP client) of chapter 16 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | int cnt = 1; 19 | struct sockaddr_in addr; 20 | int sockfd; 21 | 22 | if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 23 | perror("socket"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | addr.sin_family = AF_INET; 28 | addr.sin_port = htons(9003); 29 | inet_pton(AF_INET, "127.0.0.1", &(addr.sin_addr)); 30 | if(connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) { 31 | perror("connect"); 32 | exit(EXIT_FAILURE); 33 | } 34 | struct sockaddr_in clnt; 35 | int clnt_len = sizeof(clnt); 36 | char clnt_addr[16] = ""; 37 | getsockname(sockfd, (struct sockaddr*)&clnt, &clnt_len); 38 | inet_ntop(AF_INET, (void*)&clnt.sin_addr, clnt_addr, sizeof(clnt_addr)); 39 | printf("[%s] connect server success\n", clnt_addr); 40 | 41 | if(send(sockfd, &cnt, sizeof(cnt), 0) < 0) { 42 | perror("send"); 43 | exit(EXIT_FAILURE); 44 | } 45 | 46 | printf("%d\n", cnt); 47 | 48 | if(close(sockfd) < 0) { 49 | perror("close"); 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | exit(EXIT_SUCCESS); 54 | } -------------------------------------------------------------------------------- /apue/14_chapter/epoll.md: -------------------------------------------------------------------------------- 1 | ## epoll 2 | 3 | ### 1 epoll的电平触发和边沿触发 4 | 5 | epoll有两种事件通知方式:电平出发(LT)和边沿触发(ET)。下面我们来看看两种方式的不同点。 6 | 7 | 假设发生以下情形: 8 | 1. 管道的读端的描述符rfd已经注册到epoll实例; 9 | 2. 向管道的写端写入2KB数据; 10 | 3. epoll_wait返回,并返回可以进行读操作的文件描述符rfd; 11 | 4. 从管道中读取1KB的数据; 12 | 5. epoll_wait调用完成。 13 | 14 | 如果在添加rfd文件描述符时指定EPOLLET标志,尽管文件读取缓冲区中仍然有可读数据,上面第5步epoll_wait调用会被挂起;同时,对端可能期望收到它已经发送的数据的响应。因为边沿触发只是在监听的文件描述符上发生事件时才会传递事件。因此,第5步中调用者不会等待读取缓冲区中的部分数据。在这个例子中,由于第2步的写操作,在rfd上产生事件,然后该事件被第3步消耗。又由于第4步的读操作没有读取所有的数据,第5步对epoll_wait可能会无限阻塞。 15 | 16 | 采用EPOLLET标志的应用程序应该使用非阻塞的文件描述符,以避免阻塞的读或者写操作饿死处理多个文件描述符的任务。建议以下面的方式使用epoll的边沿触发: 17 | * 使用非阻塞的文件描述符; 18 | * 只有当read()或者write()操作返回EAGAIN时才等待事件发生。read()返回EAGAIN说明文件描述符是非阻塞的,但是,此时没有数据可读,write()类似。因此,如果返回EAGAIN,说明已经完成了任务。 19 | 20 | 相比而言,以电平方式(默认是电平出发)使用的话,epoll就是一个快速的poll。 21 | 22 | 但是,即使使用边沿触发的epoll,如果接收到多个数据块就会发生多个事件,调用者可以指定EPOLLONESHOT标志告诉epoll,在epoll_wait收到一个事件之后,就使相关的文件描述符不可用。当指定EPOLLONESHOT标志时,调用者有责任使用epoll_ctl来重新使文件描述符可用。 23 | 24 | 所以有: 25 | 电平触发(LT):发生事件了,通知你,直到你完成任务为止。这是默认方式。 26 | 边沿触发(ET):发生事件了,只通知一次,不处理拉倒。 27 | -------------------------------------------------------------------------------- /apue/15_chapter/15_1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/29 4 | * source: APUE 5 | * title: pipe 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define MAXLINE 1024 14 | 15 | int main(int argc, char const *argv[]) 16 | { 17 | int n; 18 | int fd[2]; 19 | pid_t pid; 20 | char line[MAXLINE]; 21 | 22 | if(pipe(fd) < 0) { 23 | perror("pipe"); 24 | exit(EXIT_FAILURE); 25 | } 26 | if((pid = fork()) < 0) { 27 | perror("fork"); 28 | exit(EXIT_FAILURE); 29 | } 30 | else if(pid > 0) { 31 | close(fd[0]); 32 | write(fd[1], "hello world\n", 12); 33 | } 34 | else { 35 | close(fd[1]); 36 | n = read(fd[0], line, MAXLINE); 37 | write(STDOUT_FILENO, line, n); 38 | } 39 | 40 | exit(EXIT_SUCCESS); 41 | } -------------------------------------------------------------------------------- /apue/15_chapter/15_11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/7 4 | * source: APUE 5 | * title: 15.9 shared memory 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define ARRAY_SIZE 4000 14 | #define MALLOC_SIZE 100000 15 | #define SHM_SIZE 100000 16 | #define SHM_MODE 0600 17 | 18 | char array[ARRAY_SIZE]; 19 | 20 | int main(int argc, char const *argv[]) 21 | { 22 | int shmid; 23 | char *ptr, *shmptr; 24 | 25 | printf("array[] from %lx to %lx\n", (unsigned long)&array[0], 26 | (unsigned long)&array[ARRAY_SIZE]); 27 | printf("stack around %lx\n", (unsigned long)&shmid); 28 | 29 | if((ptr = malloc(MALLOC_SIZE)) == NULL) { 30 | printf("malloc error\n"); 31 | } 32 | printf("malloced from %lx to %lx\n", (unsigned long)ptr, 33 | (unsigned long)ptr+MALLOC_SIZE); 34 | 35 | if((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0) { 36 | printf("shmget error\n"); 37 | } 38 | if((shmptr = shmat(shmid, 0, 0)) == (void *)-1) { 39 | printf("shmat error\n"); 40 | } 41 | printf("shared memory attached from %lx to %lx\n", 42 | (unsigned long)shmptr, (unsigned long)shmptr+SHM_SIZE); 43 | if(shmctl(shmid, IPC_RMID, 0) < 0) { 44 | printf("shmctl error\n"); 45 | } 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /apue/15_chapter/15_3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/29 4 | * source: APUE 5 | * title: 15.2 pipe TELL & WAIT 6 | * language: C 7 | */ 8 | 9 | static int pfd1[2], pfd2[2]; 10 | 11 | void TELL_WAIT() 12 | { 13 | if(pipe(pfd1) < 0 || pipe(pfd2) < 0) { 14 | perror("pipe"); 15 | exit(EXIT_FAILURE); 16 | } 17 | } 18 | 19 | void TELL_PARENT(pid_t pid) 20 | { 21 | if(write(pfd2[1], "c", 1) != 1) { 22 | perror("write"); 23 | exit(EXIT_FAILURE); 24 | } 25 | } 26 | 27 | void WAIT_PARENT() 28 | { 29 | char c; 30 | 31 | if(read(pfd1[0], &c, 1) != 1) { 32 | perror("read"); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | if(c != 'p') { 37 | printf("WAIT_PARENT : incorrect data\n"); 38 | } 39 | } 40 | 41 | void TELL_CHILD(pid_t pid) 42 | { 43 | if(write(pfd1[1], "p", 1) != 1) { 44 | perror("write"); 45 | exit(EXIT_FAILURE); 46 | } 47 | } 48 | 49 | void WAIT_CHILD() 50 | { 51 | char c; 52 | 53 | if(read(pfd2[0], &c, 1) != 1) { 54 | perror("read"); 55 | exit(EXIT_FAILURE); 56 | } 57 | 58 | if(c != 'c') { 59 | printf("WAIT_CHILD : incorrect data\n"); 60 | } 61 | } -------------------------------------------------------------------------------- /apue/15_chapter/15_4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/29 4 | * source: APUE 5 | * title: 15.3 popen & pclose 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define MAXLINE 1024 14 | 15 | #define PAGER "${PAGER:-more}" 16 | 17 | int main(int argc, char const *argv[]) 18 | { 19 | char line[MAXLINE]; 20 | FILE *fpin, *fpout; 21 | 22 | if(argc != 2) { 23 | fprintf(stderr, "usage : ./a.out \n"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | if((fpin = popen(argv[1], "r")) == NULL) { 28 | perror("popen"); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | if((fpout = popen(PAGER, "w")) == NULL) { 33 | perror("popen"); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | while(fgets(line, MAXLINE, fpin) != NULL) { 38 | if(fputs(line, fpout) == EOF) { 39 | fprintf(stderr, "fputs error to pipe\n"); 40 | } 41 | } 42 | 43 | if(ferror(fpin)) { 44 | perror("fgets"); 45 | exit(EXIT_FAILURE); 46 | } 47 | if(pclose(fpout) == -1) { 48 | perror("pclose error"); 49 | exit(EXIT_FAILURE); 50 | } 51 | 52 | exit(EXIT_SUCCESS); 53 | } -------------------------------------------------------------------------------- /apue/15_chapter/15_6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/5 4 | * source: APUE 5 | * title: 15.3 popen 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | int main(int argc, char const *argv[]) 13 | { 14 | int c; 15 | 16 | while((c = getchar()) != EOF) { 17 | if(isupper(c)) { 18 | c = tolower(c); 19 | } 20 | 21 | if(putchar(c) == EOF) { 22 | fprintf(stderr, "output error\n"); 23 | } 24 | 25 | if(c == '\n') { 26 | fflush(stdout); 27 | } 28 | } 29 | 30 | return 0; 31 | } -------------------------------------------------------------------------------- /apue/15_chapter/15_7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/5 4 | * source: APUE 5 | * title: 15.3 popen 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #define MAXLINE 64 13 | 14 | int main(int argc, char const *argv[]) 15 | { 16 | char line[MAXLINE]; 17 | FILE *fpin; 18 | 19 | if((fpin = popen("./my", "r")) == NULL) { 20 | fprintf(stderr, "popen error\n"); 21 | } 22 | 23 | for(;;) { 24 | fputs("prompt> ", stdout); 25 | fflush(stdout); 26 | if(fgets(line, MAXLINE, fpin) == NULL) { 27 | break; 28 | } 29 | if(fputs(line, stdout) == EOF) { 30 | fprintf(stderr, "fputs error to pipe\n"); 31 | break; 32 | } 33 | } 34 | 35 | if(pclose(fpin) == -1) { 36 | fprintf(stderr, "pclose error\n"); 37 | } 38 | putchar('\n'); 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /apue/16_chapter/16_exercise4_tcp_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/9 4 | * source: APUE 5 | * title: exercise 4(TCP server) of chapter 16 6 | * language: C 7 | */ -------------------------------------------------------------------------------- /apue/16_chapter/16_exercise_1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/9 4 | * source: APUE 5 | * title: exercise 1 of chapter 16 6 | * language: C 7 | */ 8 | 9 | #include 10 | 11 | int main(int argc, char const *argv[]) 12 | { 13 | unsigned int x = 0x04030201; 14 | unsigned char *p = (unsigned char*)&x; 15 | unsigned char c = *p; 16 | if(c == 0x04) { 17 | printf("Big Endian\n"); 18 | } 19 | else if(c == 0x01) { 20 | printf("Little Endian\n"); 21 | } 22 | else { 23 | printf("unknown Endian\n"); 24 | } 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /apue/16_chapter/16_exercise_2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/9 4 | * source: APUE 5 | * title: exercise 2 of chapter 16 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | void print_stat(struct stat *st) 18 | { 19 | printf("%x\n", st->st_dev); 20 | printf("%x\n", st->st_ino); 21 | printf("%x\n", st->st_mode); 22 | printf("%x\n", st->st_nlink); 23 | printf("%x\n", st->st_uid); 24 | printf("%x\n", st->st_gid); 25 | printf("%x\n", st->st_rdev); 26 | printf("%x\n", st->st_size); 27 | printf("%x\n", st->st_blksize); 28 | printf("%x\n", st->st_blocks); 29 | printf("%s", ctime(&(st->st_atime))); 30 | printf("%s", ctime(&(st->st_mtime))); 31 | printf("%s", ctime(&(st->st_ctime))); 32 | } 33 | 34 | int main(int argc, char const *argv[]) 35 | { 36 | int sockfd1, sockfd2; 37 | struct stat st1, st2; 38 | 39 | if((sockfd1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 40 | printf("socket error\n"); 41 | return EXIT_FAILURE; 42 | } 43 | 44 | if((sockfd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 45 | printf("socket error\n"); 46 | return EXIT_FAILURE; 47 | } 48 | 49 | if(fstat(sockfd1, &st1) < 0) { 50 | printf("fstat error\n"); 51 | return EXIT_FAILURE; 52 | } 53 | 54 | if(fstat(sockfd2, &st2) < 0) { 55 | printf("fstat error\n"); 56 | return EXIT_FAILURE; 57 | } 58 | 59 | print_stat(&st1); 60 | print_stat(&st2); 61 | 62 | if(close(sockfd1) < 0) { 63 | printf("close socket fd error\n"); 64 | return EXIT_FAILURE; 65 | } 66 | 67 | if(close(sockfd2) < 0) { 68 | printf("close socket fd error\n"); 69 | return EXIT_FAILURE; 70 | } 71 | 72 | return 0; 73 | } -------------------------------------------------------------------------------- /apue/16_chapter/16_exercise_4_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/9 4 | * source: APUE 5 | * title: exercise 4(UDP client) of chapter 16 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(int argc, char const *argv[]) 15 | { 16 | int sockfd; 17 | unsigned int cnt = 0; 18 | struct sockaddr_in addr; 19 | 20 | if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 21 | perror("socket"); 22 | exit(EXIT_FAILURE); 23 | } 24 | 25 | addr.sin_family = AF_INET; 26 | addr.sin_port = htons(9003); 27 | inet_pton(AF_INET, "127.0.0.1", (void*)&(addr.sin_addr)); 28 | if(bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) { 29 | perror("bind"); 30 | exit(EXIT_FAILURE); 31 | } 32 | 33 | if(recvfrom(sockfd, &cnt, sizeof(cnt), 0, NULL, NULL) < 0) { 34 | perror("recvfrom"); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | printf("%d\n", cnt); 39 | 40 | if(close(sockfd) < 0) { 41 | perror("close socket"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | exit(EXIT_SUCCESS); 46 | } -------------------------------------------------------------------------------- /apue/16_chapter/16_exercise_4_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/9 4 | * source: APUE 5 | * title: exercise 4(UDP server) of chapter 16 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char const *argv[]) 16 | { 17 | int sockfd; 18 | unsigned int cnt = 0; 19 | FILE *pf = NULL; 20 | struct sockaddr_in addr; 21 | 22 | if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 23 | perror("socket"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | /* 此题要求得到下面的命令的结果,但是用popen有得到的是错误的结果,不知为何*/ 28 | /* 不过这里的通信是正确的 */ 29 | if((pf = popen("ps aux | wc -l", "r")) == NULL) { 30 | perror("popen"); 31 | exit(EXIT_FAILURE); 32 | } 33 | 34 | fread((void*)&cnt, sizeof(cnt), 1, pf); 35 | printf("%d\n", cnt); 36 | 37 | if(pclose(pf) < 0) { 38 | perror("pclose"); 39 | exit(EXIT_FAILURE); 40 | } 41 | 42 | memset(&addr, 0, sizeof(addr)); 43 | addr.sin_family = AF_INET; 44 | addr.sin_port = htons(9003); 45 | inet_pton(AF_INET, "127.0.0.1", (void*)&(addr.sin_addr)); 46 | if(sendto(sockfd, &cnt, sizeof(cnt), 0, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) { 47 | perror("sendto"); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | if(close(sockfd) < 0) { 52 | perror("close socket"); 53 | exit(EXIT_FAILURE); 54 | } 55 | 56 | exit(EXIT_SUCCESS); 57 | } 58 | -------------------------------------------------------------------------------- /apue/16_chapter/16_exercise_4_tcp_client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/9 4 | * source: APUE 5 | * title: exercise 4(TCP client) of chapter 16 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | int cnt = 0; 19 | struct sockaddr_in addr; 20 | int sockfd; 21 | 22 | if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 23 | perror("socket"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | addr.sin_family = AF_INET; 28 | addr.sin_port = htons(9003); 29 | inet_pton(AF_INET, "127.0.0.1", &(addr.sin_addr)); 30 | if(connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) { 31 | perror("connect"); 32 | exit(EXIT_FAILURE); 33 | } 34 | 35 | if(recv(sockfd, &cnt, sizeof(cnt), 0) < 0) { 36 | perror("recv"); 37 | exit(EXIT_FAILURE); 38 | } 39 | 40 | printf("%d\n", cnt); 41 | 42 | if(close(sockfd) < 0) { 43 | perror("close"); 44 | exit(EXIT_FAILURE); 45 | } 46 | 47 | exit(EXIT_SUCCESS); 48 | } -------------------------------------------------------------------------------- /apue/16_chapter/16_exercise_4_tcp_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/9 4 | * source: APUE 5 | * title: exercise 4(TCP server) of chapter 16 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | int cnt = 10; 19 | struct sockaddr_in addr; 20 | int sockfd, datasock; 21 | 22 | if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 23 | perror("socket"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | addr.sin_family = AF_INET; 28 | addr.sin_port = htons(9003); 29 | inet_pton(AF_INET, "127.0.0.1", &(addr.sin_addr)); 30 | if(bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0) { 31 | perror("bind"); 32 | exit(EXIT_FAILURE); 33 | } 34 | 35 | if(listen(sockfd, 5) < 0) { 36 | perror("listen"); 37 | exit(EXIT_FAILURE); 38 | } 39 | 40 | if((datasock = accept(sockfd, NULL, NULL)) < 0) { 41 | perror("accept"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | if(send(datasock, &cnt, sizeof(cnt), 0) < 0) { 46 | perror("send"); 47 | exit(EXIT_FAILURE); 48 | } 49 | 50 | if(close(datasock) < 0) { 51 | perror("close"); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | if(close(sockfd) < 0) { 56 | perror("close"); 57 | exit(EXIT_FAILURE); 58 | } 59 | 60 | exit(EXIT_SUCCESS); 61 | } -------------------------------------------------------------------------------- /apue/3_chapter/3.9_55.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/12/10 4 | * source: Advanced Programming in the Unix Environment 5 | * info: 55页关于I/O的效率 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #define BUFFSIZE 4096 13 | 14 | int main() 15 | { 16 | int n; 17 | char buf[BUFFSIZE]; 18 | 19 | while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) { 20 | if(write(STDOUT_FILENO, buf, n) != n) 21 | write(STDERR_FILENO, "error", sizeof("error")); 22 | } 23 | 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /apue/3_chapter/3_exercise_2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/12/10 4 | * source: APUE 5 | * info: 第三章习题第二题 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define MAXN 4096 13 | #define EXIT_SUCC 0 14 | #define EXIT_FAIL -1 15 | 16 | int dup2_func(int filedes, int filedes2) 17 | { 18 | int i = 0; 19 | int n = 0; 20 | int top = 0; 21 | int stack[MAXN]; 22 | 23 | if((filedes2 > MAXN) || (filedes2 < 0)) { 24 | printf("invalid filedes2!\n"); 25 | return EXIT_FAIL; 26 | } 27 | 28 | if(filedes == filedes2) { 29 | return filedes2; 30 | } 31 | 32 | while((n = dup(filedes)) < filedes2) { 33 | if(n == -1) { 34 | printf("System can not make a filedes!\n"); 35 | return EXIT_FAIL; 36 | } 37 | stack[top++] = n; 38 | } 39 | 40 | close(filedes2); 41 | 42 | if(dup(filedes) == -1) { 43 | printf("dup function error!\n"); 44 | return EXIT_FAIL; 45 | } 46 | 47 | for(i = 0; i < top; ++i) { 48 | close(stack[i]); 49 | } 50 | 51 | return filedes2; 52 | } 53 | 54 | int main(int argc, char *argv[]) 55 | { 56 | int filedes, filedes2; 57 | 58 | if(argc != 3) { 59 | printf("Parameter error!\n"); 60 | return EXIT_FAIL; 61 | } 62 | 63 | filedes = open(argv[1], O_RDWR); 64 | if(filedes == -1) { 65 | printf("Error! System cannot open %s\n", argv[1]); 66 | return EXIT_FAIL; 67 | } 68 | 69 | filedes2 = atoi(argv[2]); 70 | if(dup2_func(filedes, filedes2) != EXIT_FAIL) { 71 | write(filedes2, "test", sizeof("test")); 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /apue/6_chapter/6.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct passwd* getpwnam_user(const char *name) 6 | { 7 | struct passwd *ptr; 8 | 9 | setpwent(); 10 | while((ptr = getpwent()) != NULL) { 11 | if(strcmp(name, ptr->pw_name) == 0) 12 | break; 13 | } 14 | endpwent(); 15 | return ptr; 16 | } 17 | 18 | int main() 19 | { 20 | struct passwd *pd = getpwnam_user("no"); 21 | if(pd) { 22 | printf("user name: %s\n", pd->pw_name); 23 | printf("pw_passwd: %s\n", pd->pw_passwd); 24 | printf("user ID: %d\n", pd->pw_uid); 25 | printf("user GID: %d\n", pd->pw_gid); 26 | printf("pw_gecos: %s\n", pd->pw_gecos); 27 | printf("dir %s\n", pd->pw_dir); 28 | printf("pw_shell: %s\n", pd->pw_shell); 29 | } 30 | 31 | return 0; 32 | } -------------------------------------------------------------------------------- /apue/8_chapter/8.13.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/4/2 4 | * source: APUE 5 | * chapter: 8.13 6 | * info: system 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int system(const char *cmdstring) 15 | { 16 | pid_t pid; 17 | int status; 18 | 19 | if(cmdstring == NULL) 20 | return 1; 21 | 22 | if((pid = fork()) < 0) { 23 | status = -1; 24 | } 25 | else if(pid == 0) { 26 | execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 27 | _exit(127); 28 | } 29 | else { 30 | while(waitpid(pid, &status, 0) < 0) { 31 | if(errno != EINTR) { 32 | status = -1; 33 | break; 34 | } 35 | } 36 | } 37 | 38 | return status; 39 | } 40 | 41 | int main() 42 | { 43 | system("date"); 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /apue/8_chapter/8.16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend) 8 | { 9 | static long clktck = 0; 10 | 11 | if(clktck == 0) { 12 | if((clktck = sysconf(_SC_CLK_TCK)) < 0) { 13 | printf("sysconf error\n"); 14 | } 15 | } 16 | 17 | printf("real: %7.2f\n", real / (double)clktck); 18 | printf("user: %7.2f\n", 19 | (tmsend->tms_utime - tmsstart->tms_utime) / (double)clktck); 20 | printf("sys: %7.2f\n", 21 | (tmsend->tms_stime - tmsstart->tms_stime) / (double)clktck); 22 | printf("child user: %7.2f\n", 23 | (tmsend->tms_cutime - tmsstart->tms_cutime) / (double)clktck); 24 | printf("child sys: %7.2f\n", 25 | (tmsend->tms_cstime - tmsstart->tms_cstime) / (double)clktck); 26 | } 27 | 28 | void do_cmd(char *cmd) 29 | { 30 | struct tms tmsstart, tmsend; 31 | clock_t start, end; 32 | int status; 33 | 34 | printf("\ncommand: %s\n", cmd); 35 | 36 | if((start = times(&tmsstart)) == -1) { 37 | printf("times error\n"); 38 | exit(1); 39 | } 40 | 41 | if((status = system(cmd)) < 0) { 42 | printf("system error\n"); 43 | exit(2); 44 | } 45 | 46 | if((end = times(&tmsend)) == -1) { 47 | printf("times error\n"); 48 | exit(3); 49 | } 50 | 51 | pr_times(end - start, &tmsstart, &tmsend); 52 | } 53 | 54 | int main(int argc, char *argv[]) 55 | { 56 | int i; 57 | 58 | setbuf(stdout, NULL); 59 | for(i = 1; i < argc; ++i) { 60 | do_cmd(argv[i]); 61 | } 62 | exit(0); 63 | } -------------------------------------------------------------------------------- /apue/8_chapter/8.3_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int glob = 6; 5 | char buf[] = "a write to stdout"; 6 | 7 | int main() 8 | { 9 | int var; 10 | pid_t pid; 11 | 12 | var = 88; 13 | if(write(STDOUT_FILENO, buf, sizeof(buf) - 1) != sizeof(buf) - 1) { 14 | printf("write error\n"); 15 | } 16 | printf("before fork\n"); 17 | 18 | if((pid = fork()) < 0) { 19 | printf("fork error\n"); 20 | } 21 | else if(pid == 0) { 22 | glob++; 23 | var++; 24 | sleep(2); 25 | } 26 | else { 27 | //sleep(2); 28 | } 29 | 30 | printf("ppid = %d, pid = %d, glob = %d, var = %d\n", getppid(), getpid(), glob, var); 31 | printf("ppid = %d, pid = %d, g_a = %p, v_a = %p\n", getppid(), getpid(), &glob, &var); 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /apue/8_chapter/8_ex_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void test() 5 | { 6 | pid_t pid; 7 | 8 | printf("before vfork"); 9 | if((pid = vfork()) < 0) { 10 | printf("vfork error\n"); 11 | } 12 | else if(pid == 0) { 13 | printf("child\n"); 14 | fclose(stdout); 15 | exit(0); 16 | } 17 | printf("parent\n"); 18 | exit(0); 19 | } 20 | 21 | void zom() 22 | { 23 | pid_t pid; 24 | 25 | if((pid = fork()) < 0) { 26 | printf("fork error\n"); 27 | } 28 | } 29 | 30 | int main() 31 | { 32 | zom(); 33 | 34 | return 0; 35 | } -------------------------------------------------------------------------------- /apue/8_chapter/8_ex_6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define PSCMD "ps -o pid,ppid,state,tty,command" 5 | 6 | int main() 7 | { 8 | pid_t pid; 9 | 10 | if((pid = fork()) < 0) { 11 | fprintf(stderr, "fork error\n"); 12 | return EXIT_FAILURE; 13 | } 14 | else if(pid == 0) { 15 | exit(0); 16 | } 17 | 18 | sleep(4); 19 | system(PSCMD); 20 | 21 | exit(0); 22 | } 23 | -------------------------------------------------------------------------------- /apue/9_chapter/9_1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luofeng 3 | * date: 2014/6/6 4 | * source: APUE 5 | * title: 孤儿进程组 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | static void sig_hup(int signo) 16 | { 17 | printf("SIGHUP received, pid = %d\n", getpid()); 18 | } 19 | 20 | static void pr_ids(char *name) 21 | { 22 | printf("%s: pid = %d, ppid = %d, pgrp = %d, tpgrp = %d\n", 23 | name, getpid(), getppid(), getpgrp(), tcgetpgrp(STDIN_FILENO)); 24 | fflush(stdout); 25 | } 26 | 27 | int main(int argc, char const *argv[]) 28 | { 29 | char c; 30 | pid_t pid; 31 | 32 | pr_ids("parent"); 33 | if((pid = fork()) < 0) { 34 | fprintf(stderr, "fork failed\n"); 35 | } 36 | else if(pid > 0) { 37 | sleep(5); 38 | exit(0); 39 | } 40 | else { 41 | pr_ids("child"); 42 | signal(SIGHUP, sig_hup); 43 | kill(getpid(), SIGTSTP); 44 | pr_ids("child"); 45 | if(read(STDIN_FILENO, &c, 1) != 1) { 46 | printf("read error from controlling TTY, errno = %d\n", errno); 47 | } 48 | exit(0); 49 | } 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /apue/9_chapter/9_exercise_2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luofeng 3 | * date: 2014/6/6 4 | * source: APUE 5 | * title: 6 | * language: C 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char const *argv[]) 16 | { 17 | pid_t pid; 18 | char c; 19 | 20 | if((pid = fork()) < 0) { 21 | fprintf(stderr, "fork failed\n"); 22 | } 23 | else if(pid > 0) { 24 | exit(0); 25 | } 26 | else { 27 | pid_t sid = setsid(); 28 | /* pid:进程ID,pgid:进程组ID,sid:会话首进程的进程ID */ 29 | printf("pid = %d, pgid = %d, sid = %d\n", getpid(), getpgid(getpid()), sid); 30 | if(read(STDOUT_FILENO, &c, 1) == -1) { 31 | fprintf(stderr, "%s\n", strerror(errno)); 32 | } 33 | exit(0); 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /apue/README.md: -------------------------------------------------------------------------------- 1 | ## Linux 2 | 3 | [回到主目录](https://github.com/luofengmacheng/algorithms) 4 | 5 | 1 [poll实现的一个简单的服务器](https://github.com/luofengmacheng/algorithms/blob/master/apue/14_chapter/server_poll.c) 6 | -------------------------------------------------------------------------------- /apue/reentrant&signal.txt: -------------------------------------------------------------------------------- 1 | 可重入性与线程安全 2 | 1 概念 3 | 可重入性是指多个线程调用时,不用担心数据丢失和程序数据损坏。 4 | 线程安全是指一个函数可以被多个线程安全地调用。 5 | 6 | 2 不同点 7 | 线程安全只需要考虑多个线程调用某个函数时,结果跟单线程调用该函数的结果一样。而可重入需要考虑各方面的因素,主要就是信号带来的影响。当一个函数在执行时被信号打断了,就会去执行信号处理函数,函数当然不知道信号处理函数中会调用什么代码,那么,信号处理函数的代码的执行可能会对函数本身的执行造成影响。 8 | 一个程序是线程安全的,但是它不一样是可重入的。 9 | 一个程序是可重入的,那么,它一定是线程安全的。 10 | 11 | 3 举例说明 12 | 3.1 对于errno,由于每个线程中都有一个副本,因此,如果一个函数调用了一个修改errno的函数,那么该函数是线程安全的,因为,多个线程同时调用这个函数并不会对errno的使用产生错误。然而,却不是可重入的。 13 | void func() 14 | { 15 | func1(); 16 | if(errno == EFAULT) { 17 | /* some error handling */ 18 | } 19 | } 20 | func1()的调用会修改errno,如果在func1()和if语句之间收到了信号,在信号处理函数中会调用另外一个修改errno的函数,那么信号处理函数返回后,if语句检查的就是信号处理函数中的那个函数的errno,明显发生了错误。 21 | 22 | 3.2 如果一个函数使用了静态变量,那么,它可能不是线程安全的,当然,也可能不是可重入的。 23 | int func() 24 | { 25 | static int i = 1; 26 | ++i; 27 | return i; 28 | } 29 | 如上的代码,该函数使用了静态变量i,然后对i自增,返回i。如果两个线程同时调用两个函数,就会发生错误。对于这种情况可以使用锁来保证i的互斥访问,或者使用局部变量。 30 | 31 | 4 小结 32 | 线程安全考虑的只是代码多次交叉执行时是否会发生错误或者不一致的情况,如果有下列情况就不是线程安全的: 33 | (1)使用了静态变量。如果代码使用了静态变量,多次执行时,不同的线程可能会看到不一致的结果。 34 | (2)结果存放在静态存储区中。同(1)一样,将结果存放在静态存储区中,多个线程可能会先后修改该存储区,导致并不是自己想要的结果。 35 | 因此,对于线程安全主要考虑的是静态变量,通过对静态变量进行加锁或者使用局部变量可以得到函数的线程安全版本。 36 | 37 | 可重入性在考虑线程安全的基础上还考虑了信号的影响,如果有下列情况就不是可重入的: 38 | 信号处理函数中调用了不可重入函数。如果信号处理函数调用了不可重入函数,那么在信号发生后,信号处理函数的结果是未知的。 39 | 这里没有列出静态变量的情形,因为不是线程安全的,肯定是不可重入的。 40 | 需要一提的是,malloc、free和I/O标准库是不可重入的。 41 | -------------------------------------------------------------------------------- /apue/rpc/echo/Makefile: -------------------------------------------------------------------------------- 1 | server:echo_svc.c server_func.c echo_xdr.c 2 | gcc -o server echo_svc.c server_func.c echo_xdr.c 3 | 4 | client:client.c echo_clnt.c echo_xdr.c 5 | gcc -o client client.c echo_clnt.c echo_xdr.c 6 | 7 | -------------------------------------------------------------------------------- /apue/rpc/echo/client.c: -------------------------------------------------------------------------------- 1 | #include "echo.h" 2 | 3 | int main(int argc, char const *argv[]) 4 | { 5 | CLIENT *cl; 6 | hello in; 7 | hello_echo *outp; 8 | 9 | if(argc != 3) { 10 | fprintf(stderr, "usage: client \n"); 11 | exit(0); 12 | } 13 | 14 | cl = clnt_create(argv[1], ECHO_PROG, ECHO_VERS, "tcp"); 15 | strncpy(in.text, argv[2], strlen(argv[2])); 16 | in.text[strlen(argv[2])] = 0; 17 | if((outp = echoproc_1(&in, cl)) == NULL) { 18 | fprintf(stderr, "%s\n", clnt_sperror(cl, argv[1])); 19 | exit(0); 20 | } 21 | printf("result: %s\n", outp->text_echo); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /apue/rpc/echo/echo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #ifndef _ECHO_H_RPCGEN 7 | #define _ECHO_H_RPCGEN 8 | 9 | #include 10 | 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | struct hello { 18 | char text[256]; 19 | }; 20 | typedef struct hello hello; 21 | 22 | struct hello_echo { 23 | char text_echo[256]; 24 | }; 25 | typedef struct hello_echo hello_echo; 26 | 27 | #define ECHO_PROG 0x31230000 28 | #define ECHO_VERS 1 29 | 30 | #if defined(__STDC__) || defined(__cplusplus) 31 | #define ECHOPROC 1 32 | extern hello_echo * echoproc_1(hello *, CLIENT *); 33 | extern hello_echo * echoproc_1_svc(hello *, struct svc_req *); 34 | extern int echo_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); 35 | 36 | #else /* K&R C */ 37 | #define ECHOPROC 1 38 | extern hello_echo * echoproc_1(); 39 | extern hello_echo * echoproc_1_svc(); 40 | extern int echo_prog_1_freeresult (); 41 | #endif /* K&R C */ 42 | 43 | /* the xdr functions */ 44 | 45 | #if defined(__STDC__) || defined(__cplusplus) 46 | extern bool_t xdr_hello (XDR *, hello*); 47 | extern bool_t xdr_hello_echo (XDR *, hello_echo*); 48 | 49 | #else /* K&R C */ 50 | extern bool_t xdr_hello (); 51 | extern bool_t xdr_hello_echo (); 52 | 53 | #endif /* K&R C */ 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* !_ECHO_H_RPCGEN */ 60 | -------------------------------------------------------------------------------- /apue/rpc/echo/echo.x: -------------------------------------------------------------------------------- 1 | struct hello { 2 | char text[256]; 3 | }; 4 | 5 | struct hello_echo { 6 | char text_echo[256]; 7 | }; 8 | 9 | program ECHO_PROG { 10 | version ECHO_VERS { 11 | hello_echo ECHOPROC(hello) = 1; 12 | } = 1; 13 | } = 0x31230000; 14 | -------------------------------------------------------------------------------- /apue/rpc/echo/echo_clnt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #include /* for memset */ 7 | #include "echo.h" 8 | 9 | /* Default timeout can be changed using clnt_control() */ 10 | static struct timeval TIMEOUT = { 25, 0 }; 11 | 12 | hello_echo * 13 | echoproc_1(hello *argp, CLIENT *clnt) 14 | { 15 | static hello_echo clnt_res; 16 | 17 | memset((char *)&clnt_res, 0, sizeof(clnt_res)); 18 | if (clnt_call (clnt, ECHOPROC, 19 | (xdrproc_t) xdr_hello, (caddr_t) argp, 20 | (xdrproc_t) xdr_hello_echo, (caddr_t) &clnt_res, 21 | TIMEOUT) != RPC_SUCCESS) { 22 | return (NULL); 23 | } 24 | return (&clnt_res); 25 | } 26 | -------------------------------------------------------------------------------- /apue/rpc/echo/echo_xdr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #include "echo.h" 7 | 8 | bool_t 9 | xdr_hello (XDR *xdrs, hello *objp) 10 | { 11 | register int32_t *buf; 12 | 13 | int i; 14 | if (!xdr_vector (xdrs, (char *)objp->text, 256, 15 | sizeof (char), (xdrproc_t) xdr_char)) 16 | return FALSE; 17 | return TRUE; 18 | } 19 | 20 | bool_t 21 | xdr_hello_echo (XDR *xdrs, hello_echo *objp) 22 | { 23 | register int32_t *buf; 24 | 25 | int i; 26 | if (!xdr_vector (xdrs, (char *)objp->text_echo, 256, 27 | sizeof (char), (xdrproc_t) xdr_char)) 28 | return FALSE; 29 | return TRUE; 30 | } 31 | -------------------------------------------------------------------------------- /apue/rpc/echo/server_func.c: -------------------------------------------------------------------------------- 1 | #include "echo.h" 2 | 3 | hello_echo *echoproc_1_svc(hello *inp, struct svc_req *rqstp) 4 | { 5 | static hello_echo out; 6 | strncpy(out.text_echo, inp->text, strlen(inp->text)); 7 | out.text_echo[strlen(inp->text)] = 0; 8 | 9 | return (&out); 10 | } 11 | -------------------------------------------------------------------------------- /apue/rpc/square/README.md: -------------------------------------------------------------------------------- 1 | 本文件夹包含6个源文件,其中有三个是通过rpcgen生成的。 2 | 用户编写的程序有: 3 | square.x client.c server.c 4 | 5 | 对square.x运行以下命令: 6 | ``` 7 | rpcgen -C square.x 8 | ``` 9 | 就会生成三个文件:square.h square_clnt.c square_svc.c square_xdr.c 10 | 11 | square.x中定义了远程过程调用中传递的参数以及过程的定位信息(程序名,版本号,过程号),也就是客户机和服务器通信的信息。 12 | 13 | square.h中定义了客户端和服务器调用的对应的函数,比如: 14 | 15 | 在square.x中定义了一个过程:square_out SQUAREPROC(square_in),那么在square.h中就会生成 16 | ``` 17 | extern square_out * squareproc_1(square_in *, CLIENT *); 18 | extern square_out * squareproc_1_svc(square_in *, struct svc_req *); 19 | ``` 20 | squareproc_1()是客户端上执行的函数,squareproc_1_svc是()是服务器上执行的函数。 21 | 22 | square_clnt.c客户端上执行的函数squareproc_1()的定义。 23 | 24 | square_svc.c是服务器的主要两个函数,一个是main函数,其中包含了RPC的一些初始化操作,另一个是square_proc_1(),它对收到的请求进行响应,并调用合适的函数。 25 | 26 | client.c是用户编写的客户端主程序,它可以创建CLIENT,并调用squareproc_1()。 27 | 28 | server.c是用户编写的远程过程squareproc_1_svc()的实际代码。 29 | 30 | 小结: 31 | * square.x 定义了客户端与服务器通信时传递的参数和过程的定位信息。 32 | * client.c 客户端可以自己决定调用本地函数。 33 | * server.c 定义服务器的远程过程。 34 | -------------------------------------------------------------------------------- /apue/rpc/square/client.c: -------------------------------------------------------------------------------- 1 | #include "square.h" 2 | 3 | int main(int argc, char const *argv[]) 4 | { 5 | CLIENT *cl; 6 | square_in in; 7 | square_out *outp; 8 | 9 | if(argc != 3) { 10 | fprintf(stderr, "usage: client \n"); 11 | exit(0); 12 | } 13 | 14 | cl = clnt_create(argv[1], SQUARE_PROG, SQUARE_VERS, "tcp"); 15 | in.arg1 = atoll(argv[2]); 16 | if((outp = squareproc_1(&in, cl)) == NULL) { 17 | fprintf(stderr, "%s\n", clnt_sperror(cl, argv[1])); 18 | exit(0); 19 | } 20 | printf("result: %ld\n", outp->res1); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /apue/rpc/square/server.c: -------------------------------------------------------------------------------- 1 | #include "square.h" 2 | 3 | square_out *squareproc_1_svc(square_in *inp, struct svc_req *rqstp) 4 | { 5 | static square_out out; 6 | out.res1 = inp->arg1 * inp->arg1; 7 | 8 | return (&out); 9 | } -------------------------------------------------------------------------------- /apue/rpc/square/square.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #ifndef _SQUARE_H_RPCGEN 7 | #define _SQUARE_H_RPCGEN 8 | 9 | #include 10 | 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | struct square_in { 18 | long arg1; 19 | }; 20 | typedef struct square_in square_in; 21 | 22 | struct square_out { 23 | long res1; 24 | }; 25 | typedef struct square_out square_out; 26 | 27 | #define SQUARE_PROG 0x31230000 28 | #define SQUARE_VERS 1 29 | 30 | #if defined(__STDC__) || defined(__cplusplus) 31 | #define SQUAREPROC 1 32 | extern square_out * squareproc_1(square_in *, CLIENT *); 33 | extern square_out * squareproc_1_svc(square_in *, struct svc_req *); 34 | extern int square_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); 35 | 36 | #else /* K&R C */ 37 | #define SQUAREPROC 1 38 | extern square_out * squareproc_1(); 39 | extern square_out * squareproc_1_svc(); 40 | extern int square_prog_1_freeresult (); 41 | #endif /* K&R C */ 42 | 43 | /* the xdr functions */ 44 | 45 | #if defined(__STDC__) || defined(__cplusplus) 46 | extern bool_t xdr_square_in (XDR *, square_in*); 47 | extern bool_t xdr_square_out (XDR *, square_out*); 48 | 49 | #else /* K&R C */ 50 | extern bool_t xdr_square_in (); 51 | extern bool_t xdr_square_out (); 52 | 53 | #endif /* K&R C */ 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* !_SQUARE_H_RPCGEN */ 60 | -------------------------------------------------------------------------------- /apue/rpc/square/square.x: -------------------------------------------------------------------------------- 1 | struct square_in { 2 | long arg1; 3 | }; 4 | 5 | struct square_out { 6 | long res1; 7 | }; 8 | 9 | program SQUARE_PROG { 10 | version SQUARE_VERS { 11 | square_out SQUAREPROC(square_in) = 1; 12 | } = 1; 13 | } = 0x31230000; -------------------------------------------------------------------------------- /apue/rpc/square/square_clnt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #include /* for memset */ 7 | #include "square.h" 8 | 9 | /* Default timeout can be changed using clnt_control() */ 10 | static struct timeval TIMEOUT = { 25, 0 }; 11 | 12 | square_out * 13 | squareproc_1(square_in *argp, CLIENT *clnt) 14 | { 15 | static square_out clnt_res; 16 | 17 | memset((char *)&clnt_res, 0, sizeof(clnt_res)); 18 | if (clnt_call (clnt, SQUAREPROC, 19 | (xdrproc_t) xdr_square_in, (caddr_t) argp, 20 | (xdrproc_t) xdr_square_out, (caddr_t) &clnt_res, 21 | TIMEOUT) != RPC_SUCCESS) { 22 | return (NULL); 23 | } 24 | return (&clnt_res); 25 | } 26 | -------------------------------------------------------------------------------- /apue/rpc/square/square_xdr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Please do not edit this file. 3 | * It was generated using rpcgen. 4 | */ 5 | 6 | #include "square.h" 7 | 8 | bool_t 9 | xdr_square_in (XDR *xdrs, square_in *objp) 10 | { 11 | register int32_t *buf; 12 | 13 | if (!xdr_long (xdrs, &objp->arg1)) 14 | return FALSE; 15 | return TRUE; 16 | } 17 | 18 | bool_t 19 | xdr_square_out (XDR *xdrs, square_out *objp) 20 | { 21 | register int32_t *buf; 22 | 23 | if (!xdr_long (xdrs, &objp->res1)) 24 | return FALSE; 25 | return TRUE; 26 | } 27 | -------------------------------------------------------------------------------- /apue/threadpool/Makefile: -------------------------------------------------------------------------------- 1 | test: threadpool.o test_threadpool.o 2 | gcc -o test threadpool.o test_threadpool.o -lpthread 3 | threadpool.o:threadpool.c 4 | test_threadpool.o:test_threadpool.c 5 | -------------------------------------------------------------------------------- /apue/threadpool/test_threadpool.c: -------------------------------------------------------------------------------- 1 | /* test_threadpool.c */ 2 | #include 3 | #include "threadpool.h" 4 | 5 | void *routine(void *arg) 6 | { 7 | printf("%d\n", (int)arg); 8 | return NULL; 9 | } 10 | 11 | int main(int argc, char const *argv[]) 12 | { 13 | threadpool_t *tp = threadpool_create(); 14 | 15 | int i = 0; 16 | while(i < 10) { 17 | threadpool_insert_work(tp, routine, (void*)i); 18 | ++i; 19 | } 20 | 21 | threadpool_destroy(tp); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /apue/threadpool/threadpool.h: -------------------------------------------------------------------------------- 1 | /* threadpool.h */ 2 | #ifndef _THREAD_POOL_H 3 | #define _THREAD_POOL_H 4 | 5 | #include 6 | 7 | #define THREADPOOL_MAX_THREADS 8 /* 最大线程数 */ 8 | #define THREADPOOL_MIN_THREADS 1 /* 最小线程数 */ 9 | #define THREADPOOL_DEF_THREADS 4 /* 默认线程数 */ 10 | 11 | struct work_queue_s { 12 | void* (*routine)(void *); /* 工作例程 */ 13 | void *arg; /* 工作例程参数 */ 14 | struct work_queue_s *next; 15 | }; 16 | 17 | typedef struct work_queue_s work_queue_t; /* 工作队列 */ 18 | 19 | struct worker_queue_s { 20 | pthread_t id; /* 线程ID */ 21 | struct worker_queue_s *next; 22 | }; 23 | 24 | typedef struct worker_queue_s worker_queue_t; /* 工作者队列 */ 25 | 26 | struct threadpool_s { 27 | int finish; /* 是否结束 */ 28 | int cur_thread_num; /* 当前线程数 */ 29 | worker_queue_t *workers; /* 工作者队列 */ 30 | work_queue_t *first; /* 工作队列首指针 */ 31 | work_queue_t *last; /* 工作队列尾指针 */ 32 | pthread_cond_t queue_nonempty; /* 工作队列是否为空的条件变量 */ 33 | pthread_mutex_t queue_lock; /* 工作队列锁 */ 34 | }; 35 | 36 | typedef struct threadpool_s threadpool_t; /* 线程池结构 */ 37 | 38 | /* 创建线程池 */ 39 | threadpool_t* threadpool_create(); 40 | 41 | /* 向线程池中添加工作 */ 42 | int threadpool_insert_work(threadpool_t*, void* (*)(void *), void*); 43 | 44 | /* 创建工作者 */ 45 | int threadpool_create_worker(threadpool_t*); 46 | 47 | /* 销毁工作者 */ 48 | int threadpool_destroy_worker(threadpool_t*); 49 | 50 | /* 销毁线程池 */ 51 | int threadpool_destroy(threadpool_t*); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /apue/threadpool/threadpool.txt: -------------------------------------------------------------------------------- 1 | 关于线程池的一点想法 2 | “池”化技术都是比较类似的,都是应对“小”的特点而开发出来的,比如: 3 | 内存池是针对小块内存的申请和释放过于频繁导致的效率低下问题。先分配一定量的内存,按照大小分类,当程序需要小块内存(这里的小是相对而言的,看实现方式)时,就从某个大块内存中截取小块内存,用完了之后,就再放入大块内存中。当然,这里说的只是基本的思想,在实现的时候,有针对不同的分配方式的优化方案。 4 | 线程池是针对大量短任务申请线程和释放线程过于频繁导致的效率低下问题,如果任务运行时间较短,而申请线程和释放线程的时间较长,那么频繁地进行线程的申请和释放必将降低效率。先分配一定数量的线程,如果有任务到达,就从线程池中取出一个线程处理任务,处理完成后,将线程归还给线程池。于是,就避免了过于频繁线程的申请和释放导致的效率低下问题。而且,还可以根据当前线程的负载进行线程的增加和减少,当现有的线程比较忙碌时,可以增加线程,但是,线程也不能无限增加,因为过多的线程会增大系统开销,当现有的线程多数处于空闲时,可以减少线程。 5 | 当然,还有其它的池化技术,不过,原理大体都是类似的。 6 | 7 | 线程池的实现: 8 | 任务队列:保存需要交给线程来执行的任务。 9 | 执行线程队列:正在执行任务的线程。 10 | 空闲线程栈:存放空闲的线程。 11 | 工作流程: 12 | 创建线程池。每个线程都等待工作到达的信号。并将所有线程放入到空闲线程栈中。 13 | 客户生成任务,将任务放到任务队列。 14 | 空闲线程栈中的线程收到信号(有任务来了),获取任务,处理任务。再查看是否有任务,如果有则再次获取任务并处理,如果没有,就将线程放入到空闲线程栈中。 15 | -------------------------------------------------------------------------------- /bop/3.1.md: -------------------------------------------------------------------------------- 1 | ## 编程之美3.1:字符串移位包含的问题 2 | 3 | > 给定两个字符串s1和s2,要求判定s2是否能够被s1做循环移位得到的字符串包含。例如,给定s1 = AABCD和s2 = CDAA,返回true;给定s1 = ABCD和s2 = ACBD,返回false。 4 | 5 | ### 1 分析 6 | 7 | 方法1:对s1做s1.size()次移位,然后判断移位后的字符串是否包含s2。显然,时间复杂度太高了。 8 | 9 | 方法2:s1进行移位的字符串一定包含在s1s1中,因此,可以直接判断s1s1是否包含s2。 10 | -------------------------------------------------------------------------------- /bop/3.11.md: -------------------------------------------------------------------------------- 1 | ## 编程之美3.11:程序改错 2 | 3 | > 修改下面一个带有错误的二分查找源码。 4 | 5 | ``` C 6 | int bisearch(char **arr, int b, int e, char *v) 7 | { 8 | int minIndex = b, maxIndex = e, midIndex; 9 | while(minIndex < maxIndex) { 10 | midIndex = (minIndex + maxIndex) / 2; 11 | if(strcmp(arr[midIndex], v) <= 0) { 12 | minIndex = midIndex; 13 | } 14 | else { 15 | maxIndex = midIndex - 1; 16 | } 17 | } 18 | if(!strcmp(arr[maxIndex], v)) { 19 | return maxIndex; 20 | } 21 | else { 22 | return -1; 23 | } 24 | } 25 | ``` 26 | 27 | error 1: 当midIndex == minIndex且arr[minIndex] <= v时,发生死循环。将循环条件修改为minIndex < maxIndex - 1。 28 | 29 | error 2: 求midIndex时,minIndex + maxIndex可能会溢出。将求midIndex的表达式改为midIndex = minIndex + (maxIndex - minIndex) / 2。 30 | 31 | error 3: 书中将maxIndex = midIndex - 1;修改为maxIndex = midIndex;不知道是为什么。 32 | 33 | error 4: 循环结束后,有可能maxIndex和minIndex位置的值等于v,因此,先判断maxIndex,再判断minIndex。 34 | -------------------------------------------------------------------------------- /bop/3.6.md: -------------------------------------------------------------------------------- 1 | ## 编程之美3.6:编程判断两个链表是否相交 2 | 3 | > 给定两个单链表的头指针,判断这两个链表是否相交。 4 | 5 | ### 1 解法1 6 | 7 | 如果两个链表相交,那么,在一个链表中必定存在一些节点,这些节点也在另一个链表中。因此,可以对一条链表的节点建立hash表,然后查找另外一个链表,当另一个链表的某个节点也在hash表中,就说明两条链表相交。 8 | 9 | ### 2 解法2 10 | 11 | 如果两个链表相交,最后一个节点必定是共有的。因此,可以先遍历一个链表,到达链表尾部时,再遍历另外一个链表,到达尾部时与之前一个链表的尾部指针进行比较,如果相同,那么,两条链表相交。 12 | 13 | ### 3 解法3 14 | 15 | 如果两个链表相交,必定是Y型。可以先遍历两个链表,求出两个链表的长度,假设,得到两个链表的长度分别为len1和len2,用两个指针分别遍历两个链表,让较长的链表先走|len1-len2|步,再让两个指针同时走,当两个指针相等时,说明两条链表相交,而且此时相等的节点就是两个链表相交的第一个节点。 16 | 17 | ### 4 解法4 18 | 19 | 1 让其中一条链表的尾部指向头部,那么,如果两个链表相交,从另一个链表的视角来看,就存在环。于是,就转换成了判断链表是否有环的问题,可以用快慢指针。 20 | 21 | 2 将其中一条链表A的头部链接在另一个链表B的尾部,那么,如果两个链表相交,就存在环。于是,A的头部必定在环中,用一个指针遍历A,如果会回到A的头部,那么,两个链表就相交。 22 | 23 | ### 关于扩展问题 24 | 25 | 1 链表可能有环? 26 | 27 | 解法3即可。 28 | 29 | 2 找到相交的第一个节点? 30 | 31 | 解法3即可。 32 | -------------------------------------------------------------------------------- /bop/3.8.md: -------------------------------------------------------------------------------- 1 | ## 编程之美3.8:求二叉树中节点的最大距离 2 | 3 | > 如果把二叉树看成一个图,父子节点之间的连线看成是双向的,定义“距离”为两个节点之间边的个数。写一个程序求一棵二叉树中相距最远的两个节点之间的距离。 4 | 5 | ### 1 分析 6 | 7 | 二叉树中节点的最大距离必定是两个叶子节点的距离。求某个子树的节点的最大距离,有三种情况:1.两个叶子节点都出现在左子树;2.两个叶子节点都出现在右子树;3.一个叶子节点在左子树,一个叶子节点在右子树。只要求得三种情况的最大值,结果就是这个子树的节点的最大距离。 8 | 9 | int find_max_len(Node *root); 10 | 11 | case 1: 两个叶子节点都出现在左子树。find_max_len(root->pLeft); 12 | 13 | case 2: 两个叶子节点都出现在右子树。find_max_len(root->pRight); 14 | 15 | case 3: 一个出现在左子树,一个出现在右子树。distance(root->pLeft) + distance(root->pRight) + 2;其中,distance()计算子树中最远的叶子节点与根节点的距离,其实就是左子树的高度减1。 16 | 17 | ### 2 实现 18 | 19 | ``` C++ 20 | struct Node { 21 | int data; 22 | Node *pLeft; 23 | Node *pRight; 24 | }; 25 | 26 | // 计算树的高度 27 | int height(Node *root) 28 | { 29 | if(root == NULL) { 30 | return 0; 31 | } 32 | 33 | return max(height(root->pLeft), height(root->pRight)) + 1; 34 | } 35 | 36 | int find_max_len(Node *root) 37 | { 38 | if(root == NULL) { 39 | return 0; 40 | } 41 | 42 | int lmax = find_max_len(root->pLeft); // 左子树中的最大距离 43 | int rmax = find_max_len(root->pRight); // 右子树中的最大距离 44 | 45 | int lh = 0, rh = 0; 46 | 47 | if(root->pLeft) { 48 | // 左子树最远的叶子节点与根节点的距离 49 | lh = height(root->pLeft); 50 | } 51 | 52 | if(root->pRight) { 53 | // 右子树最远的叶子节点与根节点的距离 54 | rh = height(root->pRight); 55 | } 56 | 57 | return max(max(lmax, rmax), lh + rh); 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /bop/3.9.md: -------------------------------------------------------------------------------- 1 | ## 编程之美3.9:重建二叉树 2 | 3 | > 根据前序遍历和中序遍历的结果,写一个算法重建二叉树。 4 | 5 | ``` C++ 6 | // 节点定义 7 | struct NODE { 8 | NODE *pLeft; 9 | NODE *pRight; 10 | char chValue; 11 | }; 12 | 13 | // 函数声明 14 | void Rebuild(char *pPreOrder, char *pInOrder, int nTreeLen, NODE **pRoot); 15 | ``` 16 | 17 | ### 实现:递归 18 | 19 | ``` C++ 20 | void Rebuild(char *pPreOrder, char *pInOrder, int nTreeLen, NODE **pRoot) 21 | { 22 | if(pPreOrder == NULL || pInOrder == NULL) { 23 | *pRoot = NULL; 24 | return; 25 | } 26 | 27 | if(nTreeLen == 0) { 28 | *pRoot = NULL; 29 | return; 30 | } 31 | 32 | if(nTreeLen == 1) { 33 | if(*pPreOrder != *pInOrder) { 34 | cout << "invalid parameters" << endl; 35 | return; 36 | } 37 | 38 | NODE *pnode = new NODE; 39 | pnode->pLeft = NULL; 40 | pnode->pRight = NULL; 41 | pnode->chValue = *pPreOrder; 42 | *pRoot = pnode; 43 | return; 44 | } 45 | 46 | NODE *pnode = new NODE; 47 | pnode->pLeft = NULL; 48 | pnode->pRight = NULL; 49 | pnode->chValue = *pPreOrder; 50 | *pRoot = pnode; 51 | 52 | char chRoot = *pPreOrder; 53 | int leftlen = 0, rightlen = 0; 54 | 55 | while(leftlen < nTreeLen && pInOrder[leftlen] != chRoot) { 56 | ++leftlen; 57 | } 58 | 59 | if(leftlen == nTreeLen) { 60 | cout << "invalid parameters" << endl; 61 | return; 62 | } 63 | 64 | rightlen = nTreeLen - leftlen - 1; 65 | 66 | Rebuild(pPreOrder + 1, pInOrder, leftlen, &((*pRoot)->pLeft)); 67 | Rebuild(pPreOrder + leftlen + 1, pInOrder + leftlen + 1, rightlen, &((*pRoot)->pRight)); 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /bop/README.md: -------------------------------------------------------------------------------- 1 | ## 编程之美 2 | 3 | [回到主目录](https://github.com/luofengmacheng/algorithms) 4 | 5 | 2.16 [求数组中最长递增子序列的长度](https://github.com/luofengmacheng/algorithms/blob/master/bop/2.16.md) 6 | 7 | 2.19 [区间重合判断](https://github.com/luofengmacheng/algorithms/blob/master/bop/2.19.md) 8 | 9 | 3.1 [字符串移位包含的问题](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.1.md) 10 | 11 | 3.2 [电话号码对应英语单词](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.2.md) 12 | 13 | 3.3 [计算字符串的相似度](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.3.md) 14 | 15 | 3.5 [最短摘要的生成](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.5.md) 16 | 17 | 3.6 [判断两个链表是否相交](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.6.md) 18 | 19 | 3.7 [队列中取最大值操作问题](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.7.md) 20 | 21 | 3.8 [求二叉树中节点的最大距离](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.8.md) 22 | 23 | 3.9 [重建二叉树](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.9.md) 24 | 25 | 3.10 [分层遍历二叉树](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.10.md) 26 | 27 | 3.11 [程序改错](https://github.com/luofengmacheng/algorithms/blob/master/bop/3.11.md) 28 | -------------------------------------------------------------------------------- /config git: -------------------------------------------------------------------------------- 1 | 1 install 2 | sudo apt-get install git 3 | sudo apt-get install git-core 4 | 5 | 2 config 6 | git config --global user.name nikename 7 | git config --global user.email email-address 8 | 9 | 3 add ssh key 10 | https://help.github.com/articles/generating-ssh-keys 11 | 12 | 3.1 generate a new SSH key 13 | ssh-keygen -t rsa -C "email-address" 14 | ssh-add id_rsa 15 | 16 | 3.2 add your SSH key to GitHub 17 | copy ~/.ssh/id_rsa.pub content 18 | goto Account Settings in GitHub 19 | click SSH Keys 20 | click Add SSH key 21 | click Add key 22 | enter your GitHub password 23 | -------------------------------------------------------------------------------- /cpp_primer/more_effective_cpp/auto_ptr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/14 4 | * source: More Effective C++ 5 | * title: auto_ptr 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | template < typename T > 13 | class auto_ptr { 14 | public: 15 | auto_ptr(T *ptr = 0) : pointee(ptr) { } 16 | ~auto_ptr() { delete pointee; } 17 | 18 | auto_ptr(auto_ptr& rhs); 19 | auto_ptr& operator=(auto_ptr& rhs); 20 | 21 | T* operator->(); 22 | T& operator*(); 23 | 24 | private: 25 | T *pointee; 26 | }; 27 | 28 | template < typename T > 29 | auto_ptr::auto_ptr(auto_ptr& rhs) 30 | { 31 | pointee = rhs.pointee; 32 | rhs.pointee = 0; 33 | } 34 | 35 | template < typename T > 36 | auto_ptr& auto_ptr::operator=(auto_ptr& rhs) 37 | { 38 | if(this == &rhs) { 39 | return *this; 40 | } 41 | 42 | delete pointee; 43 | 44 | pointee = rhs.pointee; 45 | rhs.pointee = 0; 46 | 47 | return *this; 48 | } 49 | 50 | template < typename T > 51 | T* auto_ptr::operator->() 52 | { 53 | return pointee; 54 | } 55 | 56 | template < typename T > 57 | T& auto_ptr::operator*() 58 | { 59 | return *pointee; 60 | } 61 | 62 | int main(int argc, char const *argv[]) 63 | { 64 | 65 | return 0; 66 | } -------------------------------------------------------------------------------- /cpp_primer/vector_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/31 4 | * source: C++ Primer 5 | * language: C++ 6 | * info: 测试数组和vector的有关功能 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | typedef string *pstring; 15 | typedef int *ptint; 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | string *psa = new string[10]; 20 | int *pia = new int[10](5); 21 | 22 | cout< ivec(int_arr, int_arr + arr_size); 34 | cout< 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | template < typename input_iter, typename Compare > 15 | void bubble_sort(input_iter beg, input_iter end, Compare cmp) 16 | { 17 | if(beg == end) { 18 | return; 19 | } 20 | 21 | input_iter iter; 22 | 23 | while(beg != end - 1) { 24 | iter = beg; 25 | 26 | while(iter != end - 1) { 27 | if(cmp(*(iter + 1), *iter)) { 28 | iter_swap(iter + 1, iter); 29 | } 30 | ++iter; 31 | } 32 | 33 | --end; 34 | } 35 | } 36 | 37 | template < typename input_iter > 38 | struct comp { 39 | 40 | typedef typename iterator_traits::value_type val_type; 41 | 42 | bool operator()(val_type op1, val_type op2) 43 | { 44 | return op1 < op2; 45 | } 46 | }; 47 | 48 | int main(int argc, char const *argv[]) 49 | { 50 | int arr[] = {4, 2, 6, 5, 1}; 51 | vector vec(arr, arr + 5); 52 | 53 | bubble_sort(vec.begin(), vec.end(), comp::iterator>()); 54 | 55 | copy(vec.begin(), vec.end(), ostream_iterator(cout, " ")); 56 | cout << endl; 57 | 58 | return 0; 59 | } -------------------------------------------------------------------------------- /data_struct/sort/insert_sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/7/30 4 | * title: insert sort 5 | * language: C++ 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | template < typename input_iter, typename Compare > 15 | void insert_sort(input_iter beg, input_iter end, Compare cmp) 16 | { 17 | for(input_iter iter = beg; iter != end; ++iter) { 18 | 19 | input_iter iter2 = iter; 20 | 21 | while(iter2 != beg && cmp(*iter2, *(iter2 - 1))) { 22 | iter_swap(iter2, iter2 - 1); 23 | --iter2; 24 | } 25 | } 26 | } 27 | 28 | template < typename input_iter > 29 | struct comp { 30 | 31 | typedef typename iterator_traits::value_type val_type; 32 | 33 | bool operator()(val_type op1, val_type op2) 34 | { 35 | return op1 < op2; 36 | } 37 | }; 38 | 39 | int main(int argc, char const *argv[]) 40 | { 41 | int arr[] = {4, 2, 6, 5, 1}; 42 | vector vec(arr, arr + 5); 43 | 44 | insert_sort(vec.begin(), vec.end(), comp::iterator>()); 45 | 46 | copy(vec.begin(), vec.end(), ostream_iterator(cout, " ")); 47 | cout << endl; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /data_struct/sort/merge_sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/7/30 4 | * title: merge sort 5 | * language: C++ 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | template < typename input_iter, typename Compare > 15 | void merge_sort(input_iter beg, input_iter end, Compare cmp) 16 | { 17 | if(beg == end || end - beg == 1) { 18 | return; 19 | } 20 | 21 | typename iterator_traits::difference_type len = end - beg; 22 | input_iter mid = beg + len / 2; 23 | 24 | merge_sort(beg, mid, cmp); 25 | merge_sort(mid, end, cmp); 26 | 27 | typedef typename iterator_traits::value_type val_type; 28 | vector vec(len); 29 | 30 | // 注意下面这行,不能直接用vector::iterator 31 | typename vector::iterator iter = vec.begin(); 32 | input_iter iter1 = beg, iter2 = mid; 33 | while(iter1 != mid && iter2 != end) { 34 | if(cmp(*iter1, *iter2)) { 35 | *iter++ = *iter1++; 36 | } 37 | else { 38 | *iter++ = *iter2++; 39 | } 40 | } 41 | 42 | if(iter1 != mid) { 43 | copy(iter1, mid, iter); 44 | } 45 | 46 | if(iter2 != end) { 47 | copy(iter2, end, iter); 48 | } 49 | 50 | copy(vec.begin(), vec.end(), beg); 51 | } 52 | 53 | template < typename input_iter > 54 | struct comp { 55 | 56 | typedef typename iterator_traits::value_type val_type; 57 | 58 | bool operator()(val_type op1, val_type op2) 59 | { 60 | return op1 < op2; 61 | } 62 | }; 63 | 64 | int main(int argc, char const *argv[]) 65 | { 66 | int arr[] = {4, 2, 6, 5, 1}; 67 | vector vec(arr, arr + 5); 68 | 69 | merge_sort(vec.begin(), vec.end(), comp::iterator>()); 70 | 71 | copy(vec.begin(), vec.end(), ostream_iterator(cout, " ")); 72 | cout << endl; 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /data_struct/sort/quick_sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/7/30 4 | * title: quick sort 5 | * language: C++ 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | template < typename input_iter, typename Compare > 15 | void quick_sort(input_iter beg, input_iter end, Compare cmp) 16 | { 17 | if(beg == end) { 18 | return; 19 | } 20 | 21 | input_iter start = beg, last = end - 1; 22 | 23 | while(start != last) { 24 | 25 | while(start != last && cmp(*start, *last)) { 26 | --last; 27 | } 28 | 29 | if(start != last) { 30 | iter_swap(start, last); 31 | } 32 | 33 | while(start != last && cmp(*start, *last)) { 34 | ++start; 35 | } 36 | 37 | if(start != last) { 38 | iter_swap(start, last); 39 | } 40 | } 41 | 42 | quick_sort(beg, start, cmp); 43 | quick_sort(start + 1, end, cmp); 44 | } 45 | 46 | template < typename input_iter > 47 | struct comp { 48 | 49 | typedef typename iterator_traits::value_type val_type; 50 | 51 | bool operator()(val_type op1, val_type op2) 52 | { 53 | return op1 < op2; 54 | } 55 | }; 56 | 57 | int main(int argc, char const *argv[]) 58 | { 59 | int arr[] = {4, 2, 6, 5, 1}; 60 | vector vec(arr, arr + 5); 61 | 62 | quick_sort(vec.begin(), vec.end(), comp::iterator>()); 63 | 64 | copy(vec.begin(), vec.end(), ostream_iterator(cout, " ")); 65 | cout << endl; 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /data_struct/sort/select_sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/7/30 4 | * title: select sort 5 | * language: C++ 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | template < typename input_iter, typename Compare > 15 | void select_sort(input_iter beg, input_iter end, Compare cmp) 16 | { 17 | input_iter iter, iter2; 18 | 19 | while(beg != end) { 20 | iter = beg; 21 | 22 | while(iter != end) { 23 | if(cmp(*iter, *beg)) { 24 | iter_swap(iter, beg); 25 | } 26 | 27 | ++iter; 28 | } 29 | 30 | ++beg; 31 | } 32 | } 33 | 34 | template < typename input_iter > 35 | struct comp { 36 | 37 | typedef typename iterator_traits::value_type val_type; 38 | 39 | bool operator()(val_type op1, val_type op2) 40 | { 41 | return op1 < op2; 42 | } 43 | }; 44 | 45 | int main(int argc, char const *argv[]) 46 | { 47 | int arr[] = {4, 2, 6, 5, 1}; 48 | vector vec(arr, arr + 5); 49 | 50 | select_sort(vec.begin(), vec.end(), comp::iterator>()); 51 | 52 | copy(vec.begin(), vec.end(), ostream_iterator(cout, " ")); 53 | cout << endl; 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /data_struct/sort/shell_sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/7/30 4 | * title: shell sort 5 | * language: C++ 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | template < typename input_iter, typename Compare > 15 | void shell_sort(input_iter beg, input_iter end, Compare cmp) 16 | { 17 | typename iterator_traits::difference_type len = end - beg; 18 | 19 | for(int gap = len / 2; gap > 0; gap /= 2) { 20 | for(int i = gap; i < len; ++i) { 21 | for(int j = i - gap; j >= 0 && cmp(*(beg + j + gap), *(beg + j)); j -= gap) { 22 | iter_swap(beg + j + gap, beg + j); 23 | } 24 | } 25 | } 26 | } 27 | 28 | template < typename input_iter > 29 | struct comp { 30 | 31 | typedef typename iterator_traits::value_type val_type; 32 | 33 | bool operator()(val_type op1, val_type op2) 34 | { 35 | return op1 < op2; 36 | } 37 | }; 38 | 39 | int main(int argc, char const *argv[]) 40 | { 41 | int arr[] = {4, 2, 6, 5, 1}; 42 | vector vec(arr, arr + 5); 43 | 44 | shell_sort(vec.begin(), vec.end(), comp::iterator>()); 45 | 46 | copy(vec.begin(), vec.end(), ostream_iterator(cout, " ")); 47 | cout << endl; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /data_struct/vector/vector.h: -------------------------------------------------------------------------------- 1 | 2 | namespace luofengmacheng { 3 | 4 | template < typename T, class alloc = alloctor > 5 | class Vector { 6 | public: 7 | // type definition 8 | typedef T value_type; 9 | typedef alloc allocator_type; 10 | typedef typename alloc::pointer pointer; 11 | typedef typename alloc::const_pointer const_pointer; 12 | typedef typename alloc::reference reference; 13 | typedef typename alloc::const_reference const_reference; 14 | 15 | // iterator 16 | iterator begin(); 17 | const_iterator begin() const; 18 | iterator end(); 19 | const_iterator end() const; 20 | 21 | // access 22 | reference operator[](size_type n); // without check 23 | const_reference operator[](size_type n) const; 24 | 25 | reference at(size_type n); // with check 26 | const_reference at(size_type n); 27 | 28 | reference front(); // first element 29 | const_reference front() const; 30 | 31 | reference back(); // last element 32 | const_reference back() const; 33 | 34 | // constructor 35 | explicit Vector(const alloc& = alloc()); // constructor without parameter constructs emtpy vector 36 | explicit Vector(size_type n, const T& value = T(), const alloc& = alloc()); 37 | template < typename in > 38 | Vector(in first, in last, const alloc& = alloc()); 39 | Vector(const Vector&); 40 | Vector& operator=(const Vector&); 41 | 42 | ~Vector(); 43 | }; 44 | 45 | } -------------------------------------------------------------------------------- /hdu_oj/1003_max_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/11/20 4 | * source: HDU OJ 5 | * title: 1003 Max Sum 6 | * category: Dynamic Programming 7 | * language: C++ 8 | */ 9 | 10 | #include 11 | using namespace std; 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | int n = 0; 16 | cin >> n; 17 | 18 | int max_sum = 0; 19 | int b = 0; 20 | int i = 0, j = 0; 21 | 22 | while(n--) { 23 | while(cin >> b) { 24 | if(b > 0) { 25 | b += a; 26 | 27 | } 28 | else { 29 | b = a; 30 | } 31 | if(b > max_sum) { 32 | max_sum = b; 33 | } 34 | } 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /hihocoder/1.md: -------------------------------------------------------------------------------- 1 | ## hihoCoder:最长回文子串 2 | 3 | 题目链接:[最长回文子串](http://hihocoder.com/problemset/problem/1032) 4 | 5 | > 给定一个字符串,返回它的最长回文子串的长度。例如,给定字符串aaaabaa,最长回文子串是aabaa,返回长度5。 6 | 7 | **输入:** 8 | 9 | 输入的第一行是一个整数N,表示字符串的个数。接下来的N行就是给定的N个字符串。 10 | 11 | **输出:** 12 | 13 | 按照字符串的顺序依次输出每个字符串的最长回文子串的长度。 14 | 15 | ### 1 分析 16 | 17 | 18 | ### 2 实现 19 | -------------------------------------------------------------------------------- /hihocoder/README.md: -------------------------------------------------------------------------------- 1 | ## hihoCoder 2 | 3 | [回到主目录](https://github.com/luofengmacheng/algorithms) 4 | 5 | 题目来自[hihocoder](http://www.hihocoder.com) 6 | 7 | 1 [最长回文子串](https://github.com/luofengmacheng/algorithms/blob/master/hihocoder/1.md) 8 | 9 | 2 [Trie树](https://github.com/luofengmacheng/algorithms/blob/master/hihocoder/2.md) 10 | 11 | 3 [KMP算法](https://github.com/luofengmacheng/algorithms/blob/master/hihocoder/3.md) 12 | 13 | 4 [字符消除](https://github.com/luofengmacheng/algorithms/blob/master/hihocoder/4.md) 14 | -------------------------------------------------------------------------------- /interviewOffer/10.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题10:二进制中1的个数 2 | 3 | > 请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如,把9表示成二进制是1001,有2位是1。因此,如果输入9,该函数输出2。 4 | 5 | ### 1 方法1:依次判断每一位是否为1 6 | 7 | 最简单的办法就是,依次判断整数的每一位是否为1。书中说这种方法会因为负数的左移导致死循环,其实,可以将参数定义为unsigned int。 8 | 9 | 方法1:将整数与1相与,如果结果为真,说明最后一位是1,计数器加1。每次循环都将整数向右移动一位。知道整数变成0。 10 | 11 | ``` C++ 12 | int numof1(unsigned int n) 13 | { 14 | int cnt = 0; 15 | 16 | while(n) { 17 | if(n & 1) { 18 | ++cnt; 19 | } 20 | 21 | n = n >> 1; 22 | } 23 | 24 | return cnt; 25 | } 26 | ``` 27 | 28 | 与上面的方法类似,也可以固定n,而使1向左移动来检测每一位是否为1。 29 | 30 | ### 2 利用位运算的经典算法 31 | 32 | 上面的方法都要遍历整数的所有位,这里介绍的方法循环的次数跟整数中1的个数一样。 33 | 34 | 要点:将一个整数减1,可以将这个整数最右边的1变成0,如果这个1后面有0的话,将这个1后面所有的0变成1,而这个1前面的数保持不变。将一个整数减1再与这个整数相与,可以将这个整数的最右边的1变成0。 35 | 36 | ``` C++ 37 | int numof1(int n) 38 | { 39 | int cnt = 0; 40 | 41 | while(n) { 42 | ++cnt; 43 | n = (n-1) & n; 44 | } 45 | 46 | return cnt; 47 | } 48 | ``` 49 | -------------------------------------------------------------------------------- /interviewOffer/13.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题13:在O(1)时间删除链表节点 2 | 3 | > 给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点。下面是链表节点和函数的定义: 4 | 5 | ``` C++ 6 | struct ListNode { 7 | int m_nValue; 8 | ListNode *m_pNext; 9 | }; 10 | 11 | void DeleteNode(ListNode **pListHead, ListNode *pToBeDeleted); 12 | ``` 13 | 14 | ### 1 分析 15 | 16 | 单向链表中,前一个节点中包含一个指向下一个节点的指针,因此,只能从前往后遍历,而不能反向遍历。 17 | 18 | 通常情况下,如果我们要删除某个节点,就要将前一个节点的指针域修改为下一个节点的地址。然后销毁这个节点的存储空间。 19 | 20 | 现在只有要删除的节点指针,需要在O(1)时间删除这个节点,貌似是不可能的。 21 | 22 | ### 2 实现 23 | 24 | 一种投机取巧的方法是:将下一个节点的数据域拷贝到当前要删除的节点的数据域,然后删除下一个节点。 25 | 26 | 当然,还有一些特殊情况需要考虑: 27 | * 如果要删除的节点是最后一个节点,就只能从头开始遍历,修改前一个节点的指针域。 28 | * 如果链表中只有一个节点,而且删除的就是这个节点,在删除这个节点后,还需要修改头节点指针。 29 | 30 | ``` C++ 31 | void DeleteNode(ListNode **pListHead, ListNode *pToBeDeleted) 32 | { 33 | if(pListHead == NULL || pListHead && *pListHead == NULL || pToBeDeleted == NULL) { 34 | return; 35 | } 36 | 37 | ListNode *head = *pListHead; 38 | 39 | if(head->m_pNext == NULL && head == pToBeDeleted) { // 链表只有一个节点,并且删除的就是这个节点 40 | *pListHead = NULL; 41 | delete pToBeDeleted; 42 | return; 43 | } 44 | 45 | if(pToBeDeleted->m_pNext == NULL) { // 删除的是最后一个节点 46 | while(head && head->m_pNext != pToBeDeleted) { // 遍历到前一个节点 47 | head = head->m_pNext; 48 | } 49 | 50 | head->m_pNext = NULL; 51 | 52 | delete pToBeDeleted; 53 | } 54 | else { 55 | pToBeDeleted->m_nValue = pToBeDeleted->m_pNext->m_nValue; 56 | pToBeDeleted->m_pNext = pToBeDeleted->m_pNext->m_pNext; 57 | 58 | delete pToBeDeleted; 59 | } 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /interviewOffer/15.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题15:链表中倒数第k个结点 2 | 3 | > 输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如,一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6,这个链表的倒数第3个结点是值为4的结点。 4 | 5 | ``` C++ 6 | struct ListNode { 7 | int m_nValue; 8 | ListNode *m_pNext; 9 | }; 10 | ``` 11 | 12 | ### 1 分析 13 | 14 | 这题是用快慢指针解决的经典问题,另一个用快慢指针解决的经典问题是:[Linked List Cycle](http://blog.csdn.net/luofengmacheng/article/details/22158471)。 15 | 16 | 用一个指针从头结点开始走k步,然后将另一个指针指向头结点,之后,两个指针同时进行遍历,当第一个指针为空时,第二个指针指向的就是倒数第k个结点。 17 | 18 | 需要注意的问题是: 19 | 20 | * **要检查用户输入的链表是否为空** 21 | * **当链表的总长度小于k时的解决办法** 22 | 23 | ### 2 实现 24 | 25 | ``` C++ 26 | ListNode *find_kth_from_tail(ListNode *head, unsigned int k) 27 | { 28 | if(head == NULL || k == 0) { 29 | // 处理链表为空和k为0 30 | // 其实,这两个判断都可以交给下面这个while循环处理 31 | return NULL; 32 | } 33 | 34 | ListNode *fast = head; 35 | 36 | while(fast != NULL && k--) { // 快指针走k步,同时处理链表长度小于k的情况 37 | fast = fast->m_pNext; 38 | } 39 | 40 | if(fast == NULL) { 41 | return NULL; 42 | } 43 | 44 | ListNode *slow = head; 45 | 46 | while(fast != NULL) { 47 | // 这里是让fast为空时停止,书上是让fast指向最后一个结点 48 | fast = fast->m_pNext; 49 | slow = slow->m_pNext; 50 | } 51 | 52 | return slow; 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /interviewOffer/18.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题18:树的子结构 2 | 3 | > 输入两棵二叉树A和B,判断B是不是A的子结构。 4 | 5 | ``` C++ 6 | struct BinaryTreeNode { 7 | int m_nValue; 8 | BinaryTreeNode *m_pLeft; 9 | BinaryTreeNode *m_pRight; 10 | }; 11 | ``` 12 | 13 | ### 1 分析 14 | 15 | 首先必须知道什么是**子结构**:如果A中包含B,就说B是A的子结构。 16 | 17 | 例如: 18 | 19 | A树 B树 20 | 21 | 8 8 22 | / \ / \ 23 | 8 7 9 2 24 | / \ 25 | 9 2 26 | / \ 27 | 4 7 28 | 29 | A中完全包含B树,于是B就是A的子结构,因此,子结构不仅在结构,还在结点的值,其实,更准确的应该叫子树。 30 | 31 | ### 2 实现 32 | 33 | ``` C++ 34 | bool is_same(BinaryTreeNode *root1, BinaryTreeNode *root2) 35 | { 36 | if(root2 == NULL) { 37 | return true; 38 | } 39 | 40 | if(root1 == NULL) { 41 | return false; 42 | } 43 | 44 | if(root1->m_nValue != root2->m_nValue) { 45 | return false; 46 | } 47 | 48 | return is_same(root1->m_pLeft, root2->m_pLeft) && 49 | is_same(root1->m_pRight, root2->m_pRight); 50 | } 51 | 52 | bool sub_tree(BinaryTreeNode *root1, BinaryTreeNode *root2) 53 | { 54 | bool result = false; 55 | 56 | if(root1 != NULL && root2 != NULL) { 57 | if(root1->m_nValue == root2->m_nValue) { 58 | result = is_same(root1, root2); 59 | } 60 | 61 | if(!result) { 62 | result = sub_tree(root1->m_pLeft, root2); 63 | } 64 | 65 | if(!result) { 66 | result = sub_tree(root1->m_pRight, root2); 67 | } 68 | } 69 | 70 | return result; 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /interviewOffer/19.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题19:二叉树的镜像 2 | 3 | > 请完成一个函数,输入一个二叉树,该函数输出它的镜像。 4 | 5 | 这题比较简单,而且许多笔试面试题都会提到这个题目,这里简单说下思路,代码详见:[将一个给定的二叉树转换为它的镜像](https://github.com/luofengmacheng/algorithms/blob/master/july_100/15.cpp)。 6 | 7 | 镜像其实就是交换左右子树,于是,可以很容易想到递归,先交换左右子树,然后对左右子树再求镜像即可。 8 | -------------------------------------------------------------------------------- /interviewOffer/21.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题21:包含min函数的栈 2 | 3 | > 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。 4 | 5 | ### 1 分析 6 | 7 | 要求min、push及pop的时间复杂度是O(1),push和pop很容易,关键是min,如何在常数时间内找到一个栈的最小元素呢? 8 | 9 | 要在保持栈的特性的前提下,是不容易在常数时间内找到一个栈的最小元素的,基本想法是:用一个辅助栈保存栈此时的最小值。 10 | 11 | 12 | ### 2 实现 13 | 14 | ``` C++ 15 | template < typename T, typename Container = vector > 16 | class min_stack { 17 | Container container; // 保存数据的栈 18 | Container aux_cont; // 辅助栈 19 | public: 20 | void push(const T&); 21 | void pop(); 22 | T& top(); 23 | T min(); 24 | }; 25 | 26 | template < typename T, typename Container > 27 | void min_stack::push(const T& t) 28 | { 29 | container.push_back(t); 30 | if(aux_cont.empty()) { 31 | aux_cont.push_back(t); 32 | } 33 | else { 34 | aux_cont.push_back(std::min(aux_cont.back(), t)); 35 | } 36 | } 37 | 38 | template < typename T, typename Container > 39 | void min_stack::pop() 40 | { 41 | if(container.empty()) { 42 | throw new string("empty stack"); 43 | } 44 | 45 | container.pop_back(); 46 | aux_cont.pop_back(); 47 | } 48 | 49 | template < typename T, typename Container > 50 | T& min_stack::top() 51 | { 52 | if(container.empty()) { 53 | throw new string("empty stack"); 54 | } 55 | 56 | return container.back(); 57 | } 58 | 59 | template < typename T, typename Container > 60 | T min_stack::min() 61 | { 62 | if(container.empty()) { 63 | throw new string("empty stack"); 64 | } 65 | 66 | return aux_cont.back(); 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /interviewOffer/22.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题22:栈的压入、弹出序列 2 | 3 | > 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、3、5、1、2就不可能是该呀栈序列的弹出序列。 4 | 5 | ### 1 分析 6 | 7 | 基本想法是,用一个栈对压栈序列进行压入,看是否可以得到弹出序列。 8 | 9 | * 如果当前栈顶元素不等于当前期待的弹出元素,就压栈,直到当前栈顶元素等于当前期待的弹出元素。 10 | * 如果当前栈顶元素等于当前期待的弹出元素,则进行弹出。 11 | * 如果当前栈顶元素不等于当前期待的弹出元素,但是,已经没有元素可以压栈了,就说明该序列不是对应的弹出序列。 12 | * 如果栈空并且已经得到了弹出序列,就说明该序列是对应的弹出序列。其实,这里只要检查弹出序列就行了,因为,弹出序列的长度跟压入序列的长度肯定一样,既然已经得到了弹出序列,那么,当然已经压入了所有元素并且栈为空。 13 | 14 | ### 2 实现 15 | 16 | ``` C++ 17 | template < typename in_iter, typename out_iter > 18 | bool pop_order(in_iter bpush, in_iter epush, out_iter bpop, out_iter epop) 19 | { 20 | if(epush - bpush != epop - bpop) { 21 | return false; 22 | } 23 | 24 | if(epush == bpush) { 25 | return false; 26 | } 27 | 28 | stack sta; 29 | 30 | while(bpop != epop) { 31 | while(bpush != epush && (sta.empty() || sta.top() != *bpop)) { 32 | sta.push(*bpush); 33 | ++bpush; 34 | } 35 | 36 | if(sta.top() == *bpop) { 37 | sta.pop(); 38 | ++bpop; 39 | } 40 | else if(bpush == epush) { 41 | return false; 42 | } 43 | 44 | if(sta.empty() && bpop == epop) { 45 | return true; 46 | } 47 | } 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /interviewOffer/23.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题23:从上往下打印二叉树 2 | 3 | > 从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。 4 | 5 | ``` C++ 6 | struct BinaryTreeNode { 7 | int m_nValue; 8 | BinaryTreeNode *m_pLeft; 9 | BinaryTreeNode *m_pRight; 10 | }; 11 | ``` 12 | 13 | ### 1 分析 14 | 15 | 这就是二叉树遍历的其中一种,称之为:**层序遍历**。 16 | 17 | 需要使用辅助工具:队列。 18 | 19 | 首先,将根结点入队列,然后开始遍历。如果队列不空,就从队列中取出一个结点,对这个节点进行访问,如果这个结点存在左右子树,就将左右子树进队列。 20 | 21 | ### 2 实现 22 | 23 | ``` C++ 24 | void traverse_level(BinaryTreeNode *root) 25 | { 26 | if(root == NULL) { 27 | return; 28 | } 29 | 30 | queue tree_que; 31 | BinaryTreeNode *pnode = NULL; 32 | 33 | tree_que.push(root); 34 | while(!tree_que.empty()) { 35 | pnode = tree_que.front(); 36 | tree_que.pop(); 37 | 38 | cout << pnode->m_nValue << " "; 39 | 40 | if(pnode->m_pLeft) { 41 | tree_que.push(pnode->m_pLeft); 42 | } 43 | 44 | if(pnode->m_pRight) { 45 | tree_que.push(pnode->m_pRight); 46 | } 47 | } 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /interviewOffer/24.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题24:二叉搜索树的后序遍历序列 2 | 3 | > 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是,则返回true,否则返回false。假设输入的数组的任意两个数字都不相同。 4 | 5 | ### 1 分析 6 | 7 | 判断一个序列是否是二叉搜索树的后序遍历序列,可以从二叉搜索树的特点来入手。二叉搜索树的后序遍历是按照“左右根”的顺序,因此,序列的最后一个元素肯定是根,然后根据这个根去找左子树和右子树的分界点。 8 | 9 | ### 2 实现 10 | 11 | ``` C++ 12 | template < typename input_iter > 13 | bool is_post_order(input_iter beg, input_iter end) 14 | { 15 | if(beg == end) { 16 | return false; 17 | } 18 | 19 | if(end - beg == 1) { 20 | return true; 21 | } 22 | 23 | typename input_iter::value_type root = *(end - 1); 24 | 25 | input_iter iter, iter2; 26 | 27 | for(iter = beg; iter != end - 1; ++iter) { 28 | if(*iter >= root) { 29 | break; 30 | } 31 | } 32 | 33 | iter2 = iter; 34 | while(iter2 != end - 1 && *iter2 >= root) { 35 | ++iter2; 36 | } 37 | 38 | if(iter2 != end - 1) { 39 | return false; 40 | } 41 | 42 | return is_post_order(beg, iter) && is_post_order(iter, iter2); 43 | } 44 | ``` 45 | 46 | 由于是后序遍历,因此*(end - 1)就是根结点的值。第一个for循环从序列开始遍历,找到第一个比根节点大的结点,那么,该位置前面的就是左子树,包括该结点,以及它后面的是右子树,现在可以确定,左子树的结点的值都小于根结点的值,但是,右子树呢?因此,还必须对右子树的节点的值进行检验,如果有一个值小于根节点,就说明该序列不是后序遍历序列,如果都大于根结点,那么对左右子树进行递归。 47 | -------------------------------------------------------------------------------- /interviewOffer/25.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题25:二叉树中和为某一值的路径 2 | 3 | > 输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 4 | 5 | ``` C++ 6 | struct BinaryTreeNode { 7 | int m_nValue; 8 | BinaryTreeNode *m_pLeft; 9 | BinaryTreeNode *m_pRight; 10 | }; 11 | ``` 12 | 13 | ### 1 分析 14 | 15 | 要想找到一条等于特定值的路径,就必然要在遍历这棵树时,保存从根结点到当前结点的路径。 16 | 17 | 用一个栈保存当前遍历到的结点所遍历的值,当所期待的值刚好等于叶结点的值时,就找到了一条路径。 18 | 19 | ### 2 实现 20 | 21 | ``` C++ 22 | 23 | void find_path_sum(BinaryTreeNode *root, vector &que, int sum) 24 | { 25 | if(root->m_pLeft == NULL && root->m_pRight == NULL) { 26 | if(root->m_nValue == sum) { 27 | copy(que.begin(), que.end(), ostream_iterator(cout, " ")); 28 | cout << sum << endl; 29 | } 30 | return; 31 | } 32 | 33 | que.push_back(root->m_nValue); 34 | if(root->m_pLeft != NULL) { 35 | find_path_sum(root->m_pLeft, que, sum-root->m_nValue); 36 | } 37 | 38 | if(root->m_pRight != NULL) { 39 | find_path_sum(root->m_pRight, que, sum-root->m_nValue); 40 | } 41 | que.pop_back(); 42 | } 43 | 44 | void find_path(BinaryTreeNode *root, int sum) 45 | { 46 | if(root == NULL) { 47 | return; 48 | } 49 | 50 | vector que; 51 | 52 | find_path_sum(root, que, sum); 53 | } 54 | ``` 55 | 56 | 这里采用的是将期待的值减去当前节点的值,就得到左右子树期待的值,做的是减法。而书上的方法做的是加法,当遍历一个结点时,将当前结点的值加到某个值上,如果这个值等于期待的值,并且当前结点是叶结点,那么,就得到一条路径。思路是一样的。 57 | 58 | 由于要打印整个栈的内容,因此,没有用queue,而用vector。 59 | -------------------------------------------------------------------------------- /interviewOffer/27.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题27:二叉搜索树与双向链表 2 | 3 | > 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中节点的指针的指向。 4 | 5 | ``` C++ 6 | struct BinaryTreeNode { 7 | int m_nValue; 8 | BinaryTreeNode *m_pLeft; 9 | BinaryTreeNode *m_pRight; 10 | }; 11 | ``` 12 | 13 | ### 1 分析 14 | 15 | 这个题看似麻烦,但是,如果用递归是很好解的。 16 | 17 | 用递归最好的理解方式就是假设一部分已经得到了解:某个根结点的左右子树已经变成了双向链表的形式,如何得到整个的双向链表呢? 18 | 19 | 要想得到整个双向链表,就必须得到左右子树的双向链表的头尾结点,因此,在递归时,可以用参数返回这个子树变成双向链表的头尾结点。 20 | 21 | ### 2 实现 22 | 23 | ``` C++ 24 | void ConertNode(BinaryTreeNode *root, BinaryTreeNode *&head, BinaryTreeNode *&tail) 25 | { 26 | if((root == NULL) || (root->m_pLeft == NULL && root->m_pRight == NULL)) { 27 | head = root; 28 | tail = root; 29 | return; 30 | } 31 | 32 | BinaryTreeNode *head1 = NULL, *tail1 = NULL; 33 | BinaryTreeNode *head2 = NULL, *tail2 = NULL; 34 | 35 | ConertNode(root->m_pLeft, head1, tail1); 36 | ConertNode(root->m_pRight, head2, tail2); 37 | 38 | if(tail1 == NULL) { 39 | head = root; 40 | } 41 | else { 42 | head = head1; 43 | tail1->m_pRight = root; 44 | root->m_pLeft = tail1; 45 | } 46 | 47 | if(head2 == NULL) { 48 | tail = root; 49 | } 50 | else { 51 | tail = tail2; 52 | head2->m_pLeft = root; 53 | root->m_pRight = head2; 54 | } 55 | } 56 | 57 | BinaryTreeNode *Convert(BinaryTreeNode *root) 58 | { 59 | if(root == NULL) { 60 | return NULL; 61 | } 62 | 63 | BinaryTreeNode *head = NULL, *tail = NULL; 64 | 65 | ConertNode(root, head, tail); 66 | 67 | return head; 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /interviewOffer/28.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题28:字符串的全排列 2 | 3 | > 输入一个字符串,打印该字符串中字符的所有排列。例如,输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。 4 | 5 | ### 1 实现1 6 | 7 | ``` C++ 8 | void _Permutation(string &str, string::iterator beg, string::iterator end) 9 | { 10 | if(beg == end) { 11 | cout << str << endl; 12 | return; 13 | } 14 | 15 | for(string::iterator iter = beg; iter != end; ++iter) { 16 | iter_swap(beg, iter); 17 | _Permutation(str, beg + 1, end); 18 | iter_swap(beg, iter); 19 | } 20 | } 21 | 22 | void Permutation2(string &str) 23 | { 24 | _Permutation(str, str.begin(), str.end()); 25 | } 26 | ``` 27 | 28 | 在_Permutation()函数中,用第一个参数表示当前字符串,第二个参数和第三个参数表示当前操作的一个区间。 29 | 30 | 对每个区间的字符串,首先将每个字符与第一个字符进行交换,然后处理从第二个字符到最后的字符,最后将交换的字符再次交换回来。 31 | 32 | ### 2 实现2 33 | 34 | ``` C++ 35 | vector Permutation(string &str) 36 | { 37 | if(str.empty()) { 38 | return vector(); 39 | } 40 | 41 | if(str.size() == 1) { 42 | return vector(1, string(1, str.back())); 43 | } 44 | 45 | char ch = str.back(); 46 | str.pop_back(); 47 | 48 | vector per = Permutation(str); 49 | vector ret; 50 | for(vector::iterator iter = per.begin(); 51 | iter != per.end(); ++iter) { 52 | string s = *iter; 53 | for(size_t i = 0; i < s.size(); ++i) { 54 | s.insert(i, 1, ch); 55 | ret.push_back(s); 56 | s = *iter; 57 | } 58 | s += ch; 59 | ret.push_back(s); 60 | } 61 | 62 | return ret; 63 | } 64 | ``` 65 | 66 | 这里用一个vector返回字符串的所有排列。 67 | 68 | 例如: 69 | 70 | 要求abc的全排列,如果已知ab的全排列,如何得到abc的全排列呢? 71 | 72 | 如果求得了ab的全排列:ab、ba。先对ab处理,将c插入到ab的三个位置,就得到cab、acb、abc。再处理ba,同样有cba、bca、bac。这样,就求得了abc的所有全排列。 73 | -------------------------------------------------------------------------------- /interviewOffer/33.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题33:把数组排成最小的数 2 | 3 | > 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如,输入数组{3,32,321},则打印出这三个数字能排成的最小数字321323。 4 | 5 | ### 1 实现 6 | 7 | ``` C++ 8 | struct comp { 9 | int operator()(string num1, string num2) 10 | { 11 | string str1 = num1 + num2; 12 | string str2 = num2 + num1; 13 | 14 | return str1.compare(str2); 15 | } 16 | }; 17 | 18 | void min_num(vector::iterator beg, vector::iterator end) 19 | { 20 | sort(beg, end, comp()); 21 | 22 | copy(beg, end, ostream_iterator(cout, "")); 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /interviewOffer/34.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题34:丑数 2 | 3 | > 我们把只包含因子2、3和5的数称为丑数。求按从小到大的顺序的第1500个丑数。例如,6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当作第一个丑数。 4 | 5 | ### 1 分析 6 | 7 | 由于丑数只包含因子2、3、5,如果已经有了一些丑数,如果来求得下一个丑数呢? 8 | 9 | 假设当前已经求得的最大丑数是M。对于因子2,将所有已经求得的丑数乘以2,就得到一些新的丑数,这些丑数有的比M小,有的比M大。比M大的第一个丑数设为M2。同理,对于因子3和5,也可以求得比M大的第一个丑数M3和M5。那么,比M大的下一个丑数就是min(M2, M3, M5)。 10 | 11 | ### 2 实现 12 | 13 | ``` C++ 14 | int get_ugly_number(int index) 15 | { 16 | if(index <= 0) { 17 | return 0; 18 | } 19 | 20 | vector ugly_nums; 21 | ugly_nums.reserve(index); 22 | 23 | ugly_nums.push_back(1); 24 | vector::iterator mul2 = ugly_nums.begin(); 25 | vector::iterator mul3 = ugly_nums.begin(); 26 | vector::iterator mul5 = ugly_nums.begin(); 27 | 28 | while(ugly_nums.size() < index) { 29 | 30 | int m = min(min((*mul2) * 2, (*mul3) * 3), (*mul5) * 5); 31 | ugly_nums.push_back(m); 32 | 33 | while(mul2 != ugly_nums.end() - 1 && (*mul2) * 2 <= ugly_nums.back()) { 34 | ++mul2; 35 | } 36 | 37 | while(mul3 != ugly_nums.end() - 1 && (*mul3) * 3 <= ugly_nums.back()) { 38 | ++mul3; 39 | } 40 | 41 | while(mul5 != ugly_nums.end() - 1 && (*mul5) * 5 <= ugly_nums.back()) { 42 | ++mul5; 43 | } 44 | } 45 | 46 | return ugly_nums.back(); 47 | } 48 | ``` 49 | -------------------------------------------------------------------------------- /interviewOffer/37.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题37:两个链表的第一个公共结点 2 | 3 | > 输入两个链表,找出它们的第一个公共结点。 4 | 5 | ``` C++ 6 | struct ListNode { 7 | int m_nKey; 8 | ListNode *m_pNext; 9 | }; 10 | ``` 11 | 12 | ### 1 分析 13 | 14 | 方法1:两个链表的公共结点,其实就是从尾部遍历这个链表时,第一个相同的结点。由于是单链表,肯定不能从尾部遍历,可以用两个辅助栈,先遍历两个链表,遍历的同时将结点添加到两个栈中,再同时对两个栈进行pop,找到的最后一个相同的结点就是公共结点。 15 | 16 | 方法2:两个链表从头结点开始,到第一个公共结点的长度就是两个链表的长度。因此,可以先遍历两个链表,求得两个链表的长度以及长度的差dif。用两个指针指向头结点,让较长的链表指针先走dif步,然后,两个指针同时走,找到的第一个相同的结点就是第一个公共结点。 17 | 18 | ### 2 实现 19 | 20 | ``` C++ 21 | unsigned int get_list_length(ListNode *head) 22 | { 23 | unsigned int len = 0; 24 | 25 | ListNode *pnode = head; 26 | while(pnode != NULL) { 27 | ++len; 28 | pnode = pnode->m_pNext; 29 | } 30 | 31 | return len; 32 | } 33 | 34 | ListNode* find_first_same(ListNode *head1, ListNode *head2) 35 | { 36 | unsigned int len1 = get_list_length(head1); 37 | unsigned int len2 = get_list_length(head2); 38 | 39 | int dif = len2 - len1; 40 | 41 | ListNode *plong = head1; 42 | ListNode *pshort = head2; 43 | if(len1 < len2) { 44 | plong = head2; 45 | pshort = heda1; 46 | dif = len2 - len1; 47 | } 48 | 49 | for(int i = 0; i < dif; ++i) { 50 | plong = plong->m_pNext; 51 | } 52 | 53 | while(plong != NULL && 54 | pshort != NULL && 55 | plong != pshort) { 56 | plong = plong->m_pNext; 57 | pshort = pshort->m_pNext; 58 | } 59 | 60 | return plong; 61 | } 62 | ``` 63 | -------------------------------------------------------------------------------- /interviewOffer/39.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题39:二叉树的深度 2 | 3 | ### 1 求深度 4 | 5 | > 输入一棵二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根节点、叶结点)形成树的一条路径,最长路径的长度为树的深度。 6 | 7 | ``` C++ 8 | struct BinaryTreeNode { 9 | int m_nValue; 10 | BinaryTreeNode *m_pLeft; 11 | BinaryTreeNode *m_pRight; 12 | }; 13 | ``` 14 | 15 | 递归实现: 16 | 17 | ``` C++ 18 | int tree_depth(BinaryTreeNode *root) 19 | { 20 | if(root == NULL) { 21 | return 0; 22 | } 23 | 24 | int lh = tree_depth(root->m_pLeft); 25 | int rh = tree_depth(root->m_pRight); 26 | 27 | return max(lh, rh) + 1; 28 | } 29 | ``` 30 | 31 | ### 2 判断是否为平衡二叉树 32 | 33 | > 输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是平衡二叉树。 34 | 35 | 平衡二叉树定义的另一种叙述:左右子树都是平衡二叉树,并且,左右子树的高度差不大于1。 36 | 37 | 于是,可以根据上面的定义写出下面的代码: 38 | 39 | ``` C++ 40 | bool is_balanced(BinaryTreeNode *root) 41 | { 42 | if(root == NULL) { 43 | return true; 44 | } 45 | 46 | int lh = 0, rh = 0; 47 | 48 | if(is_balanced(root->m_pLeft) && 49 | is_balanced(root->m_pRight) { 50 | lh = tree_depth(root->m_pLeft); 51 | rh = tree_depth(root->m_pRight); 52 | if(lh - rh <= 1 && lh - rh >= -1) { 53 | return true; 54 | } 55 | } 56 | 57 | return false; 58 | } 59 | ``` 60 | 61 | 但是,这样的话,会在求平衡和求深度时对同一个子树遍历两次。 62 | 63 | 为了提高效率,不重复遍历一个子树,将求平衡和深度同时进行: 64 | 65 | ``` C++ 66 | bool is_balanced(BinaryTreeNode *root, int *depth) 67 | { 68 | if(root == NULL) { 69 | *depth = 0; 70 | return true; 71 | } 72 | 73 | int lh = 0, rh = 0; 74 | 75 | if(is_balanced(root->m_pLeft, &lh) && 76 | is_balanced(root->m_pRight, &rh)) { 77 | int diff = lh - rh; 78 | if(diff <= 1 && diff >= -1) { 79 | *depth = max(lh, rh) + 1; 80 | return true; 81 | } 82 | } 83 | 84 | return false; 85 | } 86 | ``` 87 | -------------------------------------------------------------------------------- /interviewOffer/41.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题41:和为s的两个数字VS和为s的连续正数序列 2 | 3 | ### 1 和为s的两个数字 4 | 5 | > 输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。 6 | 7 | ``` C++ 8 | bool find_num_sum(vector::iterator beg, vector::iterator end, 9 | int sum, vector > &res) 10 | { 11 | bool found = false; 12 | 13 | if(beg == end) { 14 | return found; 15 | } 16 | 17 | vector::iterator start = beg, last = end - 1; 18 | 19 | while(start != last) { 20 | if(*start + *last > sum) { 21 | --last; 22 | } 23 | else if(*start + *last < sum) { 24 | ++start; 25 | } 26 | else { 27 | res.push_back(make_pair(*start, *last)); 28 | ++start; 29 | --last; 30 | found = true; 31 | } 32 | } 33 | 34 | return found; 35 | } 36 | ``` 37 | 38 | 上面的代码可以返回多对和为s的数字。 39 | 40 | ### 2 和为s的连续正数序列 41 | 42 | > 输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如,输入15,由于1+2+3+4+5=4+5+6=7+8=15,所有结果打印出三个连续序列1~5、4~6、7~8。 43 | 44 | 假设最开始的区间是(small, big) = (1, 2), 区间的和为cur_sum。当区间的和大于s时,就减少区间的值,递增small。当区间的和小于s时,就增大区间的值,递增big。 45 | 46 | ``` C++ 47 | void find_continuous_seq(int sum, vector > &res) 48 | { 49 | if(sum < 3) { 50 | return; 51 | } 52 | 53 | int small = 1; 54 | int big = 2; 55 | int mid = (1 + sum) / 2; 56 | int cur_sum = big + small; 57 | 58 | while(small < mid) { 59 | if(cur_sum < sum) { 60 | ++big; 61 | cur_sum += big; 62 | } 63 | else if(cur_sum > sum) { 64 | cur_sum -= small; 65 | ++small; 66 | } 67 | else { 68 | res.push_back(make_pair(small, big)); 69 | cur_sum -= small; 70 | ++small; 71 | } 72 | } 73 | } 74 | ``` 75 | -------------------------------------------------------------------------------- /interviewOffer/43.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题43:n个骰子的点数 2 | 3 | > 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。 4 | -------------------------------------------------------------------------------- /interviewOffer/44.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题44:扑克牌的顺子 2 | 3 | > 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。 4 | 5 | ### 1 分析 6 | 7 | 主要考虑的问题是:大、小王可以看成任意数字。因此,将5个数字进行排序后,相邻的两个数字之间可以通过插入大、小王,这里将大小王当作0。例如,5个数字排序后为{0, 1, 3, 4, 5},于是,0可以当作2放到1和3之间,于是,扑克牌就是顺子。 8 | 9 | 实现方案: 10 | * 对5个数字进行排序 11 | * 统计排序后0的个数zeros 12 | * 统计排序后相邻的数字之间的空缺总数gaps 13 | * 如果gaps > zeros,那么就不是顺子,否则,就是顺子 14 | 15 | ### 2 实现 16 | 17 | ``` C++ 18 | template < typename input_iter > 19 | bool is_continuous(input_iter beg, input_iter end) 20 | { 21 | if(end - beg != 5) { 22 | return false; 23 | } 24 | 25 | sort(beg, end); 26 | 27 | int zeros = 0, gaps = 0; 28 | 29 | for(input_iter iter = beg; 30 | iter != end && *iter == 0; ++iter) { 31 | ++zeros; 32 | } 33 | 34 | input_iter small = beg + zeros; 35 | input_iter big = small + 1; 36 | while(big != end) { 37 | if(*small == *big) { 38 | return false; 39 | } 40 | small = big; 41 | ++big; 42 | } 43 | 44 | return (gaps > zeros) ? false : true; 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /interviewOffer/45.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题45:圆圈中最后剩下的数字 2 | 3 | > 0, 1, ... , n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。 4 | 5 | ### 1 实现1:用vector模拟环形链表 6 | 7 | ``` C++ 8 | int last_remaining(int n, int m) 9 | { 10 | if(n < 1 || m < 1) { 11 | return -1; 12 | } 13 | 14 | vector numbers(n); 15 | for(int i = 0; i < n; ++i) { 16 | numbers[i] = i; 17 | } 18 | 19 | int del = 0; 20 | while(numbers.size() > 1) { 21 | del = (del + m - 1) % numbers.size(); 22 | numbers.erase(numbers.begin() + del); 23 | } 24 | 25 | return numbers.back(); 26 | } 27 | ``` 28 | 29 | ### 2 实现2: 30 | 31 | 第二种方法没怎么看明白。 32 | 33 | ``` C++ 34 | int last_remaining(int n, int m) 35 | { 36 | if(n < 1 || m < 1) { 37 | return -1; 38 | } 39 | 40 | int last = 0; 41 | for(int i = 2; i <= m; ++i) { 42 | last = (last + m) % i; 43 | } 44 | 45 | return last; 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /interviewOffer/47.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题47:不用加减乘除做加法 2 | 3 | > 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 4 | 5 | ### 1 分析 6 | 7 | 1 不考虑进位,对每一位相加,其实就是位的异或。 8 | 9 | 2 将两个数字相与后,再左移一位,得到的就是进位。例如,x = 011, y = 111,那么进位就会在倒数第1位和第2位产生,11 << 1 = 110,也就是产生的进位。 10 | 11 | 3 将第1步和第2步的结果再相加,跟上面的过程一样,直到不产生进位。 12 | 13 | ### 2 实现 14 | 15 | ``` C++ 16 | int add(int num1, int num2) 17 | { 18 | int sum = 0, carry = 0; 19 | 20 | do { 21 | sum = num1 ^ num2; 22 | carry = (num1 & num2) << 1; 23 | 24 | num1 = sum; 25 | num2 = carry; 26 | } while(num2 != 0); 27 | 28 | return num1; 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /interviewOffer/48.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题48:不能被继承的类 2 | 3 | > 用C++设计一个不能被继承的类。 4 | 5 | ### 1 利用私有构造函数 6 | 7 | 将构造函数和析构函数设置成私有成员,那么,当继承这个类时,会由于构造函数和析构函数是私有的而失败。由于不能通过构造函数创建对象,因此,用一个静态函数新建实例,当然,这样做会有一些不方便:和普通类的使用不同,只能创建堆上的对象。 8 | 9 | ``` C++ 10 | class SealedClass { 11 | public: 12 | static SealedClass* get_instance() 13 | { 14 | return new SealedClass(); 15 | } 16 | 17 | static void del_instance(SealedClass *pinstance) 18 | { 19 | delete pinstance; 20 | } 21 | 22 | private: 23 | SealedClass() { } 24 | ~SealedClass() { } 25 | }; 26 | ``` 27 | 28 | ### 2 利用虚拟继承 29 | 30 | 先创建一个模板类MakeSealed,构造函数和析构函数都设置为私有成员,并将模板参数设置为MakeSealed的友元。然后创建一个类SealedClass2,该类虚拟继承MakeSealed。当另外一个类继承SealedClass2时,由于是虚拟继承,就会调用MakeSealed的构造函数,但是,MakeSealed的构造函数是私有的,因此,会编译错误。 31 | 32 | ``` C++ 33 | template < typename T > 34 | class MakeSealed { 35 | friend T; 36 | 37 | private: 38 | MakeSealed() { } 39 | ~MakeSealed() { } 40 | }; 41 | 42 | class SealedClass2 : virtual public MakeSealed { 43 | public: 44 | SealedClass2() { } 45 | ~SealedClass2() { } 46 | }; 47 | ``` 48 | -------------------------------------------------------------------------------- /interviewOffer/5.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题5:逆向打印单链表 2 | 3 | 这题比较简单,不做过多解释。 4 | 5 | > 输入一个链表的头节点,从尾到头打印出每个节点的值。 6 | 链表节点定义: 7 | ``` C++ 8 | struct ListNode { 9 | int m_nKey; 10 | ListNode *m_pNext; 11 | }; 12 | ``` 13 | 14 | ### 方法1:栈 15 | 16 | 由链表节点可以看出,这是个单链表。只能从前到后遍历。于是,想到打印的顺序和遍历的顺序相反,这不就是栈吗? 17 | 18 | 书中在栈中存放节点指针,这里直接在栈中存放节点中的数据域。 19 | 20 | ``` C++ 21 | void print_list_reverse(ListNode *head) 22 | { 23 | stack sta; 24 | 25 | ListNode *pnode = head; 26 | while(pnode != NULL) { 27 | sta.push(pnode->m_nKey); 28 | pnode = pnode->m_pNext; 29 | } 30 | 31 | while(!sta.empty()) { 32 | cout << sta.top() << " "; 33 | sta.pop(); 34 | } 35 | } 36 | ``` 37 | 38 | ### 方法2:递归 39 | 40 | 由于函数的调用就是采用栈的结构,因此,对于使用栈的算法,可以尝试用递归来重新编写。 41 | 42 | ``` C++ 43 | void print_list_reverse(ListNode *head) 44 | { 45 | if(head == NULL) { 46 | return; 47 | } 48 | 49 | print_list_reverse(head->m_pNext); 50 | cout << head->m_nKey << " "; 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /interviewOffer/6.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题6:重建二叉树 2 | 3 | LeetCode上有这道题,包括从先序和中序构造二叉树以及从中序和后序构造二叉树。 4 | 5 | ### 1 先序和中序构造二叉树 6 | 7 | 如果先序为abc,中序为bac,如何来构造这棵树呢? 8 | 9 | 根据先序可以知道,a一定是根节点,那么,在中序序列中查找a,a左边的是左子树,a右边的是右子树。 10 | 11 | 代码参见:[Construct Binary Tree from Preorder and Inorder Traversal](https://github.com/luofengmacheng/algorithms/blob/master/LeetCode/btree_from_preorder_and_inorder.cpp) 12 | 13 | ### 2 中序和后序构造二叉树 14 | 15 | 思路跟前面的一样。 16 | 17 | 如果中序为bac,后序为bca。由后序可以知道,a一定是根节点,那么,同样的,在中序序列中查找a,a左边的是左子树,a右边的是右子树。 18 | 19 | 代码参见:[Construct Binary Tree from Preorder and Inorder Traversal](https://github.com/luofengmacheng/algorithms/blob/master/LeetCode/btree_from_inorder_and_postorder.cpp) 20 | -------------------------------------------------------------------------------- /interviewOffer/9.md: -------------------------------------------------------------------------------- 1 | ## 剑指Offer之面试题9:斐波那契数列 2 | 3 | > 题目1:写一个函数,输入n,求斐波那契数列的第n项。 4 | 5 | ### 1 方法1:递归 6 | 7 | 斐波那契数列本身就是用递归来定义的,因此,许多教科书上就用递归来实现。 8 | 9 | ``` C++ 10 | long long fibonacci(unsigned int n) 11 | { 12 | if(n <= 0) { 13 | return 0; 14 | } 15 | 16 | if(n == 1) { 17 | return 1; 18 | } 19 | 20 | return fibonacci(n - 1) + fibonacci(n - 2); 21 | } 22 | ``` 23 | 24 | ### 2 方法2:循环(动态规划) 25 | 26 | 书上通过分析fibonacci(10)展示了这种方法的问题:同一个中间结果多次计算。其实,这跟动态规划中的重叠子问题是一样的:当同一个中间结果多次计算时,可以保存中间结果的值,从而减低时间复杂度。 27 | 28 | ``` C++ 29 | long long fibonacci(unsigned int n) 30 | { 31 | if(n <= 0) { 32 | return 0; 33 | } 34 | 35 | if(n == 1) { 36 | return 1; 37 | } 38 | 39 | long long fib1 = 0; 40 | long long fib2 = 1; 41 | long long fibn = 0; 42 | 43 | for(unsigned int i = 2; i <= n; ++i) { 44 | fibn = fib1 + fib2; 45 | fib1 = fib2; 46 | fib2 = fibn; 47 | } 48 | 49 | return fibn; 50 | } 51 | ``` 52 | 53 | ### 3 问题延伸 54 | 55 | 有些问题,虽然表面看起来跟斐波那契数列没什么关系,但是,经过分析之后,它就是个斐波那契数列。 56 | 57 | > 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 58 | 59 | 解法:当只有1级台阶时,只有1种跳法。当只有2级台阶时,有两种跳法。当有n级台阶时,可以先跳1级,然后求得剩下n-1级台阶的跳法,也可以先跳2级,然后求得剩下n-1级台阶的跳法。于是有: 60 | * f(n) = 1; n = 1 61 | * f(n) = 2; n = 2 62 | * f(n) = f(n - 1) + f(n - 2); n > 2 63 | -------------------------------------------------------------------------------- /intro_algorithm/kmp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/5/13 4 | * source: LeetCode 5 | * title: KMP algorithm(http://www.ituring.com.cn/article/59881,http://kb.cnblogs.com/page/176818/) 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | void get_next(const string& str, vector &next) 17 | { 18 | next[0] = -1; 19 | int j = -1; 20 | 21 | for(int i = 1; i < str.size(); ++i) { 22 | while(str[i] != str[j + 1] && j >= 0) { 23 | j = next[j]; 24 | } 25 | if(str[i] == str[j + 1]) { 26 | ++j; 27 | } 28 | next[i] = j; 29 | } 30 | } 31 | 32 | int kmp(const string& str1, const string& str2) 33 | { 34 | if(str1.size() < str2.size()) { 35 | return -1; 36 | } 37 | 38 | vector next(str2.size(), 0); 39 | get_next(str2, next); 40 | copy(next.begin(), next.end(), ostream_iterator(cout, " ")); 41 | cout << endl; 42 | 43 | int j = -1; 44 | for(int i = 0; i < str1.size(); ++i) { 45 | while(str1[i] != str2[j + 1] && j >= 0) { 46 | j = next[j]; 47 | } 48 | if(str1[i] == str2[j + 1]) { 49 | ++j; 50 | } 51 | if(j == str2.size() - 1) { 52 | return i - j; 53 | } 54 | } 55 | return -1; 56 | } 57 | 58 | int main(int argc, char const *argv[]) 59 | { 60 | string str1("ababcdabd"), str2("abdabdc"); 61 | cout << kmp(str1, str2) << endl; 62 | 63 | return 0; 64 | } -------------------------------------------------------------------------------- /jobdu_oj/1006_zoj.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/3/20 4 | * source: Jobdu OJ 5 | * title: ZOJ problem 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | int main() 15 | { 16 | string str; 17 | bool flag = false; 18 | unsigned int o_left = 0, o_mid = 0, o_right = 0; 19 | 20 | while(cin >> str) { 21 | string::iterator z_iter = str.end(), j_iter = str.end(); 22 | o_left = 0; 23 | o_mid = 0; 24 | o_right = 0; 25 | flag = false; 26 | for(string::iterator iter = str.begin(); iter != str.end(); ++iter) { 27 | if(*iter == 'z' && z_iter == str.end() && j_iter == str.end()) { 28 | z_iter = iter; 29 | } 30 | else if(*iter == 'o' && z_iter == str.end() && j_iter == str.end()) { 31 | ++o_left; 32 | } 33 | else if(*iter == 'o' && z_iter != str.end() && j_iter == str.end()) { 34 | ++o_mid; 35 | } 36 | else if(*iter == 'o' && z_iter != str.end() && j_iter != str.end()) { 37 | ++o_right; 38 | } 39 | else if(*iter == 'j' && z_iter != str.end() && j_iter == str.end()) { 40 | j_iter = iter; 41 | } 42 | else { 43 | cout << "Wrong Answer" << endl; 44 | flag = true; 45 | break; 46 | } 47 | } 48 | 49 | if(flag) 50 | continue; 51 | 52 | if(z_iter != str.end() && j_iter != str.end() && (o_mid == 1 || o_mid == 2) && o_right == o_left * o_mid) { 53 | cout << "Accepted" << endl; 54 | } 55 | else { 56 | cout << "Wrong Answer" << endl; 57 | } 58 | } 59 | 60 | return 0; 61 | } -------------------------------------------------------------------------------- /july_100/25.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/7/7 4 | * source: July的微软面试100题系列 5 | * title: 25.在字符串中找出连续最长的数字串 6 | * language: C++ 7 | * 详细题目: 在字符串中找出连续最长的字符串,并把这个字符串的长度返回。 8 | * 并把这个最长数字串赋给其中一个参数outputstr所指内存。 9 | */ 10 | 11 | #include 12 | 13 | using namespace std; 14 | 15 | int continumax(char *outputstr, char *inputstr) 16 | { 17 | char *str = inputstr; 18 | int len = 0, maxlen = 0; 19 | char *cur = NULL, *maxcur = NULL; 20 | 21 | while(*str != '\0') { 22 | if(*str >= '0' && *str <= '9') { 23 | if(len == 0) { // 长度为0说明新发现了一个数字 24 | cur = str; 25 | len = 1; 26 | } 27 | else { 28 | ++len; 29 | } 30 | } 31 | else { 32 | if(len > maxlen) { 33 | maxlen = len; 34 | maxcur =cur; 35 | } 36 | len = 0; 37 | } 38 | ++str; 39 | } 40 | 41 | int i = 0; 42 | while(i < maxlen) { 43 | *outputstr++ = *maxcur++; 44 | ++i; 45 | } 46 | *outputstr = '\0'; 47 | 48 | return maxlen; 49 | } 50 | 51 | int main(int argc, char const *argv[]) 52 | { 53 | char istr[] = "abcd12345e123456789d125ss"; 54 | char ostr[20] = ""; 55 | cout << continumax(ostr, istr) << endl; 56 | cout << ostr << endl; 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /july_100/29.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/7/7 4 | * source: July的微软面试100题系列 5 | * title: 29.判断某个序列是否可能是栈的push顺序对应的pop顺序 6 | * language: C++ 7 | * 详细题目: 输入两个整数序列,其中一个序列表示栈的push顺序,判断另一个序列是否可能是对应的pop顺序。 8 | * 方法: 用一个栈来处理push序列,看是否可以得到pop序列。当栈不空并且栈顶元素不等于当前pop元素时,说明还没到pop的时候。 9 | * 如果栈不空并且栈顶元素等于当前pop元素,说明可以执行pop操作了。 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | bool is_pop(int push[], int pop[], int n) 18 | { 19 | if(push == NULL || pop == NULL || n <= 0) { 20 | return false; 21 | } 22 | 23 | int i1 = 0, i2 = 0; 24 | stack sta; 25 | 26 | while(i2 < n) { 27 | while(sta.empty() || sta.top() != pop[i2]) { 28 | if(i1 < n) { 29 | sta.push(push[i1++]); 30 | } 31 | else { // i1 >= n说明数据已经全部进栈,但是,进了这个循环则说明数据还没有全部出栈,但是,栈顶元素又不等于当前pop元素,无法出栈。 32 | return false; 33 | } 34 | } 35 | sta.pop(); 36 | ++i2; 37 | } 38 | 39 | if(sta.empty() && i1 == n && i2 == n) { 40 | return true; 41 | } 42 | else { 43 | return false; 44 | } 45 | } 46 | 47 | int main(int argc, char const *argv[]) 48 | { 49 | int push[] = {1, 2, 3, 4, 5}; 50 | int pop[] = {4, 3, 5, 1, 2}; 51 | cout << boolalpha << is_pop(push, pop, 5) << endl; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /july_100/4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/6/27 4 | * source: July的微软面试100题系列 5 | * title: 4.在二叉查找树中找出和为某一值的所有路径 6 | * language: C++ 7 | */ 8 | 9 | #include 10 | #include 11 | #include "btree.hpp" 12 | 13 | using namespace std; 14 | typedef bnode_base bnode; 15 | 16 | void traverse_tree(bnode *pnode, int val, stack sta) 17 | { 18 | if(pnode == NULL) { 19 | return; 20 | } 21 | if(pnode->left == NULL && pnode->right == NULL && pnode->data == val) { 22 | int x = 0; 23 | cout << pnode->data << " "; 24 | while(!sta.empty()) { 25 | x = sta.top(); 26 | sta.pop(); 27 | cout << x << " "; 28 | } 29 | cout << endl; 30 | } 31 | sta.push(pnode->data); 32 | traverse_tree(pnode->left, val - pnode->data, sta); 33 | traverse_tree(pnode->right, val - pnode->data, sta); 34 | } 35 | 36 | void print(int t) 37 | { 38 | cout << t << " "; 39 | } 40 | 41 | void solve(btree &bt, int val) 42 | { 43 | bnode *root = bt.get_root(); 44 | stack sta; 45 | bt.traverse(print); 46 | cout << endl; 47 | sta.push(root->data); 48 | 49 | traverse_tree(root->left, val - root->data, sta); 50 | traverse_tree(root->right, val - root->data, sta); 51 | } 52 | 53 | int main(int argc, char const *argv[]) 54 | { 55 | int arr[] = {10, 5, 12, 7, 0, 0, 0, 0}; 56 | vector vec(arr, arr + sizeof(arr) / sizeof(arr[0])); 57 | btree bt(vec.begin(), vec.end()); 58 | int a = 22; 59 | solve(bt, a); 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /july_100/51.md: -------------------------------------------------------------------------------- 1 | ## 微软面试100题:51 2 | 3 | 题目描述: 4 | 5 | > 输入一个正数n,输出所有和为n的连续正数序列。例如,输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以,输出三个序列:1-5、4-6、7-8。 6 | 7 | ``` C++ 8 | vector > conti_seq(int num) 9 | { 10 | if(num < 3) { 11 | return vector >(); 12 | } 13 | 14 | int start = 1, last = 2; 15 | int s = start + last; 16 | vector > res; 17 | 18 | while(start <= num / 2) { 19 | if(s == num) { 20 | res.push_back(make_pair(start, last)); 21 | ++last; 22 | s += last; 23 | } 24 | else if(s < num) { 25 | ++last; 26 | s += last; 27 | } 28 | else if(s > num) { 29 | s -= start; 30 | ++start; 31 | } 32 | } 33 | 34 | return res; 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /july_100/52.md: -------------------------------------------------------------------------------- 1 | ## 微软面试100题:52 2 | 3 | > 输入一棵二叉树的根节点,求该树的深度。 4 | 5 | 树的节点定义: 6 | 7 | ``` C++ 8 | struct tree_node { 9 | int val; 10 | tree_node *left, *right; 11 | tree_node(int x = 0) : val(x), left(NULL), right(NULL) { } 12 | }; 13 | ``` 14 | 15 | ### 1 递归 16 | 17 | ``` C++ 18 | unsigned int tree_depth_recur(tree_node *root) 19 | { 20 | if(root == NULL) { 21 | return 0; 22 | } 23 | 24 | unsigned int lh = tree_depth_recur(root->left); 25 | unsigned int rh = tree_depth_recur(root->right); 26 | 27 | return (lh > rh) ? (lh + 1) : (rh + 1); 28 | } 29 | ``` 30 | 31 | ### 2 非递归 32 | 33 | ``` C++ 34 | unsigned int tree_depth_nonrecur(tree_node *root) 35 | { 36 | if(root == NULL) { 37 | return 0; 38 | } 39 | 40 | list que1, que2; 41 | que1.push_back(root); 42 | 43 | unsigned int depth = 0; 44 | 45 | while(!que1.empty()) { 46 | 47 | while(!que1.empty()) { 48 | tree_node *pnode = que1.front(); 49 | 50 | if(pnode->left) { 51 | que2.push_back(pnode->left); 52 | } 53 | 54 | if(pnode->right) { 55 | que2.push_back(pnode->right); 56 | } 57 | 58 | que1.pop_front(); 59 | } 60 | 61 | que1.swap(que2); 62 | que2.clear(); 63 | ++depth; 64 | } 65 | 66 | return depth; 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /july_100/9.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2014/6/30 4 | * source: July的微软面试100题系列 5 | * title: 9.判断整数序列是不是二叉查找树的后序遍历结果 6 | * language: C++ 7 | * 本题主要是要明确二叉查找树的性质。判断一个序列是否是二叉查找树的后序遍历的方法是,如果一个序列是二叉查找树的后序遍历,那么最后一个元素就是这个树的根, 8 | * 然后,从前往后遍历,找到第一个比根大的值a,那么根的左子树就是起始元素到a的前一个元素,从a开始到倒数第二个元素就是根的右子树, 9 | * 而且左右子树必须都是二叉查找树。并且,还必须遍历从a开始到倒数第二个元素,检查它们是否比最后一个元素大。 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | bool solve(vector::iterator beg, vector::iterator end) 20 | { 21 | if(beg == end) { 22 | return true; 23 | } 24 | int last = *(end-1); 25 | 26 | vector::iterator iter = beg; 27 | while(iter != end-1 && *iter < last) { 28 | ++iter; 29 | } 30 | vector::iterator iter2 = iter; 31 | while(iter2 != end-1 && *iter2 >= last) { 32 | ++iter2; 33 | } 34 | if(iter2 != end-1) { 35 | return false; 36 | } 37 | --end; 38 | 39 | if(solve(beg, iter) && solve(iter, end)) { 40 | return true; 41 | } 42 | 43 | return false; 44 | } 45 | 46 | int main(int argc, char const *argv[]) 47 | { 48 | int arr[] = {5, 7, 6, 9, 11, 10, 8}; 49 | vector vec(arr, arr+sizeof(arr)/sizeof(arr[0])); 50 | cout << boolalpha << solve(vec.begin(), vec.end()) << endl; 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /july_100/README.md: -------------------------------------------------------------------------------- 1 | ## July微软面试100题系列 2 | 3 | [回到主目录](https://github.com/luofengmacheng/algorithms) 4 | 5 | 4 [在二叉查找树中找出和为某一值的所有路径](https://github.com/luofengmacheng/algorithms/blob/master/july_100/4.cpp) 6 | 7 | 9 [判断整数序列是不是二叉查找树的后序遍历结果](https://github.com/luofengmacheng/algorithms/blob/master/july_100/9.cpp) 8 | 9 | 11 [求二叉树中节点的最大距离](https://github.com/luofengmacheng/algorithms/blob/master/july_100/11.cpp) 10 | 11 | 15 [将一个给定的二叉树转换为它的镜像](https://github.com/luofengmacheng/algorithms/blob/master/july_100/15.cpp) 12 | 13 | 20 [将一个字符串转换为整数](https://github.com/luofengmacheng/algorithms/blob/master/LeetCode/string_to_integer.cpp) 14 | 15 | 25 [在字符串中找出连续最长的数字串](https://github.com/luofengmacheng/algorithms/blob/master/july_100/25.cpp) 16 | 17 | 29 [判断某个序列是否可能是栈的push顺序对应的pop顺序](https://github.com/luofengmacheng/algorithms/blob/master/july_100/29.cpp) 18 | 19 | 30 [求从1到n的正数中1出现的次数](https://github.com/luofengmacheng/algorithms/blob/master/interviewOffer/32.md) 20 | 21 | 43 [二叉树的非递归遍历](https://github.com/luofengmacheng/algorithms/blob/master/myalgo/nonrecursion_traversal.md) 22 | 23 | 51 [和为n的连续正数序列](https://github.com/luofengmacheng/algorithms/blob/master/july_100/51.md) 24 | 25 | 52 [二叉树的深度](https://github.com/luofengmacheng/algorithms/blob/master/july_100/52.md) 26 | -------------------------------------------------------------------------------- /misc/bisearch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/25 4 | * info: 二分查找 5 | */ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | vector vec; 14 | vec.push_back(1); 15 | vec.push_back(2); 16 | vec.push_back(3); 17 | vec.push_back(4); 18 | vec.push_back(5); 19 | vec.push_back(6); 20 | 21 | int target = 1; 22 | int left = 0, right = vec.size()-1; 23 | int mid = 0; 24 | while(left < right) { 25 | mid = (left+right)/2; 26 | if(target < vec[mid]) 27 | right = mid-1; 28 | else if(target > vec[mid]) 29 | left = mid+1; 30 | else 31 | break; 32 | } 33 | cout< 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | double eta[1000][1514]; 13 | double tag2word[1514][17316]; 14 | double res[1000][17316]; 15 | 16 | 17 | /* int i = 0, j = 0, k = 0; 18 | for(i = 0; i < 1000; i++) 19 | for(j = 0; j < 17316; j++) { 20 | res[i][j] = 0; 21 | for(k = 0; k < 1514; k++) { 22 | res[i][j] += eta[i][k]*tag2word[k][j]; 23 | } 24 | } 25 | */ 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /misc/move_all_zeroes_end.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/18 4 | * source: GeeksforGeeks 5 | * title: Move all zeros to end of array 6 | * solution URL:http://www.geeksforgeeks.org/move-zeroes-end-array/ 7 | * info: 8 | 9 | Given an array of random numbers, Push all the zero’s of a given array to the end of the array. For example, if the given arrays is {1, 9, 8, 4, 0, 0, 2, 7, 0, 6, 0}, it should be changed to {1, 9, 8, 4, 2, 7, 6, 0, 0, 0, 0}. The order of all other elements should be same. Expected time complexity is O(n) and extra space is O(1). 10 | 11 | */ 12 | 13 | #include 14 | 15 | void move_all_zeroes_end(int arr[], int size) 16 | { 17 | int i = 0, j = 0; 18 | 19 | for(i = 0; i < size; i++) { 20 | if(arr[i]) 21 | arr[j++] = arr[i]; 22 | } 23 | 24 | while(j < size) 25 | arr[j++] = 0; 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | int arr[] = {1, 9, 8, 4, 0, 0, 2, 7, 0, 6, 0}; 31 | int len = sizeof(arr)/sizeof(int); 32 | 33 | move_all_zeroes_end(arr, len); 34 | int i = 0; 35 | for(i = 0; i < len; i++) 36 | printf("%d\t", arr[i]); 37 | 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /misc/runtime_duration.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/17 4 | * info: 测试程序运行的时间 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | long start_sec, finish_sec, start_usec, finish_usec; 13 | struct timeval tv; 14 | struct timezone tz; 15 | 16 | gettimeofday(&tv, &tz); 17 | start_sec = tv.tv_sec; 18 | start_usec = tv.tv_usec; 19 | 20 | 21 | gettimeofday(&tv, &tz); 22 | finish_sec = tv.tv_sec; 23 | finish_usec = tv.tv_usec; 24 | 25 | double duration = (double)(finish_usec-start_usec)/1000+(finish_sec-start_sec)*1000; 26 | printf("Runtime: %.3fms\n", duration); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /myalgo/fdisk_mkfs.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/fdisk_mkfs.md -------------------------------------------------------------------------------- /myalgo/fopen_error.md: -------------------------------------------------------------------------------- 1 | ## 解决ubuntu 13.04中fopen打开大于2GB文件失败的问题 2 | 3 | ### 1 问题的由来 4 | 5 | 在ubuntu中运行别人的一个程序,这个程序打开一个文件,读取数据,进行处理。 6 | 7 | ``` C 8 | FILE *fin; 9 | 10 | fin = fopen(train_file, "rb"); 11 | if (fin == NULL) { 12 | printf("ERROR: training data file not found!\n"); 13 | exit(1); 14 | } 15 | 16 | /* read data and process it */ 17 | ``` 18 | 19 | 但是,程序打印ERROR: training data file not found!就退出了。 20 | 21 | ### 2 分析问题 22 | 23 | 也就是说打开文件失败了,个人觉得,可能的原因有以下几个: 24 | 25 | * 路径错误 26 | * 权限问题 27 | 28 | 路径错误是不可能的,因为笔者是直接将处理文件拷贝到可执行文件所在目录下。 29 | 30 | 考虑权限问题,于是,将权限修改为777,问题依旧,因此,也不可能是权限问题。 31 | 32 | 想到有个perror可以打印错误信息,于是,就在printf下面添加了perror("error");,错误信息为: 33 | 34 | ``` 35 | error: Value too large for defined data type 36 | ``` 37 | 38 | 想到,可能是处理的文件太大了,处理的文件有2.1GB,很有可能。 39 | 40 | 在网上搜索,发现确实有这个问题。 41 | 42 | ### 3 解决问题 43 | 44 | 在编译选项中添加 -D_FILE_OFFSET_BITS=64 即可。 45 | 46 | ### 4 小结 47 | 48 | 从以上知道,在编程时,一定要给出确切的错误信息。在这里,文件打开失败一定是文件不存在吗,当然不一定,有可能还有别的原因。 49 | 50 | 在这里,由于有源代码,可以查看源代码,然后修改,如果没有源代码,那给出的错误信息就对用户有一定的误导。 51 | 52 | 因此,尽量用系统的错误信息打印语句,像perror、strerror都可以。 53 | 54 | 参考文档: 55 | 56 | 1 [linux环境下读写超过2G的大文件](http://blog.163.com/b__v/blog/static/70977362011315103653804/) 57 | -------------------------------------------------------------------------------- /myalgo/hadoop_wordcount.md: -------------------------------------------------------------------------------- 1 | ## hadoop运行WordCount程序 2 | 3 | 使用hadoop standalone模式运行WordCount程序。 4 | 5 | ### 1 安装JDK 6 | 7 | 从[Java Downloads](http://www.oracle.com/technetwork/java/javase/downloads/index.html)上下载JDK。 8 | 9 | 把下载的压缩包解压到要安装的目录,笔者一般安装到/usr/local/目录下,因此,把压缩包解压到/usr/local/下。 10 | 11 | 然后添加环境变量,可以在/etc/profile和~/.bashrc中添加,前者使得所有用户有效,后者只修改当前用户,这里修改~/.bashrc,在该文件末尾添加下列环境变量: 12 | 13 | ``` 14 | export JAVA_HOME=/usr/local/jdk1.7.0_75 15 | export JAVA_BIN=$JAVA_HOME/bin 16 | export PATH=$PATH:$JAVA_BIN 17 | export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 18 | export JAVA_HOME JAVA_BIN PATH CLASSPATH 19 | ``` 20 | 21 | 然后运行下列命令使bashrc立即生效: 22 | 23 | ``` 24 | source .bashrc 25 | ``` 26 | 27 | 接着就可以运行javac和java了。 28 | 29 | ### 2 安装hadoop 30 | 31 | 从[hadoop Download](http://www.apache.org/dyn/closer.cgi/hadoop/common/)下载hadoop。同样,将它解压到/usr/local/目录下。 32 | 33 | 然后就可以运行hadoop目录下的bin目录中的hadoop。 34 | 35 | ### 3 运行WordCount 36 | 37 | 从网上下载一个WordCount.java程序。 38 | 39 | #### 3.1 编译 40 | 41 | ``` java 42 | javac -classpath /usr/local/hadoop-2.6.0/share/hadoop/common/*:/usr/local/hadoop-2.6.0/share/hadoop/mapreduce/*:/usr/local/hadoop-2.6.0/share/hadoop/tools/lib/* ./WordCount.java 43 | ``` 44 | 45 | 为了编译的简便,直接加入了common、mapreduce、tools下的jar包。再将生成的3个class文件打包: 46 | 47 | ``` 48 | jar -cvf WordCount.jar *.class 49 | ``` 50 | 51 | #### 3.2 运行 52 | 53 | 现在,就可以启动hadoop运行了。 54 | 55 | 该程序的输入和输出都是文件夹。创建input目录,其中放置要统计的文件。 56 | 57 | 执行hadoop: 58 | 59 | ``` 60 | /usr/local/hadoop-2.6.0/bin/hadoop jar WordCount.jar WordCount input output 61 | ``` 62 | 63 | 其中WordCount.jar就是程序的jar包,WordCount是程序的主类,后面两个参数分别是输入和输出。 64 | 65 | 运行之后,会生成output目录,其中存放统计的结果。结果的文件夹名为:part-r-0000。可以直接用vi或者gedit查看。 66 | -------------------------------------------------------------------------------- /myalgo/java_run.md: -------------------------------------------------------------------------------- 1 | ## linux命令行下执行java程序 2 | 3 | 运行java程序之前要安装jdk和jre,一般jdk中包含了jre。 4 | 5 | ### 1 没有包结构的情形 6 | 7 | 没有包结构的情况比较简单,比较适合小的工程。 8 | 9 | 编写代码hello.java: 10 | 11 | ``` java 12 | public class hello { 13 | 14 | 15 | public static void main(String[] args) { 16 | System.out.println("hello"); 17 | } 18 | } 19 | ``` 20 | 21 | 然后就可以直接在命令行下运行: 22 | 23 | ``` 24 | javac hello.java 25 | 26 | java hello 27 | ``` 28 | 29 | ### 2 有包结构的情形 30 | 31 | 当代码前面有package语句时,package后面的包名必须是当前代码所在的目录名。 32 | 33 | 例如: 34 | 35 | ``` java 36 | package luo; 37 | 38 | public class hello { 39 | 40 | 41 | public static void main(String[] args) { 42 | System.out.println("hello"); 43 | } 44 | } 45 | ``` 46 | 47 | 把它编译为字节码: 48 | 49 | ``` 50 | javac hello.java 51 | ``` 52 | 53 | 执行时要注意两点: 54 | 55 | * 1 必须在包的目录的上层目录中执行,例如,这里是luo这个包,就必须在luo这个目录的上层目录中执行。 56 | * 2 执行的主类必须带有主类的包结构,例如,这里的主类hello位于luo这个包中,执行时就必须用luo.hello。 57 | 58 | 因此,在luo这个文件夹所在的文件夹中执行java luo.hello。 59 | 60 | ### 3 引用其它的jar包 61 | 62 | 如果代码中引用了其它的jar包,则需要在编译和运行时能够找到那些类。 63 | 64 | http://blog.sina.com.cn/s/blog_637800000100r904.html 65 | -------------------------------------------------------------------------------- /myalgo/linux_limits.md: -------------------------------------------------------------------------------- 1 | ## 修改linux的各种限制及ulimit命令的使用 2 | 3 | ### 1 引言 4 | 5 | 在linux下有各种限制,用ulimit命令可以显示这些限制: 6 | 7 | ``` 8 | $ulimit -a 9 | core file size (blocks, -c) 0 10 | data seg size (kbytes, -d) unlimited 11 | scheduling priority (-e) 0 12 | file size (blocks, -f) unlimited 13 | pending signals (-i) 31912 14 | max locked memory (kbytes, -l) 64 15 | max memory size (kbytes, -m) unlimited 16 | open files (-n) 1024 17 | pipe size (512 bytes, -p) 8 18 | POSIX message queues (bytes, -q) 819200 19 | real-time priority (-r) 0 20 | stack size (kbytes, -s) 8192 21 | cpu time (seconds, -t) unlimited 22 | max user processes (-u) 31912 23 | virtual memory (kbytes, -v) unlimited 24 | file locks (-x) unlimited 25 | ``` 26 | 27 | ### 2 修改限制 28 | 29 | 最常见要修改的限制是open files,默认是1024,这对于一般的应用是足够的,但是,对于大规模的文件处理时,就需要修改。 30 | 31 | 修改方式如下: 32 | 33 | 1 在/etc/security/limits.conf结尾添加 34 | 35 | ``` 36 | * - nofile 40960 37 | ``` 38 | 39 | 2 在/etc/pam.d/login添加 40 | 41 | session required /lib/security/pam_limit.so 42 | 43 | 然后重启系统即可,然后用ulimit命令查看。 44 | 45 | 注意:网上使用ulimit命令修改,在ubuntu上没有效果。 46 | -------------------------------------------------------------------------------- /myalgo/pics/about_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/about_test.png -------------------------------------------------------------------------------- /myalgo/pics/about_test_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/about_test_1.png -------------------------------------------------------------------------------- /myalgo/pics/about_test_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/about_test_2.png -------------------------------------------------------------------------------- /myalgo/pics/about_test_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/about_test_3.png -------------------------------------------------------------------------------- /myalgo/pics/about_test_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/about_test_4.png -------------------------------------------------------------------------------- /myalgo/pics/about_test_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/about_test_5.png -------------------------------------------------------------------------------- /myalgo/pics/about_test_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/about_test_6.png -------------------------------------------------------------------------------- /myalgo/pics/about_test_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/about_test_7.png -------------------------------------------------------------------------------- /myalgo/pics/fdisk_p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/fdisk_p.png -------------------------------------------------------------------------------- /myalgo/pics/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/pic1.png -------------------------------------------------------------------------------- /myalgo/pics/sublime_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luofengmacheng/algorithms/31ca8d9342a9fe63eda646e781430a3f906b03bd/myalgo/pics/sublime_layout.png -------------------------------------------------------------------------------- /myalgo/vim_color.md: -------------------------------------------------------------------------------- 1 | ## vim的配色方案的调整 2 | 3 | 用vim编写程序时,有时需要调整vim的默认配色方案,例如,我就很喜欢sublime的Monokai配色方案,那么,我可能就会想将vim的配色方案变成Monokai,但是,vim的配色方案中是没有Monokai的,那怎么办呢? 4 | 5 | ### 1 与vim配色方案相关的文件 6 | 7 | 与vim配色方案相关的文件有主文件夹的部分和系统部分。 8 | 9 | 主文件夹的部分有:~/.vimrc和~/.vim/colors/,.vimrc是vim的设置文件,与配色相关的就是文件中的colorscheme那一行。.vim/colors/是某个用户的配色方案文件夹。 10 | 11 | 系统部分有:/usr/share/vim/vim73/colors/,这个是存放所有用户的vim的配色方案,当然,有可能因为版本不同而路径不完全一样。 12 | 13 | 因此,要修改配色方案,只要修改这两部分就行。 14 | 15 | ### 2 将配色方案调整为sublime的Monokai 16 | 17 | 先去[vim-monokia](https://github.com/sickill/vim-monokai)下载monokai配色方案。 18 | 19 | 如果将monokai.vim拷贝到/usr/share/vim/vim73/colors/目录下,那么,系统所有用户都可以使用该配色方案。如果将monokai拷贝到~/.vim/colors/目录下,那么,只有该用户才能使用该配色方案。 20 | 21 | 然后,将colorscheme那一行改为colorscheme monokai(如果没有的话,就添加),然后打开vim就可以了。 22 | -------------------------------------------------------------------------------- /project/losf.txt: -------------------------------------------------------------------------------- 1 | Lustre中小文件存在的问题: 2 | (1)元数据和文件本身的数据分开存储,用户在读小文件之前需要先同MDS交互,以获得目标小文件的位置。和传统的本地文件系统相比,这一过程相当于增加了一次额外的网络传输开销和元数据服务器的访问开销。对小文件来说,这两项额外开销都是相当大的。 3 | (2)Cache设计对小文件I/O性能的作用不明显。客户端Cache只对本机有效,不同客户端访问OSD的同一部分文件数据时,每个用户都需要先把数据从OSD复制到本地Cache中。如果要访问的文件内容只占页内很少一部分,也要先把整个物理页从OSD端的磁盘读入操作系统的文件缓存中再访问。 4 | (3)OSD后端磁盘文件系统的小文件读写性能不好,读写小文件时,磁盘寻址带来的延时对一次小文件I/O操作的总时间来说,占很大比例。 5 | 6 | 服务器驱动的元数据预取和命名空间平坦化: 7 | 修改对象的元数据,在对象元数据中增加反映对象之间关系的字段。每次访问MDS进行元数据操作时,预取和本次访问的对象相关的其它对象的元数据,以减少访问MDS的次数。 8 | 9 | idea 1: 大文件和小文件分开存储 10 | 11 | 针对Lustre的I/O特点,要改善其小文件性能,有两条途径: 12 | (1)改善Lustre的I/O流程,减少小文件I/O操作时的网络开销。 13 | (2)改善Lustre后端存储设备的性能,降低小文件I/O操作时访问存储设备的延时。 14 | 15 | question 1: 如何判断小文件I/O? 16 | 17 | question 2: OSD端做了缓存吗? 18 | 19 | question 3: 对象条块化所基于的大小? 20 | -------------------------------------------------------------------------------- /sgi_stl/1.8.3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | #if defined(__sgi) 8 | cout << "__sgi" << endl; 9 | #endif 10 | 11 | #if defined(__GNUC__) 12 | cout << "__GNUC__" << endl; 13 | cout << __GNUC__ << ' ' << __GNUC_MINOR__ << endl; 14 | #endif 15 | 16 | #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG 17 | cout << "__STL_STATIC_TEMPLATE_MEMBER_BUG defined" << endl; 18 | #else 19 | cout << "__STL_STATIC_TEMPLATE_MEMBER_BUG undefined" << endl; 20 | #endif 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /sgi_stl/1.9.3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | template 5 | class testClass { 6 | public: 7 | static const int _datai = 5; 8 | static const long _datal = 3L; 9 | static const char _datac = 'c'; 10 | }; 11 | 12 | int main() 13 | { 14 | cout << testClass::_datai << endl; 15 | cout << testClass::_datal << endl; 16 | cout << testClass::_datac << endl; 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /sgi_stl/1.9.4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class INT { 7 | friend ostream& operator<<(ostream& os, const INT& i); 8 | 9 | public: 10 | INT(int i) : m_i(i) {} 11 | INT(const INT& I) : m_i(I.m_i) {} 12 | 13 | INT& operator++() 14 | { 15 | ++(this->m_i); 16 | return *this; 17 | } 18 | 19 | //问题一:后置自增和自减运算的返回值为什么是对象,而且是const对象 20 | //是因为不允许I++++吗,那++++I呢? 21 | const INT operator++(int) 22 | { 23 | const INT tmp(*this); 24 | ++(*this); 25 | return tmp; 26 | } 27 | 28 | INT& operator--() 29 | { 30 | --(this->m_i); 31 | return *this; 32 | } 33 | 34 | const INT operator--(int) 35 | { 36 | const INT tmp(*this); 37 | --(*this); 38 | return tmp; 39 | } 40 | 41 | //问题二:解引用操作符获取引用时,为什么一定要进行类型转换 42 | int& operator*() const 43 | { 44 | cout << boolalpha << (typeid(const INT) == typeid(*this)) << endl; 45 | cout << boolalpha << (typeid(const int) == typeid(m_i)) << endl; 46 | return m_i; 47 | } 48 | 49 | private: 50 | int m_i; 51 | }; 52 | 53 | ostream& operator<<(ostream& os, const INT& i) 54 | { 55 | os << '[' << i.m_i << ']'; 56 | return os; 57 | } 58 | 59 | int main() 60 | { 61 | INT I(5); 62 | cout << I++ << endl; 63 | cout << ++I << endl; 64 | cout << I-- << endl; 65 | cout << --I << endl; 66 | cout << *I << endl; 67 | 68 | int i = 0; 69 | cout << ++++i << endl; 70 | //cout << i++++ << endl; 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /sgi_stl/1.9.6.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | template 5 | struct plus1 { 6 | T operator()(const T& x, const T& y) const 7 | { 8 | return x + y; 9 | } 10 | }; 11 | 12 | template 13 | struct minus1 { 14 | T operator()(const T& x, const T& y) const 15 | { 16 | return x - y; 17 | } 18 | }; 19 | 20 | int main() 21 | { 22 | plus1 plusobj; 23 | minus1 minusobj; 24 | 25 | cout << plusobj(3, 5) << endl; 26 | cout << minusobj(3, 5) << endl; 27 | 28 | cout << plus1()(43, 50) << endl; 29 | cout << minus1()(43, 50) << endl; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /sgi_stl/1config.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | #if defined(__sgi) 8 | cout << "__sgi" << endl; 9 | #endif 10 | 11 | #if defined(__GNUC__) 12 | cout << "__GNUC__" << endl; 13 | cout << __GNUC__ << ' ' << __GNUC_MINOR__ << endl; 14 | #endif 15 | 16 | #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG 17 | cout << "__STL_STATIC_TEMPLATE_MEMBER_BUG defined" << endl; 18 | #else 19 | cout << "__STL_STATIC_TEMPLATE_MEMBER_BUG undefined" << endl; 20 | #endif 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /sgi_stl/2chapter/2.1.1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "2.1.1.hpp" 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | int ia[5] = {0, 1, 2, 3, 4}; 9 | unsigned int i; 10 | 11 | vector > iv(ia, ia + 5); 12 | for(i = 0; i < iv.size(); ++i) 13 | cout << iv[i] << ' '; 14 | cout << endl; 15 | } 16 | -------------------------------------------------------------------------------- /sgi_stl/4chapter/4.4.5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | deque > ideq(20, 9); 9 | cout << "size = " << ideq.size() << endl; 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /skill.md: -------------------------------------------------------------------------------- 1 | 1 远程重启计算机 2 | ``` 3 | echo b > /proc/sysrq-trigger 4 | ``` 5 | 6 | 2 查看内存使用情况 7 | ``` 8 | free -m //以MB为单位查看内存使用情况 9 | ``` 10 | 11 | 3 修改计算机的可用内存 12 | 13 | 对于Redhat系(包括Fedora) 14 | 15 | 修改/etc/grub.conf,在kernel一行最后添加mem=1G就能够将可用内存修改为1GB 16 | ``` 17 | title Red Hat Enterprise Linux Server (2.6.27) 18 | root (hd0,1) 19 | kernel /vmlinuz-2.6.27 ro root=/dev/VolGroup00/LogVol00 rhgb quiet acpi=ht mem=1G 20 | initrd /initrd-2.6.27.img 21 | ``` 22 | 23 | 4 查看系统的IO统计信息 24 | ``` 25 | iostat -k 3 //以KB打印结果,3秒显示一次 26 | ``` 27 | 28 | 5 将一个进程放入后台,并使它不受前台的影响,特别是用于远程连接时 29 | ``` 30 | ./test //运行程序 31 | ^Z //ctrl+z使程序暂停 32 | bg %(jobid) //将程序放入后台运行 33 | disown -h %(jobid) 34 | ``` 35 | -------------------------------------------------------------------------------- /sort/bubble_sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/11 4 | * info: 冒泡排序 5 | */ 6 | 7 | #include 8 | 9 | void print_res(int arr[], int size) 10 | { 11 | int i = 0; 12 | 13 | while(i < size) { 14 | printf("%d\t", arr[i]); 15 | i++; 16 | } 17 | printf("\n"); 18 | } 19 | 20 | void swap(int *a, int *b) 21 | { 22 | int temp = *a; 23 | *a = *b; 24 | *b = temp; 25 | } 26 | 27 | void bubble_sort(int array[], int size) 28 | { 29 | int i = 0, j = 0; 30 | 31 | for(i = 0; i < size; i++) 32 | for(j = i+1; j < size; j++) 33 | if(array[i] > array[j]) 34 | swap(&array[i], &array[j]); 35 | } 36 | 37 | int main(int argc, char argv[]) 38 | { 39 | int arr[] = {3, 5, 2, 7, 0}; 40 | int len = sizeof(arr)/sizeof(int); 41 | 42 | bubble_sort(arr, len); 43 | print_res(arr, len); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /sort/heap_sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/11 4 | * info: 堆排序 5 | */ 6 | 7 | #include 8 | 9 | void print_res(int arr[], int size) 10 | { 11 | int i = 0; 12 | 13 | while(i < size) { 14 | printf("%d\t", arr[i]); 15 | i++; 16 | } 17 | printf("\n"); 18 | } 19 | 20 | void swap(int *a, int *b) 21 | { 22 | int temp = *a; 23 | *a = *b; 24 | *b = temp; 25 | } 26 | 27 | void heap_adjust(int array[], int i_parent, int size) 28 | { 29 | int parent = array[i_parent]; 30 | int i_child = 2*i_parent+1; 31 | 32 | while(i_child < size) { 33 | if(i_child+1 < size && array[i_child] < array[i_child+1]) 34 | i_child++; 35 | 36 | if(parent >array[i_child]) 37 | break; 38 | 39 | array[i_parent] = array[i_child]; 40 | i_parent = i_child; 41 | i_child = 2*i_parent+1; 42 | } 43 | array[i_parent] = parent; 44 | } 45 | 46 | void heap_sort(int array[], int size, int top) 47 | { 48 | int i = 0; 49 | 50 | for(i = size/2-1; i >= 0; i--) 51 | heap_adjust(array, i, size); 52 | 53 | for(i = size-1; i > size-top; i--) { 54 | swap(&array[0], &array[i]); 55 | 56 | heap_adjust(array, 0, i); 57 | } 58 | } 59 | 60 | int main(int argc, char argv[]) 61 | { 62 | int arr[] = {3, 5, 2, 7, 0}; 63 | int len = sizeof(arr)/sizeof(int); 64 | 65 | heap_sort(arr, len, 5); 66 | print_res(arr, len); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /sort/insert_sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/11 4 | * info: 直接插入排序 5 | */ 6 | 7 | #include 8 | 9 | void print_res(int arr[], int size) 10 | { 11 | int i = 0; 12 | 13 | while(i < size) { 14 | printf("%d\t", arr[i]); 15 | i++; 16 | } 17 | printf("\n"); 18 | } 19 | 20 | void insert_sort(int array[], int size) 21 | { 22 | int i = 0, j = 0; 23 | 24 | for(i = 1; i < size; i++) { 25 | int temp = array[i]; 26 | for(j = i-1; j >= 0 && array[j] >= temp; j--) 27 | array[j+1] = array[j]; 28 | array[j+1] = temp; 29 | } 30 | } 31 | 32 | void swap(int *a, int *b) 33 | { 34 | int temp = *a; 35 | *a = *b; 36 | *b = temp; 37 | } 38 | 39 | void insert_sort2(int array[], int size) 40 | { 41 | int i = 0, j = 0; 42 | 43 | for(i = 1; i < size; i++) 44 | for(j = i-1; j >= 0 && array[j] >= array[j+1]; j--) 45 | swap(&array[j], &array[j+1]); 46 | } 47 | 48 | int main(int argc, char argv[]) 49 | { 50 | int arr[] = {3, 5, 2, 7, 0}; 51 | int len = sizeof(arr)/sizeof(int); 52 | 53 | insert_sort2(arr, len); 54 | print_res(arr, len); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /sort/quick_sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/11 4 | * info: 快速排序 5 | */ 6 | 7 | #include 8 | 9 | void print_res(int arr[], int size) 10 | { 11 | int i = 0; 12 | 13 | while(i < size) { 14 | printf("%d\t", arr[i]); 15 | i++; 16 | } 17 | printf("\n"); 18 | } 19 | 20 | void swap(int *a, int *b) 21 | { 22 | int temp = *a; 23 | *a = *b; 24 | *b = temp; 25 | } 26 | 27 | void quick_sort(int array[], int i_left, int i_right) 28 | { 29 | if(i_left < i_right) { 30 | int mid = array[i_left]; 31 | int i = i_left, j = i_right; 32 | 33 | while(i < j) { 34 | while(i < j && array[j] > mid) 35 | j--; 36 | if(i < j) 37 | array[i++] = array[j]; 38 | 39 | while(i < j && array[i] < mid) 40 | i++; 41 | if(i < j) 42 | array[j--] = array[i]; 43 | } 44 | array[i] = mid; 45 | 46 | quick_sort(array, i_left, i-1); 47 | quick_sort(array, i+1, i_right); 48 | } 49 | } 50 | 51 | int main(int argc, char argv[]) 52 | { 53 | int arr[] = {3, 5, 2, 7, 0}; 54 | int len = sizeof(arr)/sizeof(int); 55 | 56 | quick_sort(arr, 0, len-1); 57 | print_res(arr, len); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /sort/select_sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/11 4 | * info: 直接选择排序 5 | */ 6 | 7 | #include 8 | 9 | void print_res(int arr[], int size) 10 | { 11 | int i = 0; 12 | 13 | while(i < size) { 14 | printf("%d\t", arr[i]); 15 | i++; 16 | } 17 | printf("\n"); 18 | } 19 | 20 | void swap(int *a, int *b) 21 | { 22 | int temp = *a; 23 | *a = *b; 24 | *b = temp; 25 | } 26 | 27 | void select_sort(int array[], int size) 28 | { 29 | int i = 0, j = 0; 30 | int i_min = 0; 31 | 32 | for(i = 0; i < size; i++) { 33 | i_min = i; 34 | for(j = i+1; j < size; j++) { 35 | if(array[i_min] > array[j]) 36 | i_min = j; 37 | } 38 | if(i_min != i) 39 | swap(&array[i_min], &array[i]); 40 | } 41 | } 42 | 43 | int main(int argc, char argv[]) 44 | { 45 | int arr[] = {3, 5, 2, 7, 0}; 46 | int len = sizeof(arr)/sizeof(int); 47 | 48 | select_sort(arr, len); 49 | print_res(arr, len); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /sort/shell_sort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/11 4 | * info: 希尔排序 5 | */ 6 | 7 | #include 8 | 9 | void print_res(int arr[], int size) 10 | { 11 | int i = 0; 12 | 13 | while(i < size) { 14 | printf("%d\t", arr[i]); 15 | i++; 16 | } 17 | printf("\n"); 18 | } 19 | 20 | void swap(int *a, int *b) 21 | { 22 | int temp = *a; 23 | *a = *b; 24 | *b = temp; 25 | } 26 | 27 | void shell_sort(int array[], int size) 28 | { 29 | int step = 0, i = 0, j = 0; 30 | 31 | for(step = size/2; step > 0; step /= 2) { 32 | for(i = step; i < size; i++) 33 | for(j = i-step; j >= 0 && array[j] >= array[j+step]; j -= step) 34 | swap(&array[j], &array[j+step]); 35 | } 36 | } 37 | 38 | int main(int argc, char argv[]) 39 | { 40 | int arr[] = {3, 5, 2, 7, 0}; 41 | int len = sizeof(arr)/sizeof(int); 42 | 43 | shell_sort(arr, len); 44 | print_res(arr, len); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /stack/stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** program name: stack.c 3 | ** author: luo feng 4 | ** date: 2013/9/12 5 | */ 6 | 7 | #include "stack.h" 8 | 9 | /* 10 | **initialize a stack 11 | */ 12 | status stack_init() 13 | { 14 | stack_index = 0; 15 | } 16 | 17 | /* 18 | **push an element into a stack 19 | */ 20 | status stack_push(stack_elem st_elem) 21 | { 22 | if(stack_index == STACK_SIZE-1) 23 | return FAIL_FULL; 24 | 25 | Stack[++stack_index] = st_elem; 26 | return SUCCESS; 27 | } 28 | 29 | /* 30 | **pop an element from a stack 31 | */ 32 | status stack_pop(stack_elem *st_elem) 33 | { 34 | if(stack_index == 0) 35 | return FAIL_EMPTY; 36 | 37 | *st_elem = Stack[stack_index--]; 38 | return SUCCESS; 39 | } 40 | 41 | /* 42 | **get the top element from a stack 43 | */ 44 | status stack_top(stack_elem *st_elem) 45 | { 46 | if(stack_index == 0) 47 | return FAIL_EMPTY; 48 | 49 | *st_elem = Stack[stack_index]; 50 | return SUCCESS; 51 | } 52 | -------------------------------------------------------------------------------- /stack/stack.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** program name: stack.h 3 | ** author: luo feng 4 | ** date: 2013/9/12 5 | */ 6 | 7 | #ifndef _STACK_H 8 | #define _STACK_H 9 | #include "status.h" 10 | 11 | #define STACK_SIZE 256 12 | 13 | //stack type definition 14 | typedef int stack_elem; 15 | typedef stack_elem *stack; 16 | 17 | //stack definition 18 | stack_elem Stack[STACK_SIZE]; 19 | int stack_index; 20 | 21 | //stack operation declare 22 | status stack_init(); 23 | status stack_push(stack_elem); 24 | status stack_pop(stack_elem*); 25 | status stack_top(stack_elem*); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /stack/status.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** program name: status.h 3 | ** author: luo feng 4 | ** date: 2013/9/12 5 | */ 6 | 7 | #ifndef _STATUS_H 8 | #define _STATUS_H 9 | 10 | typedef enum status { 11 | SUCCESS, //operation success 12 | FAIL_FULL, //operation fail because stack is full 13 | FAIL_EMPTY //operation fail because stack is empty 14 | } status; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /stack/template.c: -------------------------------------------------------------------------------- 1 | /* 2 | * author: luo feng 3 | * date: 2013/10/11 4 | * info: 5 | */ 6 | 7 | #include 8 | 9 | void print_res(int arr[], int size) 10 | { 11 | int i = 0; 12 | 13 | while(i < size) { 14 | printf("%d\t", arr[i]); 15 | i++; 16 | } 17 | printf("\n"); 18 | } 19 | 20 | void swap(int *a, int *b) 21 | { 22 | int temp = *a; 23 | *a = *b; 24 | *b = temp; 25 | } 26 | 27 | int main(int argc, char argv[]) 28 | { 29 | int arr[] = {3, 5, 2, 7, 0}; 30 | int len = sizeof(arr)/sizeof(int); 31 | 32 | (arr, len); 33 | print_res(arr, len); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /stack/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "status.h" 3 | #include "stack.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | stack_init(); 8 | 9 | stack_push(1); 10 | stack_push(2); 11 | stack_push(3); 12 | stack_push(4); 13 | 14 | stack_elem ret = 0; 15 | stack_pop(&ret); 16 | printf("%d\n", ret); 17 | stack_pop(&ret); 18 | printf("%d\n", ret); 19 | stack_pop(&ret); 20 | printf("%d\n", ret); 21 | stack_pop(&ret); 22 | printf("%d\n", ret); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /summary/2016.md: -------------------------------------------------------------------------------- 1 | ### 2016年终总结 2 | 3 | > 前言: 虽然,我依旧还是那个我,但是,我心中仍有一个梦想。在这年终之际,还是需要对过去一年的工作和生活进行总结,好的继续发扬,不好的想办法改掉。 4 | 5 | #### 1 工作 6 | 7 | 过去一年,个人的主要工作重点在小组内部的发布平台上,上半年集中在海外发布,下半年集中在国内发布以及系统切割。 8 | 9 | 在工作中,我学会了下面这些`法则`: 10 | 11 | * 把事情做好。当需要完成一个任务时,不要想着只是完成这件事本身,而是要把这件事做`好`,这就意味着,不能单纯地只是完成"某个功能",修改"某个BUG",在完成功能时,要想着:实现这个功能有什么更好的方案;实现这个功能的过程中的每一步是否都做了完整的验证(如路径的验证;文件的验证等); 12 | * 需求一定要与当事人进行沟通。有时候在功能开发初期没有与用户沟通清楚,按照自己的思路进行开发,即使开发过程中解决了很多问题,但是,最终的结果 13 | 14 | #### 2 生活 15 | 16 | 这一年,发生了几件大事: 17 | 18 | * 3月8日结婚登记。 19 | * 五一武汉买房。 20 | * 下半年老婆怀孕。 21 | 22 | #### 3 总结 23 | 24 | #### 4 展望未来 25 | 26 | ##### 4.1 技术 27 | 28 | * redis 29 | * zookeeper 30 | * nginx 31 | 32 | ##### 4.2 业务 33 | 34 | 熟悉支付相关的业务,包括几大系统之间的调用关系。 35 | 36 | ##### 4.3 其它 -------------------------------------------------------------------------------- /summary/README.md: -------------------------------------------------------------------------------- 1 | ### [2016年终总结](https://github.com/luofengmacheng/algorithms/blob/master/summary/2016.md) -------------------------------------------------------------------------------- /sys_install.md: -------------------------------------------------------------------------------- 1 | 1 mentohust 2 | 3 | 2 sublime 4 | 5 | 2 git 6 | 7 | 3 sudo apt-get install build-essential 8 | 9 | 4 fcitx 10 | 11 | sudo apt-get install fcitx 12 | 13 | sudo apt-get install fcitx-sunpinyin 14 | 15 | 16 | 5 wine & source insight 17 | 18 | 6 Dropbox (backup) 19 | 20 | 7 boost 21 | ``` 22 | 下载boost,解压 23 | ./booststrap 24 | ./b2 25 | ``` 26 | 27 | 8 golang 28 | 29 | golang.org的官方网站被屏蔽了,可以通过下面的镜像网站下载: 30 | 31 | [http://tip.golang.so/](http://tip.golang.so/) 32 | 33 | [golang中文社区](http://golang.so/) 34 | -------------------------------------------------------------------------------- /tcpl/README.md: -------------------------------------------------------------------------------- 1 | ## C++语言程序设计 2 | 3 | [回到主目录](https://github.com/luofengmacheng/algorithms) 4 | 5 | 1 [面向对象的三大特性](https://github.com/luofengmacheng/algorithms/blob/master/tcpl/object_oriented_features.md) 6 | 7 | 2 [vector中的reserve()和resize()](https://github.com/luofengmacheng/algorithms/blob/master/tcpl/reserve_resize.md) 8 | 9 | 3 [如何限制类对象只能在堆上或者栈上分配](https://github.com/luofengmacheng/algorithms/blob/master/tcpl/heap_stack_object.md) 10 | -------------------------------------------------------------------------------- /tcpl/heap_stack_object.md: -------------------------------------------------------------------------------- 1 | ## 如何限制类对象只能在堆上或者栈上分配 2 | 3 | ### 1 限制类对象只能在堆上分配 4 | 5 | 采用跟单例模式类似的方法: 6 | 7 | ``` C++ 8 | class test { 9 | test() { } 10 | ~test() { } 11 | 12 | public: 13 | static test* create() 14 | { 15 | return new test(); 16 | } 17 | 18 | void destroy() 19 | { 20 | delete this; 21 | } 22 | }; 23 | ``` 24 | 25 | ### 2 限制类对象只能在栈上分配 26 | 27 | 使用new操作符在堆上分配对象,首先会调用operator new()分配存储空间,然后在存储空间上构造对象。operator new()分为全局的和类的,如果类重载了operator new(),编译器不会去查找全局的operator new(),因此,如果类重载operator new(),并将它设为私有的,调用operator new()就会失败,于是,new操作会失败。 28 | 29 | ``` C++ 30 | class test { 31 | public: 32 | test() { } 33 | ~test() { } 34 | 35 | private: 36 | void* operator new(size_t s) { } 37 | void operator delete(void *ptr) { } 38 | }; 39 | ``` 40 | -------------------------------------------------------------------------------- /tcpl/object_oriented_features.md: -------------------------------------------------------------------------------- 1 | ## 面向对象的三大特性 2 | 3 | 面向对象的三大特性:**封装、继承、多态**。 4 | 5 | ### 1 封装 6 | 7 | 封装,也就是将客观事物封装为抽象的类,对不同的事物表现出不同的访问权限,并对外隐藏实现细节。 8 | 9 | ### 2 继承 10 | 11 | 继承,是对现实事物的关系的一个抽象。当两个事物之间有某种关联时,就可以考虑继承。比如,人和工人,工人也是人,因此,工人可以继承人,这样,就能够重用人的所有代码,并且还表现了两个事物之间的关系。 12 | 13 | ### 3 多态 14 | 15 | 多态,就是用基类指针或者引用来操纵派生类对象,使得针对不同的派生类表现不同的行为。在C++中,多态是通过虚函数实现的,当基类将某个方法声明为virtual,那么这个方法就是虚函数,派生类可以重定义这个函数。将派生类对象赋给基类指针或者引用后,用基类指针或者引用调用虚函数时,会调用基类指针或者引用实际使用的对象的方法,如果派生类重新定义了该方法,就调用派生类的,如果派生类没有重定义,就调用基类的。 16 | --------------------------------------------------------------------------------