存档:数据结构算法

中庸之道的newsfeed的设计

四月 25, 2010 | 数据结构算法, 网站架构 | RSS 2.0

follows大道至简,道道相同,其实世界本没有那么复杂,不过人们把它描写的多样化了,他就那么复杂了,抽象到一定程度发现互不相关的东西都有他的共性,无论在任何领域都少不了change,有change都有质变,质变点就有极值点,min,max,在数学中尤为常见。但有时需要结合最大和最小结合运用才能创造出合理,譬如在web2.0时代颇为流行的newsfeed。twitter,facebook,其实googlereader等都一样,一个生产者,一个消费者。设计往往经常是大家谈论的两种,一种是存储一份,消费者就登陆时候就pull过来,例如你登陆豆瓣,就会看到你好多好友的信息,都是pull过来的,如果你比较强大可以把生产者的内容给每一个消费者发一份。但是也会面临瞬间分发的压力,虽然在发的时候有一定的延时性。但用户读取的时候就很容易,读跟自己相关的就可以了。目前好多有这种应用的都是这种操作。以下是facebooke的。

facebook newsfeed

facebook newsfeed

在看看一篇有关校内的http://www.54chen.com/uncategorized/net-new-to-live-for-all-to-share.html

用的是一些key value的数据库。也是push的思想,即给所有的相关的好友dispatch一份。 但是想twitter这样的有些突发事件或者名人

follows过多的话会有多大的压力无论是写还是读。  后来躲到一篇follows的论文,好像一个普林斯顿大学大学的人写的,专门解决这种臭名昭著的棘手问题,没看的太明白,但是大概思想是把生产者和消费者分类,因为有些生成者是高产者,而有些消费者是高消费者,无论单一的产用pull的方式

或者是push的方式都不是太合适,他们会根据用户的生产效率和登录比率来判断到底给用pull的方式或者是push的方式,当然作者也说类似follows的应用时臭名昭著的应用

难于设计扩展等,作者也做了性能优化方面的分析,用了yahoo的开源的pnuts的key value的一个系统。把用户的好友关系抽象成一张图,然后利用一定的算法来优化这种follows的应用。而且作者通过调用twitter的api进行了一些测试,测试效果还不错。

仔细想想也是,以前总以为设计这种系统要么是是push给用户,要么是pull给用户,但是其实两者是可以结合的,相互弥补。

follows的pnuts应用

follows的pnuts应用

看来世事没有绝对性有时候需要结合两个极端来思考问题,中庸也许是一种更好的解决办法。就像老子的思想那样,物极必反。事不能要一个极端。我会附加上作者的论文,本身我也

不全明白,多读几篇follows pdf

1条评论 »

N = NP ?

十一月 12, 2009 | 数学, 数据结构算法, 读书 | RSS 2.0

终于捡到一个时间来写这篇文章,其实我对p和np也不是很了解,只是觉得学计算机的起码应该知道,np问题应该算是计算机科学中的未解决的问题,关于n=np 也是一个未知的问题,Clay数学院评出的七个悬赏百万美元的难题。简单的讲p就是我们能在多项式时间内解决的问题?例如一些排序算法,初等的一些数学运算,p就是polynomial ,计算机科学里的算法复杂度是O(n),O(n^2)等都属于p问题,而np问题则是不能在多项式时间内解决的为难题,它是有20世纪70年代,数理逻辑领域两位计算机科学家的发现,Stephen A. Cook 和richard karp的论文,许多类型不同的问题抽象的逻辑问题其实是同一个问题伪装成不同的形式,np是一个世界之谜,当我们有限的心灵面对宇宙成指数,也许是比指数更高级的一个运算的运算的复杂度增长时,我们如何应对,为什么我们无法预测未来,变量太多,导致我们的运算成告诉增长的苦难,简单如天气预报来说,计算机发展十年天气预报才能多预报一天,但是预报的也不是百分之百的准啊,大家都会深有体会,世界时一个混沌中,在其中,我们和合自然抗衡还差很远。
在生活工作中,我们是在solving problems,而且一般我们处理的问题一般也是p问题,很简单的能把它解决,复杂性能不算太高,但是如果别人给你出一个问题说给我算一下10的100次方个素数是多少?你会傻眼的,为什么??很简单的问题的复杂度增长的太快,一个简单的例子是我们高中在学等比数列时候的一个小故事,向国外索要粮食,以2为底数,可见都速度惊人?何况以别的呢?现实生活中以指数式增长的例子比比皆是,《数字追凶》记得描述过一个这样的案子,甲流如果不控制,可以想象其传播速度会有多快?在有一个例子是计算机安全领域的一些加密算法,很显然我们如果采取逐个坚持,所谓的暴力破解去解rsa,des算法相信还是很困难的,但是给你密钥,验证就可以在多项式时间内完成。可见np问题是非确定计算模型下易验证的问题,np完全是一类看似不相关的问题,可以最终化解成一类问题,如果解决了这样一类 问题,这整个问题链条都可以迎刃而解,如果a问题能化解为b,b能化解为c,c能化解为d等等,这解决了最底层的则整座大厦将可以击破,著名的np完全问题 旅行售货员问题,哈密顿问题,相信学计算机的都应该学过,这些问题会出现在《离散数学》,《算法分析》课程中,如果城市有限,我们可以把旅行售货员去过的地方做成图,或者画一个树,画出所有可能到达的分支,利用回溯法即可解决问题,但是如果他要去一万个城市呢?复杂度可想而知,但如果知道了,我们可以轻松的验证,许多问题都属于此类,如果我们找到一个通用的方法解决np问题在多项式时间内,即n=np,这我们的则没有安全,估计也到了大同世界,只要有密码的地方我们可以运行下计算机,轻松破解,而不比等千万年。例如我们的rsa加密算法利用的是大整数的分解的复杂度,迷宫也是一个np问题,世界就是一个错综复杂的迷宫。
下图是wiki上的np,p问题的所属列表。
250px-Complexity_classes.svg
说到问题的转化和分解,想起编译原理课程中讲过的一些状态图,图灵机等,事物的转化状态,看似复杂的理论,起最终的解决可以固定到一些模式上,例如经常提到的狼和白菜和羊过河问题,这样的问题,可以通过分析状态,画出状态。把所有的解化解成固定的模式。
在np完全问题上,可喜的是今年第25界计算几何年会我国复旦大学的学者提出 ,”最小曼哈顿网络问题是一个NP完全问题“,获得最佳论文奖,np完全还是很多的存在在现实中。 附件为他们的论文。scg

参考:
1 http://web.mit.edu/newsoffice/2009/explainer-pnp.html
2 计算机算法设计与分析
3 推理的迷宫

没有评论 »

读书思考重构

十月 15, 2009 | 数据结构算法, 读书 | RSS 2.0

近段时间一直没有机会研究技术和写东西,十一前两周被一场病的啥也没弄,后差不多又到了十一,所以近段时间基本没有什么新的东西,不过看了看梁斌写的《走进搜索引擎》 算是有了个大概的了解,也顺便看了看比较经典的推理的迷宫一本科普书,代码大全也读了读,不过近期还得继续研读,好久没有写c代码了,shit。花了三个晚上,和地铁上下班时间思考了下如何把重构讲的好一点,还是想出来一些新东西的,看来以后还是要经常多思考
Refactoring 重构

没有评论 »

算法世界的哲学思考

九月 16, 2009 | 数学, 数据结构算法, 软件工程/编程技巧/设计模式 | RSS 2.0

每每读到一些好的算法都会让人有叹为观止的感觉,巧妙的设计让我们回味起数学,物理等,物理的测万有引力,远古时代没有任何工具的情况下的测量出地球的半径,人就是这么一个奇妙的动物。想体味下巧妙,你可以看下《啊哈,灵机一动》google黑板报的《数学之美》系列,微软的《编程之美》等,大道至简,简单的道理抽象到了一定的高度就适应于任何事物,在我看来数学和哲学都是抽象到一定程度的事物,你可以体味下1+1=2,事物的都是有联系的普遍性。俗话说大道至简。
读计算机以来,自然也学到不少算法,虽然现在搞些web的开发,当初也是软件开发的,总是忘不了学过的那些经典的算法,经常及其老师讲解时候的费力和樯橹灰飞烟灭。自己体味好多计算机里面的算法,定理,思想,更大自然世界很协调。
先举几个简单的小例子:
1 将两只小猫放到足球场的对面,相距100码,他们以每分钟10码的速度相向行走。同时这两只小猫的母亲在足球场的一端,它可以以每分钟100码的速度跑步,猫妈妈从一只小猫跑到另一只小猫,来回轮流跑而速度不减,一直跑到两只小猫在中场相遇,问猫妈妈跑了多远?
2 渔民在池塘放养了大量鱼苗。养到一定程度后,我们要估计现在池塘中有多少鱼?
3 有一根27厘米的细长杆,在第3厘米,7厘米,11厘米,17厘米,23厘米在五个位置各放有一只蚂蚁,木杆很细,不能同时通过两次蚂蚁,开始时,蚂蚁头朝右还是朝左是任意的,他们只会超前或者调头,当不会后退。当任意两只蚂蚁碰头时,两只蚂蚁会同时掉头朝反方向走,假设蚂蚁每秒钟可以走一厘米的距离,所有蚂蚁离开木杆的最短时间和最长时间。
4 棋盘覆盖问题。在一个2k x 2k ( 即:2^k x 2^k )个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

1005341

5 某一天,一个新研究员向托马斯爱迪生报到。爱迪生要求他计算出一个空灯泡壳的体积。在使用测径仪和微积分进行数小时饿计算后,这个新员工给出了答案150立方厘米,而爱迪生在几秒之内计算就给出了更接近155,他是如何实现的呢?

—————————————-给出部分提示————————–

1 不要用蛮力,首先通过两只小猫可以计算出猫妈妈的跑步的时间,两只小猫相距100米,每分钟20码在接近,故5分钟完成,所以猫妈妈是500米

2 这个牵涉到数学中的概率等的知识,概率统计还是挺实用的一门学科,可以考虑用极大似然估算算法,即捞出一定数量的鱼,不能过少,坐上标记,过一定时间取出看看标记的比例

3 和第一个的思想有点像,碰头后蚂蚁会继续潜行,看做是个体运动就好考虑了

4 第四题图片方格少,还好,如果多了,你就不一定能搞定了,还需保证是4的k次幂,其实可以采用分治的思想,即图上可以上下左右四部分,带黑色宽那个就可以填好了,挨着黑色块的即中心的可以填好了,然后就把其他的搞定,如果更多如何?就行切分,分治,分而治理。

5 想想阿基米德王冠的故事你就明白了

现在可以看到了

一题三给我们一个解决问题的思路用时间求解较容易,摊还分析就是用这样一个思路,一如一个附加变量,位势,

二题,五题也是给我们一种思路转换问题的思路。4题给我们一个解决问题分而治之。

可以看到什么样的哲学思想呢?首先事物是联系的,解决了这个事物,和其关系的别的也就可以相应的解决了,整体和局部的思想,局部解决了,整体也就好了。

看看别的算法

1 递归于分治策略,递归?现实生活中哪里有递归的影子?没想到?那就照照镜子吧,看到了,这个就是递归,事物本身的属性,局部整体的哲学思想

2 动态规划,类似分治递归,当他们的若干个问题不是独立的是联系的,第n个问题和n-1个问题是有关系的,

3 贪心算法很明晰矛盾分主要矛盾和次要矛盾,抓住了主要矛盾就抓住了问题的核心

4 概率算法:事物发展的不确定性,螺旋式发展。舍伍德算法,拉斯维加斯算法,我们经典的抛针算π的算法,蒙特卡洛算法,现在基本都忘记了。

5 线性规划,回溯法,分枝限界法 这些都是通过把问题抽象,合理的布局,解决之,算是事物之间的联系吧。别的暂时没行到。

6np完全性理论和近似算法:图灵机等,应该是事物的发展变化的各个状态,著名的图灵机问题,问题的各个态势的变化,这个算法我不熟。

暂时先想到这里,也算是对自己学过的算法课程的一个回忆。

没有评论 »

For , While 那个更快?

九月 5, 2009 | c/c++, 数据结构算法, 软件工程/编程技巧/设计模式 | RSS 2.0

到底是for快还是while快?有人做了一下测试:

for (;;) {
}

while (1) {
}

生成的汇编分别是:

for的是:

.text
.globl _main
_main:
pushl    %ebp
movl    %esp, %ebp
subl    $8, %esp
L2:
jmp    L2
.subsections_via_symbols

while的是:

.text
.globl _main
_main:
pushl    %ebp
movl    %esp, %ebp
subl    $8, %esp
L2:
jmp    L2
.subsections_via_symbols

现在你知道了吧

—————————————————http://blog.marcelotoledo.org/2008/10/22/for-or-while/


				

没有评论 »

mod10校验算法(信用卡 银行)

九月 1, 2009 | 数据结构算法 | RSS 2.0

先看一下mod10算法的描述:

计算的规则:

1 Beginning on the right, with the digit that immediately precedes the check digit and moving toward the left, double every other digit. After doubling each selected digit, if the result is ten or greater, add the two digits together to arrive at a single-digit result.

4012 8888 8888 1881
[8]0[2]2 [16]8[16]8 [16]8[16]8 [2]8[16]1
8022 7878 7878 2871

2  Each individual resulting digit, plus those bypassed, above is then added together.
8022 7878 7878 2871
8+0+2+2+7+8+7+8+7+8+7+8+2+8+7+1
= 90
3 This sum is then subtracted from the lowest multiple of ten that is equal to or greater than the sum, and the single-digit result is the check digit.
90 ÷ 10 = 9
90 Mod 10 = 0

简单的讲就是从号码后面的最后一位乘以1算起,然后上一位的2倍,2倍后大于9这则减去9或者十位和各位相加。最后把这些的和对10进行取模,看是否是0,然后进行决定是否是信用卡号:

网上有找到两段代码,一段是c的,一段时JavaScript的,c的写的比较巧。

1 :

int LuhnMod10(char* cardNumber, int size)
{
static int table[10] = { {0,1,2,3,4,5,6,7,8,9}, {0,2,4,6,8,1,3,5,7,9} };
 
for (int i=size-1, odd=0, sum=0; i>=0; i--)
if (isdigit(cardNumber[i]))
sum += table[(odd=1-odd)][cardNumber[
<div id=":s8">i]-'0'];
sum %= 10;
return (sum ? 10-sum : 0);               /* return the check digit *
}
</div>
js的的则相当繁琐,如果读懂了两段代码,可以看到上面用c写的之妙,之美:
function Mod10(ccNumb) {  // v2.0
var valid = “0123456789″  // Valid digits in a credit card number
var len = ccNumb.length;  // The length of the submitted cc number
var iCCN = parseInt(ccNumb);  // integer of ccNumb
var sCCN = ccNumb.toString();  // string of ccNumb
sCCN = sCCN.replace (/^\s+|\s+$/g,”);  // strip spaces
var iTotal = 0;  // integer total set at zero
var bNum = true;  // by default assume it is a number
var bResult = false;  // by default assume it is NOT a valid cc
var temp;  // temp variable for parsing string
var calc;  // used for calculation of each digit

// Determine if the ccNumb is in fact all numbers
for (var j=0; j<len; j++) {
temp = “” + sCCN.substring(j, j+1);
if (valid.indexOf(temp) == “-1″){bNum = false;}
}

// if it is NOT a number, you can either alert to the fact, or just pass a failure
if(!bNum){
/*alert(”Not a Number”);*/bResult = false;
}

// Determine if it is the proper length
if((len == 0)&&(bResult)){  // nothing, field is blank AND passed above # check
bResult = false;
} else{  // ccNumb is a number and the proper length – let’s see if it is a valid card number
if(len >= 15){  // 15 or 16 for Amex or V/MC
for(var i=len;i>0;i–){  // LOOP throught the digits of the card
calc = parseInt(iCCN) % 10;  // right most digit
calc = parseInt(calc);  // assure it is an integer
iTotal += calc;  // running total of the card number as we loop – Do Nothing to first digit
i–;  // decrement the count – move to the next digit in the card
iCCN = iCCN / 10;

// subtracts right most digit from ccNumb
calc = parseInt(iCCN) % 10 ;    // NEXT right most digit
calc = calc *2;                                 // multiply the digit by two
// Instead of some screwy method of converting 16 to a string and then parsing 1 and 6 and then adding them to make 7,
// I use a simple switch statement to change the value of calc2 to 7 if 16 is the multiple.
switch(calc){
case 10: calc = 1; break;       //5*2=10 & 1+0 = 1
case 12: calc = 3; break;       //6*2=12 & 1+2 = 3
case 14: calc = 5; break;       //7*2=14 & 1+4 = 5
case 16: calc = 7; break;       //8*2=16 & 1+6 = 7
case 18: calc = 9; break;       //9*2=18 & 1+8 = 9
default: calc = calc;           //4*2= 8 &   8 = 8  -same for all lower numbers
}
iCCN = iCCN / 10;  // subtracts right most digit from ccNum
iTotal += calc;  // running total of the card number as we loop
}  // END OF LOOP
if ((iTotal%10)==0){  // check to see if the sum Mod 10 is zero
bResult = true;  // This IS (or could be) a valid credit card number.
} else {
bResult = false;  // This could NOT be a valid credit card number
}
}
}
// change alert to on-page display or other indication as needed.
if(bResult) {
alert(”This IS a valid Credit Card Number!”);
}
if(!bResult){
alert(”This is NOT a valid Credit Card Number!”);
}
return bResult; // Return the results
}
// –>
</script>

摘自:http://www.techrss.cn/html/2008/10-20/152593.htm

没有评论 »

分类算法的思考

四月 23, 2009 | 数据结构算法 | RSS 2.0

1 常见的多极分类和无限级的分类可以考虑用关系数据库实现
如设计的数据结构是
CREATE TABLE `category` (
  `categoryID` smallint(5) unsigned NOT NULL auto_increment,
  `categoryParentID` smallint(5) unsigned NOT NULL default ‘0′,
  `categoryName` varchar(50) NOT NULL default ”,
  PRIMARY KEY  (`categoryID`)
)
通过sql就可以做到多极分类和无限级别分类。
2 通过一个大数字,按照类别进行分段,如1110,1000000,000000,000000,和1110,10101001,0100010,0010001,相与,如果第一段相等则第一类相同,有点像ip的分类地址思想
如a类地址,b类地址,求起网络地址,和子网掩码相与的思想,这个思想也基本上满足常见的分类。
3 这个算法是google的数学之美的,对新闻进行自动分类,人工智能分类,用到的知识竟然是余弦定理。
地址是http://www.googlechinablog.com/2006/07/12.html

没有评论 »

数据结构系列八 简单树

四月 23, 2009 | 数据结构算法 | RSS 2.0

好久没更新博客了,一周时间都在思考些东西,有些东西都是不好写在博客上,感觉太浅薄,最近是继续看了好多数学等其它方面的东西,如生命的游戏,数学史等,总感觉自己思考的不够成熟,思维不够严密。暂时记录点自己开学习c的路程,though it’s to simple ,but this can give me a   hope .

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct tnode {
  char data;
  struct tnode *lchild;
  struct tnode *rchild;
 };
struct tnode tree;
void createtree(struct tnode *t) {
    struct tnodeee *p=t;
    char check;
    if(p->lchild == NULL || p->rchild ==NULL) {}
        printf(”please enter the data”);
        scanf(”%c”,&(p->data));
        getchar();
    }
    if(p->lchild == NULL) {
        printf(”%c left child is null Add ? y”,p->data);
        scanf(”%c”,&check);
        getchar();
        if(check == ‘y’) {
            struct tnode *q =(struct tnode*)malloc(sizeof(struct tnode));

            q->lchild =NULL;
            q->rchild =NULL;
            p->lchild =q;
            createtree(q);
        }
    
    
    }
    if(p->rchild == NULL) {
        printf(”%c right child is null Add ? y”,p->data);
        scanf(”%c”,&check);
        getchar();
        if(check == ‘y’) {
            struct tnode *q =(struct tnode*)malloc(sizeof(struct tnode));

            q->lchild =NULL;
            q->rchild =NULL;
            p->rchild =q;
            createtree(q);
        }
        
    
    
    
    }

}
 

void preorder(struct tnode *t)  {

    if(t) {
        printf(”%c”,t->data);
        preorder(t->lchild);
        preorder(t->rchild);
    }
}

void inorder(struct tnode *t)  {

    if(t) {
        inorder(t->lchild);
        printf(”%c”,t->data);
        inorder(t->rchild);
    }
}
void postorder(struct tnode *t)  {

    if(t) {
        postorder(t->lchild);
        postorder(t->rchild);
        printf(”%c”,t->data);
    }
}
void main () {
    clrscr();
    tree.lchild = NULL;
    tree.rchild = NULL;
    createtree(&tree);
    preorder(&tree);
    printf(”");
    inorder(&tree);
    printf(”");
    po

没有评论 »

高效产生不重复的随机数

三月 24, 2009 | c/c++, 数学, 数据结构算法, 软件工程/编程技巧/设计模式 | RSS 2.0

编程珠玑里面的

for(i = 0; i < n; i++)
{
x[i] = i;
}
for(i = 0; i < k; i++)
{
t = rand(i,n-1);
swap(x[i], x[t]);
out(x[i]);
}

没有评论 »

数据结构系列循环队列(六 )

三月 20, 2009 | c/c++, 数据结构算法 | RSS 2.0

引用:http://learn.akae.cn/media/ch12s05.html
我们介绍一种新的数据结构--环形队列(Circular Queue)。把queue数组想像成一个圈,head和tail指针仍然是一直增大的,当指到数组末尾时就自动回到数组开头,就像两个人围着操场赛跑,沿着它们跑的方向看,从head到tail之间是队列的有效元素,从tail到head之间是空的存储位置,head追上tail就表示队列空了,tail追上head就表示队列的存储空间满了。如下图所示
数据结构系列循环队列(六 ) - 玉树临风 - 小和尚真情无限

#define MAXQSIZE 100

typedef struct {
    int *base;//循环队列的存储空间
    int front ;
    int rear;
}SqQueue;
/*初始化*/
int InitQueue(SqQueue  *Q) {
    Q->base = (int *)malloc(MAXQSIZE*sizeof(int));
    if(!Q->base) return -1;

    Q->front = 0;
    Q->rear = 0;
    return 0;
}
/*元素e加入队,成功为0 ,否则返回1*/
int EnQueue(SqQueue *Q,int e) {
    if((Q->rear+1)%MAXQSIZE == Q->font) return -1;
    Q->base[Q->rear] = e;
    Q->rear = (Q->rear +1)%MAXQSIZE;
}
/*出队列*/
int DeQueue(SqQueue *Q,int *c) {
    if(Q->rear == Q->front) return -1;
    *e = Q->base[Q->front];
    Q->front = (Q->front+1)%MAXQSIZE;
    return 0;

}

没有评论 »