diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..261e4ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ + +#### + +*.out +*.dSYM + +*.dat +*.txt +*ipslice* + + + + +##### + + diff --git a/README.md b/README.md index c7483fe..8cd335f 100644 --- a/README.md +++ b/README.md @@ -83,14 +83,7 @@ KMP 快递选择SELECT -** @ July 博客 ** -《数学建模十大经典算法》 -《数据挖掘领域十大经典算法》 -《十道海量数据处理面试题》 -《数字图像处理领域的二十四个经典算法》 -《精选微软等公司经典的算法面试100题》 - - + ## 算法设计思想 @@ -110,26 +103,62 @@ http://www.chinaunix.net/old_jh/23/437639.html -## 后续阅读 +## 推荐阅读 + + +《数据结构与算法分析》 +《编程之美》 +《算法设计与分析基础》 + +《算法导论》 有哪些算法 +《算法引论》 如何创造算法 断货 -《算法导论》 -《编程珠玑》 -《编程之美》 《剑指offer》 + +*侧重经典算法的实现* +《Elements of Programming》 STL代码 快 准 狠 +《C interfaces and Implementation》 + + +《微软的梦工厂》 +《Language Implementatin patterns》 +《Algorithms on Strings,Trees and Sequences》 + + +《writing efficient programs》 优化 + +《Algorithm Design Manual》 红皮书 + +《编程珠玑》Programming Pearls 偏算法理论 +《More Programming Pearls》 偏算法轶事 + +《The science of programming》 证明代码段的正确性 800块一本 + + +*高级数据结构*(如元胞自动机、斐波纳契堆、线段树) + +《Algorithms》 4版 +《Advanced Data Structures》 各种诡异数据结构和算法 600块 + + 《深入理解计算机系统》 《TCP/IP详解三卷》 《UNIX网络编程二卷》 《UNIX环境高级编程:第2版》 + + - - ## 参考链接和学习网站 -POJ http://openjudge.cn/ -这有个POJ上的ACM训练方案 http://www.java3z.com/cwbwebhome/article/article19/res041.html +** @ July 博客 ** +《数学建模十大经典算法》 +《数据挖掘领域十大经典算法》 +《十道海量数据处理面试题》 +《数字图像处理领域的二十四个经典算法》 +《精选微软等公司经典的算法面试100题》 微软面试100题 http://blog.csdn.net/column/details/ms100.html 程序员编程艺术 http://blog.csdn.net/v_JULY_v/article/details/6460494 @@ -169,6 +198,6 @@ http://www.cs.usfca.edu/~galles/visualization/Algorithms.html http://leetcode.com/ http://oj.leetcode.com/ - +http://openjudge.cn/ POJ。这有个POJ上的ACM训练方案 http://www.java3z.com/cwbwebhome/article/article19/res041.html diff --git a/a.out b/a.out deleted file mode 100755 index 0cf0c21..0000000 Binary files a/a.out and /dev/null differ diff --git a/a.out.dSYM/Contents/Info.plist b/a.out.dSYM/Contents/Info.plist deleted file mode 100644 index 3679a65..0000000 --- a/a.out.dSYM/Contents/Info.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleIdentifier - com.apple.xcode.dsym.a.out - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - dSYM - CFBundleSignature - ???? - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/a.out.dSYM/Contents/Resources/DWARF/a.out b/a.out.dSYM/Contents/Resources/DWARF/a.out deleted file mode 100644 index fb793ef..0000000 Binary files a/a.out.dSYM/Contents/Resources/DWARF/a.out and /dev/null differ diff --git a/图/README.md b/图/README.md index e69de29..faca6a3 100644 --- a/图/README.md +++ b/图/README.md @@ -0,0 +1,27 @@ + + +##图 + + +## 图的存储结构 + +对象和指针 +矩阵 +邻接表 + + +## 图的操作 + +###遍历 + +广度优先 +深度优先 + +Dijkstra +A* + +用于游戏编程和分布式计算 + + + + diff --git a/多线程.md b/多线程.md index db1f739..9713813 100644 --- a/多线程.md +++ b/多线程.md @@ -148,6 +148,13 @@ A线程一直在while循环上等待,但是B线程有无法获得lockobj锁而 +实现一个队列。队列的应用场景为: +一个生产者线程将int类型的数入列,一个消费者线程将int类型的数出列 + + + + + ### 读者写者问题 这也是一个非常经典的多线程题目,题目大意如下:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写。 diff --git a/排序算法/README.md b/排序算法/README.md index 2139266..9ae5ffb 100644 --- a/排序算法/README.md +++ b/排序算法/README.md @@ -126,6 +126,7 @@ 堆排序主要时间花在建堆期间和`堆化数组`,找数列中最大树只需要O(1)时间复杂度 +推排序还可以用来求 top-K 大(小)的问题。 diff --git a/排序算法/a.out b/排序算法/a.out deleted file mode 100755 index 595f974..0000000 Binary files a/排序算法/a.out and /dev/null differ diff --git a/排序算法/a.out.dSYM/Contents/Info.plist b/排序算法/a.out.dSYM/Contents/Info.plist deleted file mode 100644 index 3679a65..0000000 --- a/排序算法/a.out.dSYM/Contents/Info.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleIdentifier - com.apple.xcode.dsym.a.out - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - dSYM - CFBundleSignature - ???? - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/排序算法/a.out.dSYM/Contents/Resources/DWARF/a.out b/排序算法/a.out.dSYM/Contents/Resources/DWARF/a.out deleted file mode 100644 index 6ff39ef..0000000 Binary files a/排序算法/a.out.dSYM/Contents/Resources/DWARF/a.out and /dev/null differ diff --git a/算法分析思路/分治算法.md b/算法分析思路/分治算法.md deleted file mode 100644 index e69de29..0000000 diff --git a/算法分析思路/动态规划.md b/算法分析思路/动态规划.md deleted file mode 100644 index e69de29..0000000 diff --git a/算法分析思路/回溯法.md b/算法分析思路/回溯法.md deleted file mode 100644 index e69de29..0000000 diff --git a/算法分析思路/枚举迭代.md b/算法分析思路/枚举迭代.md deleted file mode 100644 index e69de29..0000000 diff --git a/算法分析思路/贪心算法.md b/算法分析思路/贪心算法.md deleted file mode 100644 index e69de29..0000000 diff --git a/算法分析思路/递归.md b/算法分析思路/递归.md deleted file mode 100644 index e69de29..0000000 diff --git a/算法问题选编/二叉树.md b/算法问题选编/二叉树.md index a055e4d..fe8e1d4 100644 --- a/算法问题选编/二叉树.md +++ b/算法问题选编/二叉树.md @@ -1,3 +1,7 @@ + + + + 1.把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 diff --git a/算法问题选编/堆和栈.md b/算法问题选编/堆和栈.md index d8c8bb7..d602347 100644 --- a/算法问题选编/堆和栈.md +++ b/算法问题选编/堆和栈.md @@ -1,17 +1,44 @@ -18、如果用一个循环数组q[0..m-1]表示队列时,该队列只有一个队列头指针front,不设队列尾指针rear,求这个队列中从队列头到队列尾的元素个数(包含队列头、队列尾)(华赛面试题、腾讯笔试题)。 +如果用一个循环数组q[0..m-1]表示队列时,该队列只有一个队列头指针front,不设队列尾指针rear,求这个队列中从队列头到队列尾的元素个数(包含队列头、队列尾)(华赛面试题、腾讯笔试题)。 + +有rear指针时: + +if rear>front count = rear-front+1 +else count = rear-front+m+1 +综合,count = (rear-front+m+1)%m + +不用rear指针的话: + +数据结构中加一个 int count来计数。 -2.设计包含min函数的栈。 + + +设计包含min函数的栈。 定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。 要求函数min、push以及pop的时间复杂度都是O(1)。 +主要是min函数实现。咋一看,用一个变量来存储最小值,或最小值的下标不就ok了?这在只push的时候有用,想想如果这个最小值pop出去了呢?我们怎么更新现在的最小值? + +这里用一个辅助栈,空间复杂度是O(n). + +push一个元素a时,该元素a与辅助栈顶f[top]元素比较: +a > f[top],在辅助栈再次中push一遍f[top] (可以把这个省去,节省空间,代价是pop的时候要跟最小栈元素比较,如果pop元素跟最小栈栈顶相等,可能最小值要变了) +a < f(top),把 a push 到 辅助栈中 + +这样辅助栈中的元素是 从上到小 递增的数列。 +且 辅助栈中的栈顶元素 总是 栈中元素集合的最小值。 + +以上方法需要的空间复杂度是O(n) -29.栈的push、pop序列 + + + +栈的push、pop序列 题目:输入两个整数序列。其中一个序列表示栈的push顺序, 判断另一个序列有没有可能是对应的pop顺序。 为了简单起见,我们假设push序列的任意两个整数都是不相等的。 @@ -23,18 +50,32 @@ push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop, 但序列4、3、5、1、2就不可能是push序列1、2、3、4、5的pop序列。 +这里只是要判断是不是pop序列,并没有要求所有的pop序列 -实现一个队列。 -队列的应用场景为: -一个生产者线程将int类型的数入列,一个消费者线程将int类型的数出列 +需要一个辅助栈(需要一个写好的栈结构辅助,如果是C语言,还要包装一个栈结构) + +对序列A中的A[0]入栈,比较B[0] +如果不相等,A[1]入栈 +直到A[i] = B[0] +栈顶出栈,开始匹配B[1] +如果A[i-1]!=B[1],那就继续入栈A[i+1] + +循环往复~ +如果最后,栈为空,就是一个pop序列;如果栈不为空,或者B数组都没有遍历到尾部,就肯定不是pop序列了 -66.颠倒栈。 + +颠倒栈 题目:用递归颠倒一个栈。例如输入栈{1, 2, 3, 4, 5},1在栈顶。 颠倒之后的栈为{5, 4, 3, 2, 1},5处在栈顶。 +递归方法 + + + + diff --git a/算法问题选编/数值问题.md b/算法问题选编/数值问题.md index 04f620d..e398ea2 100644 --- a/算法问题选编/数值问题.md +++ b/算法问题选编/数值问题.md @@ -19,7 +19,14 @@ int string_to_integer(char *s,int length) 分析: 1. 不能使用循环,那就用递归 -2. 递归需要终止递归的条件判断语句,这里也不能用if,想其他办法,可以使用 || 逻辑或运输符 +2. 递归需要终止递归的条件判断语句,这里也不能用if,想其他办法,可以使用 &&逻辑与 运算符(在n>0条件满足是,才会指向后面的递归语句 + + +int factorial(n){ + int sum=0; + (n>0) && sum=n+factorial(n-1) + return sum; +} @@ -30,8 +37,7 @@ int string_to_integer(char *s,int length) 分析: 这是一道很基本的考查位运算的面试题。 -包括微软在内的很多公司都曾采用过这道题。 -解法1:循环计数 +解法1:一轮循环移位计数 (移位运算比除法运算效率要高,注意要考虑是负数的情况) 解法2:位运算 解法3:num &= num-1 巧妙之处在于,对高位没有影响 @@ -39,6 +45,8 @@ int string_to_integer(char *s,int length) + + 请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句 分析: @@ -73,16 +81,6 @@ tmp[i]= tmp[i]>=0?tmp[i]:tmp[i]+16; - -大整数乘法(或 大整数阶乘) -请使用代码计算1234567891011121314151617181920*2019181716151413121110987654321 。 - -1. 注意结果可能超出长整形的最大范围 2^64-1 -2. 采用分治算法,将大整数相乘转换为小整数计算 - - - - 编程实现两个正整数的除法(和取模) 编程实现两个正整数的除法,当然不能用除法操作符。 // return x/y. @@ -110,26 +108,23 @@ int div(const int x, const int y) + + 求两个或N个数的最大公约数和最小公倍数。 +大整数乘法(或 大整数阶乘) +请使用代码计算1234567891011121314151617181920*2019181716151413121110987654321 。 + +1. 注意结果可能超出长整形的最大范围 2^64-1 +2. 采用分治算法,将大整数相乘转换为小整数计算 + +规律分析: +任意位数的整数相乘,最终都可以转化为2位数相乘 -40、用1、2、2、3、4、5这六个数字,写一个main函数,打印出所有不同的排列, -如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连. - - - - - - - -给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), -指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。 - -比如,A=[1,0] K=21 那么输出结构应该为100。 @@ -153,7 +148,7 @@ int div(const int x, const int y) -30.在从1到n的正数中1出现的次数 +在从1到n的正数中1出现的次数 题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。 例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。 @@ -167,8 +162,48 @@ int one_appear_count(int n); -19、判断一个自然数是否是某个数的平方 -说明:当然不能使用开方运算。 + + +判断一个自然数是否是某个数的平方。说明:当然不能使用开方运算。 + +square(25) YES +square(35) NO + +方法1: 从1开始遍历,显然这种方法很差 +方法2: 除数跟余数比较,除数从2开始,每一轮都跟结果比较;相等就是存在这个数,不相等就把除数++;时间复杂度为(根号n)。在一个数比较大时,效率不够好。如1194877489=(34567)^2,需要从2开始,一直比较到34566,做3万多次除法和比较运算。跟方法1一样。。 + +方法3:二分查找 O(logn) + + + + + + +排列组合问题 + +1,2,3,4,5 五个不同的数字,打印不同的排列 + +这就是一个无向图的遍历,把每个数字看成一个节点。 + + +用1、2、2、3、4、5这六个数字,写一个main函数,打印出所有不同的排列, +如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连. + +这是对上一题增加难度。但是需要 +1. 去掉 3,5之间的联通 +2. 2重复,过滤重复结果 treeset +3. 4不能在3位 + + + + + + +给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), +指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。 + +比如,A=[1,0] K=21 那么输出结构应该为100。 + diff --git a/算法问题选编/数值问题/1.c b/算法问题选编/数值问题/1.c deleted file mode 100644 index 67829ea..0000000 --- a/算法问题选编/数值问题/1.c +++ /dev/null @@ -1,37 +0,0 @@ - -#include "stdio.h" -#include "string.h" - -int string_to_integer(char *s,int length){ - - if (length>1) - { - return s[0]=='-'?string_to_integer(s,length-1)*10-(s[length-1]-'0'):string_to_integer(s,length-1)*10+s[length-1]-'0'; - }else{ - return s[0]=='-'?-1/10:s[0]-'0'; - - } -} - -/* 问题: -1. s是空字符串 -2. s传参为非数字字符 -3. 超出整数所能表示范围 -*/ - - -int main(){ - - char *s = "4323"; - - printf("integer == %d\n",string_to_integer(s,strlen(s)) ); - printf("integer == %d\n",string_to_integer("12342",5)); - printf("integer == %d\n",string_to_integer("-11",3) ); - printf("integer == %d\n",string_to_integer("-5",2) ); - printf("integer == %d\n", string_to_integer("3",1)); - - printf("integer == %d\n", string_to_integer("abcd",4)); - printf("integer == %d\n", string_to_integer("a",1)); - - return 0; -} diff --git a/算法问题选编/数值问题/2.c b/算法问题选编/数值问题/2.c deleted file mode 100644 index b8f86c9..0000000 --- a/算法问题选编/数值问题/2.c +++ /dev/null @@ -1,23 +0,0 @@ - -#include "stdio.h" - - -int factorial(int n){ - - int ret=0; - (n==0) || (ret=n+factorial(n-1)); - return ret; -} - - -int main(){ - - int n=10; - printf("factorial(10)= %d\n",factorial(10)); - printf("factorial(5)= %d\n",factorial(5)); - printf("factorial(1)= %d\n",factorial(1)); - printf("factorial(0)= %d\n",factorial(0)); - - return 0; -} - diff --git a/算法问题选编/数值问题/3.c b/算法问题选编/数值问题/3.c deleted file mode 100644 index 669624e..0000000 --- a/算法问题选编/数值问题/3.c +++ /dev/null @@ -1,71 +0,0 @@ - -#include "stdio.h" -#include "stdlib.h" - -char *integer_to_bin(long integer){ - - int bit_num = sizeof(long)*8; - char *buffer= (char *)malloc(bit_num+1); - if (buffer==NULL) - { - return "malloc error"; - } - buffer[bit_num]='\0'; - - for (int i = 0; i < bit_num; ++i) - { - buffer[i]= integer<>(bit_num-1); - buffer[i]= buffer[i]==0?'0':'1'; - - } - return buffer; - -} - -char *integer_to_hex(long integer){ - - int bit_num=sizeof(long)*8/4; - char *buffer=(char *)malloc(bit_num+3); - buffer[0]='0'; - buffer[1]='x'; - buffer[bit_num+2]='\0'; - char *tmp=&buffer[2]; - - for (int i = 0; i < bit_num; i++) - { - tmp[i]= integer<<(i*4)>>(bit_num*4-4); - tmp[i]= tmp[i]>=0?tmp[i]:tmp[i]+16; - tmp[i]= tmp[i]<10?(tmp[i]+48):(tmp[i]-10+'A'); - } - - return buffer; -} - - -/* - -A 65 -0 48 - -*/ - - - -int main(){ - - - printf("b(11) = %s\n", integer_to_bin(11)); - printf("b(1023) = %s\n",integer_to_bin(1023) ); - printf("b(23564) = %s\n",integer_to_bin(23564) ); - - - printf("h(11) = %s\n", integer_to_hex(11)); - printf("h(1023) = %s\n",integer_to_hex(1023) ); - printf("h(23564) = %s\n",integer_to_hex(23564) ); - printf("b(11) = %x\n", 11); - printf("b(1023) = %x\n",1023 ); - printf("b(23564) = %x\n",23564 ); - - - return 0; -} \ No newline at end of file diff --git a/算法问题选编/数值问题/4-1.c b/算法问题选编/数值问题/4-1.c deleted file mode 100644 index 806e7d3..0000000 --- a/算法问题选编/数值问题/4-1.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "stdio.h" - -int main(){ - - printf("%ld",236432123443*33453098); - return 0; -} \ No newline at end of file diff --git a/算法问题选编/数值问题/5.c b/算法问题选编/数值问题/5.c deleted file mode 100644 index 4df163b..0000000 --- a/算法问题选编/数值问题/5.c +++ /dev/null @@ -1,25 +0,0 @@ - - -#include "stdio.h" - - -/* - - 1 是第一个元素 - 序列中元素被2或3或5整除 - -*/ -unsigned long value_in_sequence(unsigned index){ - - - - -} - - -int main(){ - - - - return 0; -} \ No newline at end of file diff --git a/算法问题选编/数值问题/6.c b/算法问题选编/数值问题/6.c deleted file mode 100644 index 926f346..0000000 --- a/算法问题选编/数值问题/6.c +++ /dev/null @@ -1,70 +0,0 @@ - - -#include "stdio.h" - -int binary_search_first(int *a,int length,int key){ - - int low=0; - int high = length-1; - int mid = 0; - - while(low=key)//往左找 - { - high = mid; - }else{ - - low = mid+1; - } - - } - return high; - -} - -int binary_search_last(int *a,int length,int key){ - - int low = 0; - int high = length -1; - int mid = 0; - - while(low - - - - CFBundleDevelopmentRegion - English - CFBundleIdentifier - com.apple.xcode.dsym.a.out - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - dSYM - CFBundleSignature - ???? - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/算法问题选编/数值问题/a.out.dSYM/Contents/Resources/DWARF/a.out b/算法问题选编/数值问题/a.out.dSYM/Contents/Resources/DWARF/a.out deleted file mode 100644 index b61ec8e..0000000 Binary files a/算法问题选编/数值问题/a.out.dSYM/Contents/Resources/DWARF/a.out and /dev/null differ diff --git a/算法问题选编/数组数列问题.md b/算法问题选编/数组数列问题.md index 800f642..83bfaf4 100644 --- a/算法问题选编/数组数列问题.md +++ b/算法问题选编/数组数列问题.md @@ -28,6 +28,9 @@ print_sum_detials(int n , int sum) +二维数组中的查找 + + @@ -84,8 +87,6 @@ print_minimums(int *a,int length ,int k); 2在下排出现了1次,3在下排出现了0次.... 以此类推.. -昨天,花了一个下午,用c++实现了此题。(*^__^*) - diff --git a/算法问题选编/测试代码/8.c b/算法问题选编/测试代码/8.c new file mode 100644 index 0000000..eaeb942 --- /dev/null +++ b/算法问题选编/测试代码/8.c @@ -0,0 +1,11 @@ + + +#include "stdio.h" + +int main(){ + + int a = 257; + unsigned char *result = (unsigned char *)&a; + printf("%d.%d.%d.%d\n", result[0],result[1],result[2],result[3] ); + +} \ No newline at end of file diff --git a/算法问题选编/测试代码/9.c b/算法问题选编/测试代码/9.c new file mode 100644 index 0000000..a58959b --- /dev/null +++ b/算法问题选编/测试代码/9.c @@ -0,0 +1,53 @@ + +#include "stdio.h" + +int isSquare(unsigned integer){ + + if (integer==1 || integer==0) + { + return integer; + } + + int divider=2,result=integer/divider; + + while(result>divider){ + + divider++; + result = integer/divider; + + } + + if (result!=divider) + { + return -1; + } + + return result; +} + + +int main(int argc, char const *argv[]) +{ + // 243,1849(43),289(17), 64(8) + + int a[] = {1849,144,243,289,64,1194877489}; + for (int i = 0; i < sizeof(a)/sizeof(int); ++i) + { + int ret = isSquare(a[i]); + + if (ret==-1) + { + printf("%d 不是某个数的平方\n",a[i]); + }else{ + + printf("%d 是 %d 的平方\n", a[i], ret); + } + + } + + return 0; +} + + + + diff --git a/算法问题选编/测试代码/a.out b/算法问题选编/测试代码/a.out deleted file mode 100755 index d48b898..0000000 Binary files a/算法问题选编/测试代码/a.out and /dev/null differ diff --git a/算法问题选编/测试代码/a.out.dSYM/Contents/Info.plist b/算法问题选编/测试代码/a.out.dSYM/Contents/Info.plist deleted file mode 100644 index 3679a65..0000000 --- a/算法问题选编/测试代码/a.out.dSYM/Contents/Info.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleIdentifier - com.apple.xcode.dsym.a.out - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - dSYM - CFBundleSignature - ???? - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/算法问题选编/测试代码/a.out.dSYM/Contents/Resources/DWARF/a.out b/算法问题选编/测试代码/a.out.dSYM/Contents/Resources/DWARF/a.out deleted file mode 100644 index ce6429e..0000000 Binary files a/算法问题选编/测试代码/a.out.dSYM/Contents/Resources/DWARF/a.out and /dev/null differ diff --git a/算法问题选编/测试代码/most_visit_ip.c b/算法问题选编/测试代码/most_visit_ip.c new file mode 100644 index 0000000..5c64dca --- /dev/null +++ b/算法问题选编/测试代码/most_visit_ip.c @@ -0,0 +1,135 @@ + +#include "stdio.h" // fwrite +#include "unistd.h" // write +#include "stdlib.h" // itoa +#include "string.h" + +#define test_file_path2 "./ip2.txt" +#define test_file_path "./ip.txt" +#define ip_count 100000000 //随机1亿个IP +#define tmp_file_count 32 + +#define mem_count 128*1024*1028 //128MB个IP空间 + + +int hash(unsigned i){ + + return i>>27; + +} + + +int main(){ + + + // 模拟创建一个文件,产生测试用的IP + // FILE *fd; + // fd = fopen(tmp_file_path,"a+"); + // for (int i = 0; i < ip_count;++i) + // { + // //char c[] = "this is sentence!"; + // unsigned random_ip = (unsigned)rand(); + // char tmp[50]; + // sprintf(tmp,"%d",random_ip); + // //printf("random ip = %s\n",tmp); + // fwrite(tmp,strlen(tmp),1,fd); + // fputc('\n',fd);//加入换行符号 + // } + + + //创建临时文件 + FILE *fd[tmp_file_count]; + for (int i = 0; i < tmp_file_count; ++i) + { + char file_path[128]; + //s[0]=(char)(i+48); + //char *file_path = strcat("./ipslice/ipslice",s) ; // 这样写出现 bus error!!! + sprintf(file_path,"./ipslice/ipslice%d",i); + fd[i] = fopen(file_path ,"a+" ); + if ( !fd[i]) + { + printf("file %d open fail!! \n" ,i); + } + } + + + + + //开始读测试数据IP,按IP,映射到32个文件中 + FILE *testfd = fopen(test_file_path2,"r"); + if (!testfd) + { + printf("file open fail !!\n"); + exit(-1); + } + unsigned tmp_data; + while( getline() ){ //能读到数据 // fread(&tmp_data,sizeof(unsigned),1,testfd) , C语言中没有getline() 这样的函数 + + printf("%d\n",(unsigned)tmp_data ); + int key = hash((unsigned)tmp_data);// key值即为对应文件fd + + int size = fwrite(&tmp_data,sizeof(unsigned),1,fd[key]); + printf("写入数据size=%d ,key=%d\n",size, key ); + + //跳过换行符 + fseek(testfd,1,SEEK_CUR); + } + + + + + // 依次读入每个文件并统计, hash_map 统计每个区间段的最大IP + int hash_map[mem_count]; + int max_ip; + int max_times; + + for (int i = 0; i < tmp_file_count; ++i) + { + + // hash统计 + while(){} + + //hash 表里找出最大的,变量一遍 + for (int i = 0; i < mem_count; ++i) + { + /* code */ + } + + } + + + + // 释放 + for (int i = 0; i < tmp_file_count; ++i) + { + fclose(fd[i]); + } + + + return 0; +} + + + +/** +关于warning +implicit declaration of function 'itoa' is invalid in C99 + +itoa() 函数并不是一个 standard functions ANSI C standard + + +inet_ntop() // 整数转换成 .分 ip地址 字符串 +inet_nton() // + +inet_aton() // + +struct in_addr + +*/ + + + + + + + diff --git a/算法问题选编/海量数据处理.md b/算法问题选编/海量数据处理.md index 99c6ace..2632992 100644 --- a/算法问题选编/海量数据处理.md +++ b/算法问题选编/海量数据处理.md @@ -2,23 +2,119 @@ /////////////////// 海量数据处理(千万以上量级) /////////// +时间上:无法在较短时间内迅速解决。可以设计巧妙的算法搭配合适的数据结构解决 +空间上:数据量太大,无法一次全部装入内存;针对方法是大而化小,分而治之。将规模大划分为规模小的问题,各个击破 -2.有一千万条短信,有重复,以文本文件的形式保存,一行一条,有重复。 + +1. 分而治之/Hash映射 + hash统计 + 堆排序/快速排序/归并排序 +2. 双层桶划分 +3. Bloom filter 、Bitmap +4. Trie树/数据库/倒排索引 +5. 外排序 +6. 分布处理之 Hadoop/Mapreduce + + +### 海量日志处理,提取某日访问百度次数最多的那个IP(或top-K IP) + +分析 + +2^32 = 42亿九千万。。 +假设一个IP一天内访问百度的次数不查过40亿次,可以用unsigned表示。用数组统计处每个IP地址出现的最大次数,就可以得到访问次数最大的IP地址 + +unsigned count[N],这个N=2^32=4G个IP地址 sizeof(count) = 4*N = 16G内存,原因超过32位机器所支持的4G内存大小。因此不能直接创建这个数组 + + +第一步 分治法/文件映射 + +假设运行使用的内存是512MB, 512M/4 = 128M个IP地址(一个IP地址32位,占4个字节) +注意理解:`512M内存可以统计128M个不同的IP地址的访问次数`,哪怕切割的小文件中的IP总数大于128M + +4G/128M = 32,也就是把IP地址划分成 32 个不同的区间段,addr[1-xx],addr[xx-xx]..分别计算每个区间中访问次数最大的IP,然后再比较32个区间段中的最大次数,就可以得到所有IP的做大值了。 + +一个区间段的IP地址个数任然可能撑破128M个,从而撑爆内存 + +具体实施: +把大文件映射到小文件,有2种方式: + +1. 取模映射 。 IP%32 映射到32个小文件,把model相同的IP保存到同一个文件 +2. 位运算映射。把IP的前5为作为作为区间编号,即 IP>>27 结果就是[0,31],把相同区间的IP保存到同一个文件 + +上面的映射中,都不会出现同一个IP映射到不同小文件的情况 + + +第二步 统计每个小文件中的最大值 + +现在文件不同的IP数量达到内存承受的范文了,可以统计小文件中的IP次数了,使用常规的 hash_map(IP,count) 来 统计了 + + +第三步 排序 堆排序/快速排序/归并排序 + + + + + + + + + +###top-K 找出最大的k个数 + +hashmap + 堆 + +100w个数中找出最大的100个数。 + +类似问题: + + + +分析:100W个数里面是否有重复 + + +方案1:在前面的题中,我们已经提到了,用一个含100个元素的最小堆完成。复杂度为O(100w*lg100)。 + +方案2:采用快速排序的思想,每次分割之后只考虑比轴大的一部分,知道比轴大的一部分在比100多的时候,采用传统排序算法排序,取前100个。复杂度为O(100w*100)。 + +方 案3:采用局部淘汰法。选取前100个元素,并排序,记为序列L。然后一次扫描剩余的元素x,与排好序的100个元素中最小的元素比,如果比这个最小的要 大,那么把这个最小的元素删除,并把x利用插入排序的思想,插入到序列L中。依次循环,知道扫描了所有的元素。复杂度为O(100w*100)。 + + + + + +有一千万条短信,有重复,以文本文件的形式保存,一行一条,有重复。 请用5分钟时间,找出重复出现最多的前10条。 +寻找热门查询,300万个查询字符串中统计最热门的10个查询 + + + + + 文件中的内容排序并去重复 一个文件中包含了1亿个随机整数,如何快速的找到最大(小)的100万个数字?(时间复杂度:O(n lg k)) 分析: 堆排序 + 3.2 在O(n lg k)时间内,将k个排序表合并成一个排序表,n为所有有序表中元素个数。 【解析】取前100 万个整数,构造成了一棵数组方式存储的具有小顶堆,然后接着依次取下一个整数,如果它大于最小元素亦即堆顶元素,则将其赋予堆顶元素,然后用Heapify调整整个堆,如此下去,则最后留在堆中的100万个整数即为所求 100万个数字。该方法可大大节约内存。 + +搜索中的智能提示(如 "中国" ,"zhongguo",考虑拼音) + +把2万个汉字排序,弄成一个超长的字符串 +用Int16索引汉字的所有拼音 +Int64 建立汉字和拼音的关联--汉字有多音字,需要把多个拼音pack到一个Int64,位操作搞定 +二分+位移unpack,直接做到汉字到拼音的检索 + + + + + 3.大量的URL字符串,如何从中去除重复的,优化时间空间复杂度 @@ -29,6 +125,7 @@ 一个文件中有40亿个整数,每个整数为四个字节,内存为1GB,写出一个算法:求出这个文件里的整数里不包含的一个整数 + 假设一个文件中有9亿条不重复的9位整数,现在要求对这个文件进行排序。 @@ -184,13 +281,6 @@ s 求出每台电脑上的TOP10后,然后把这100台电脑上的TOP10组合 方案1:首先根据用hash并求模,将文件分解为多个小文件,对于单个文件利用上题的方法求出每个文件件中10个最常出现的词。然后再进行归并处理,找出最终的10个最常出现的词。 -12. 100w个数中找出最大的100个数。 - -方案1:在前面的题中,我们已经提到了,用一个含100个元素的最小堆完成。复杂度为O(100w*lg100)。 - -方案2:采用快速排序的思想,每次分割之后只考虑比轴大的一部分,知道比轴大的一部分在比100多的时候,采用传统排序算法排序,取前100个。复杂度为O(100w*100)。 - -方 案3:采用局部淘汰法。选取前100个元素,并排序,记为序列L。然后一次扫描剩余的元素x,与排好序的100个元素中最小的元素比,如果比这个最小的要 大,那么把这个最小的元素删除,并把x利用插入排序的思想,插入到序列L中。依次循环,知道扫描了所有的元素。复杂度为O(100w*100)。 13. 寻找热门查询: