2008年7月20日

 

这阵子就准备买一个freerunner,fic生产的,实际上是中国苏州负责生产,只可惜在大陆不上市。

 

freerunner可以说是neo 1973的最终用户版,性能也略比1973强劲。熟悉qtopia就能很容易上手开发了。

 

记录几个openmoko相关技术的blog:

http://www.openmokofans.com/forums/

 

http://www.openmobilefree.net/

 

http://www.cublog.cn/u/13385/

 

 

另外也找到了另一个类似于openmoko的项目:Broncho

http://www.broncho.cn/

 

posted @ 2008-07-20 16:53 黑暗伯爵 阅读(28) | 评论 (0)编辑

2008年5月24日

    最近时差颠倒,今天一直睡到中午两点半才醒来,想到了那个恐怖而又高深的梦。

    梦里............黑暗中模糊看到一滩发着光的水,那滩水对我说:“我要吸纳你的意识,加入我吧,我就是你,你就是我!” 那滩水仿佛是一种群体意识,我突然感到了一种恐惧,惧怕自己从此没有意识。

    说完,那滩水随即长处了触角一样的东西向我伸过来,我想要逃跑,这时,听到了熟悉的儿歌,渐渐的,原来是楼下的幼儿园把我吵醒了.................

    出于惯性和懒惰,继续睡着了,这次梦中则没有那滩水,而是只有自己仿佛在思考群体意识和个体意识,朦胧中好像有了答案,却又被幼儿园的儿歌给吵醒了。

    彻底醒来后仔细想了想,好像是受到前几天看的《甘达星人》的影响才做了那个梦,而这个梦却又是自己生平第一次想到群体意识和个体意识,而这里的意识却又好像是意识本身或者是智慧。

    又想到蚂蚁或者蜜蜂会不会有群体意识,但梦里的那滩水,却是要吸纳具有个体意识(智慧)的我,但蚂蚁或密封却没有个体意识(智慧)....................

    又想到现在的分布式计算(云计算)或者是因特网,会不会造就出这种具备或不具备个体意识(智慧)的群体意识呢???????????????????

    某个科幻群里聊了一会儿,有人说王晋康写的《养蜂人》与此有关。 去看那篇小说喽~~

posted @ 2008-05-24 19:17 黑暗伯爵 阅读(97) | 评论 (0)编辑

2008年4月17日

递归
    不知道有新手听没听过别人拿剥糖块来形容递归,诸如一层层地剥好比一层层地进入递归。这种比喻可是误导了我,只想着剥了,其实剥完皮儿,取出糖块,再把皮儿一层层地穿上才算个完整的递归。    

    递归就是自己调用自己的函数或方法了,一般情况,像我这样的新手刚接触递归的时候,迷就迷在了不明白递归的原理上,在 (c#)数据结构与算法分析 --栈与队列 中说过,编译器一般用栈来实现递归,具体就看那篇文章吧。

    这里先举一个用到递归的例子。

    求第n项的三角数字,三角数字就是数列中,第n项的值是第n-1项加上n得来的。这里可不是那个斐波那契数列。
    1,3,6,10,15,21......... 这些个数就是三角数字。

    这个递归方法就是计算第n项的三角数字:
 1 //使用递归求第n项的三角数
 2 private int triangle(int n)
 3         {
 4             if (n == 1//这是递归的基准情形,一个递归没有基准的话,就没法跳出递归。
 5             {
 6                 return n;
 7             }
 8             else
 9             {
10                 return (n + triangle(n - 1)); //调用本方法
11             }
12         }

很简单的一个算法,可用 第n个三角数字=(n*n+n)/2 这个公式来验证其正确性。

仔细看看这个图就会完全明白递归到底怎么递归了。

n=5时,开始调用

第1层

n=5

第2层

n=4

第3层

n=3

第4层

n=2

第3层

n=1

返回 1
加 2
返回 3
加 3
返回 6
加 4
返回 10
加 5
返回 15


返回15
(这个表格在firefox下显示有点问题)


    这时,应该把递归理顺了吧,自己可以试试用递归求阶乘,然后试着解决汉诺塔问题,google搜一下会有很多汉诺塔问题的源码。

    很明显,上面那个递归是尾递归,在某些情况下,比如函数体比较庞大,有很多局部变量,则很容易引起栈溢出。有时候应该消除递归。
   
    这就用到栈了,下面这个源码,功能和上面一样,只不过用栈来消除递归了。
 1 //消除递归,使用栈代替递归
 2         private int triangleStack(int n)
 3         {
 4             Stack<int> traingle = new Stack<int>(); //这个栈来模拟递归中的环境变量
 5 
 6             while (n >= 1//相当于递归中的基准了
 7             {
 8                 traingle.Push(n); //将每次递减的值压入栈,相当于逐层调用递归
 9                 n = n - 1;
10             }
11 
12             while (traingle.Count > 0//这个相当于逐层跳出递归
13             {
14                 n = n + traingle.Pop(); //计算
15             }
16 
17             return n;
18         }

    不是很难吧,主要把递归的原理理清,思路自然就明了了。

    要注意的是,使用递归千万可别忘了基准情形,不然就永远递归不出来了。递归的效率有时候比较低,这样就可以用栈或循环来代替递归了。
posted @ 2008-04-17 20:34 黑暗伯爵 阅读(263) | 评论 (0)编辑

2008年4月13日


    首先,在win下,进入命令行,输入tree,它会以树的形式返回当前文件夹下的所有子文件夹及文件。



    如上图,就是一个树。

    就像一棵被颠倒过来的苹果树,每一个元素称之为节点,如图,A就是这棵树的老大了,称为(root),如果某个节点有元素的话,这个节点相对于它的子节点为根,这棵树相对于A来说,是它的子树,例如,树D是A的子树。

    对于没有子节点的节点,称之为节点。

    这些树的根都被来自跟的每一条有向的所连接。例如树E被来自根A的有向边TAE所连接。树J被来自根E的有向边TEJ所连接。

    那么从一个节点到另外一个节点的所有节点序列称为路径,路径上边的条数就是这条路径的了。可以看出,路径的长为所经过节点的个数减一。例如,路径EQ,它的长就是2。

    深度就是根节点与这个节点的路径的长,比如,节点P和Q的深度就是3,节点K的深度就是2。

树的表示
    可以用链表来表示一棵树。如图:


    如图,A是链表的第一个元素,G是最后的一个元素,如果元素有子节点,那么这个元素就是这棵树的链表。

    如箭头所指,ABCDEFG是一个链表,而节点DEFG是有子节点的树,所以DEFG元素存储的是另一个链表,比如E存储的是EIJ链表,以此类推,J存储的是JPQ链表,所以,一棵数不管有多大多深,都可以用一个链表表示,只不过这个链表包含了其他链表。
posted @ 2008-04-13 02:04 黑暗伯爵 阅读(287) | 评论 (1)编辑

2008年4月7日


    渐渐发现geeker们的共同点了。

  • 另类,不随主流
  • 爱科幻 (海因莱因、阿瑟.克拉克的小说必读)
  • 使用linux (大部分ubuntu)
  • 了解现代物理 (比较崇拜霍金大叔,知道弦和统一论)
  • 爱搞小发明
  • 崇尚自由、分享
  • (御宅)(没钱)..............................


posted @ 2008-04-07 13:46 黑暗伯爵 阅读(37) | 评论 (0)编辑

2008年4月6日

数组
    数组不用多解释了,都了解,这里再重复一些重要的。

    随机这个词经常出现,在刚学的时候,都说数组在内存中是随机访问的,然而随机数又是随机(不确定)的,这两个概念总是搞不清楚。这里的随机访问与随机存储器的概念一样,google了也百度了,就是搞不到这个随机是什么意思,就只能按random本意来理解了,只好意会。

    大家都知道数组在内存中存放的方式,是顺序的,也就是在访问某个元素的时候,比如访问第五个元素[5],只需要在开头地址加上偏移量,即5,就是第五个元素了。因为数组中存储的数据类型都是同一种的类型,它们在内存中的大小都是固定的,所以偏移量很好算。

    多维数组,很多人和我一样,到这里都会迷茫一下,二维数组不难想象,就像一张表,如果三维的话,就想象成一个魔方,是立方体,如果三维以上,就难了,不能根据这种思维定式去想象它的结构,了解它在内存中的方式就行了。

    看几个例子:
    

 int[4]

内存

地址

intArray[0]


bffff4f0


bffff4f1
bffff4f2
bffff4f3

intArray[1]


bffff4f4


bffff4f5
bffff4f6
bffff4f7

intArray[2]


bffff4f8


bffff4f9
bffff4fa
bffff4fb

intArray[3]


bffff4fc


bffff4fd
bffff4fe
bffff4ff

 int[2][2]

内存

地址

intArray[0][0]


bffff4f0


bffff4f1
bffff4f2
bffff4f3

intArray[0][1]


bffff4f4


bffff4f5
bffff4f6
bffff4f7

intArray[1][0]


bffff4f8


bffff4f9
bffff4fa
bffff4fb

intArray[1][1]


bffff4fc


bffff4fd
bffff4fe
bffff4ff
























    上面是两个一维整数数组和二维整数数组。从图中可以看出每次读取某个元素时只要加上某个偏移量就行了,偏移量就是就是这个元素类型所占的内存空间大小,上面是整形数组,一个整形占4个字节。

    可以看到,无论是多少维()的数组,在内存中都是线性的连续存储,它是按行优先顺序放在内存中的,即,如果有从n00开始,其次是n01...然后是n10,n11.........以此类推,三维的数组就是n000,n001.......n010,n011一直到n100.......。有些例外情况,比如fortran语言中,它是按列优先顺序存放的,顺序是n10,n20,n30.....n11,n21......n12,n22 这样的,以此类推,不管多少维,都是这样算的。

    数组的优点就是访问速度快,缺点是在声明时就已经确定数组的大小,不能再扩充了。

向量(vector容器)
    vector大家都经常使用,其实向量是一个动态数组,所谓动态就是数组在声明后还可以增长,也可以插入元素,动态数组在增长的时候,其实也就是先分配好内存,然后new 一个数组,一个个将原数组再拷贝进去。向量使用完后再delete分配的内存。

    向量的优点和数组一样,缺点就是增长过快的时候比较耗资源。

(list)
    一个简单的单向链表:

A

 

B

 

C

 

D

 

E

 

F

 

    链表的每个元素称为节点,每个结点都有两个单元,第一个就是数据项,存放数据,第二个称为(或next链),它指向第二个元素的地址,以此类推,最后的一个元素指向NULL。
    
    这种单项列表,如果给表头或表尾添加元素的时候会有些不便,最好的办法就是加上表头和表尾了。

    一个带表头和表尾的单向链表:

head

 

A

 

B

 

C

 

D

 

E

 

F

 

end

 

    表头的数据元素是这个表的名字,例如上面那个表名是head,表头的链指向第一个节点,最后一个节点则指向尾节点。

    给表添加一个元素的时,以上边的head表为例,在A和B中间插入一个节点Y,则首先把A节点的链指向Y,然后将Y的链指向B。如果是删除一个结点的话,假设删除D节点,则只要将C节点链指向D节点的下一个节点,即E节点。是不是很简单,但问题又来了,每次插入或删除一个结点的时候,尤其是删除最后一个结点的时候,都得寻找它前面的节点,这就比较麻烦了,而双向链表则解决了这种问题。

    双向链表:

n

A

 

 

B

 

 

C

 

 

D

 

 

E

 

 

F

n

    可以看出,每个都在数据区前面都多了一个指向它前面节点的指针。我们把一个节点的后一个节点叫做直接后驱,它前面的一个结点叫做直接前驱。第一个节点没有直接前驱,所以为NULL,末尾节点没有直接后驱,也为NULL,这样在插入或删除一个节点的时候的就可以直接找到它的前后两个节点了。

    有时候为了方便查询,会让最后一个节点的后驱的next链指向第一个节点,这样的链表就叫做循环链表

    当然,表不止有链表,还有别的,以后会学习到的。

    链表的优点就是可以不受内存单元的线性限制(比如数组),可以充分利用空间,缺点就是链表的存储密度不如数组或向量的高,密度当然是质量除以体积了,这里质量就是实际数据的大小,体积就是链表的大小,因为每个节点要额外存储链,所以链表的存储密度就相对小了 ,另外在链表很长时,操作一个节点就比较麻烦了,因为它在内存中不是连续的,所以得从头开始一个个找,效率就低了。


    大致算是解了数组、向量和链表,可以根据它们的特点再不同场合使用。

ps:如有错误,还请不吝指正,谢谢~!

posted @ 2008-04-06 22:43 黑暗伯爵 阅读(343) | 评论 (1)编辑
     摘要: 栈是一种后进后出机制,它只允许访问访问一个数据项,即 栈顶(最后插入的数据项)。它有主要的三种操作:push,向栈内压入值;pop,弹出栈顶的值,即返回栈顶的值,并把它从栈内删除;peek,只返回但不删除栈顶。
栈普遍应用于编译器、文本检测、科学计算等等,在编译器中,它用来检测一个函数体等是否为封闭的(括号是否成对等等),在文本检测中,想想你的vs,如果最后没有大括号它就会检测出来,和编译器中一样,在科学计算中,就像商店能买到的那些高级计算器,输入一个算式可以直接计算出来结果,而不像普通计算器中,只能输入数字,然后在按键一步一步计算,以上这些应用场景,归根结底都是对文本的检测,现在知道栈的用途了吧,后面将结合队列一起练练手............................  阅读全文
posted @ 2008-04-06 05:05 黑暗伯爵 阅读(472) | 评论 (4)编辑

2008年4月5日

    在比较算法的效率时,往往是算法的运行时间与数据项个数关系间比较,例如,为了得到某个结果,在同一数据量下,哪个算法运行最快,效率最高,而后改变这一数据量,哪种算法的时间又最快......

大O表示法
    
在描述算法运行时间时,往往能看到O(N)、O(logN)等,大O中的O的意思就是"order of"(大约是),它是种概念,就比如 大型车、小型车和中型车,忽略具体大小尺寸,来描述汽车。

首先来跟着我分析一段代码:
示例 1:
 1 int sum(int n)
 2 {
 3     int partialSum;
 4     partialSum = 0;
 5     for(int i = 1;i <= n;i++)
 6     {
 7         partialSum += i * i * i;
 8     }
 9     return partialSum;
10 }

这个程序是计算 Σn i=1 i3 即 从1开始到n的整数,计算它们的立方和

    声明不计时间,赋值、计算、比较每次占一个时间单位,则从第四行开始,首先花费1个时间单位,接着进入循环,给i赋值,又占一个单位,它只运行一次,接着比较,运行n+1次,i++为两次计算,一次加一,一次赋值,而它要运行n次,占2n个时间单位,循环主体是四个时间单位(两个乘法,一个加法,一个赋值),总共执行n次,故花费4n个单位,最后返回花费1个时间单位。

    最终,这个程序总共花费1(赋值)+1(赋值)+(1+2n)(比较)+4n(计算)+1(返回)=6n+4 个时间单位,但是,如果每个程序都像这样计算的话,岂不是让人崩溃,大O表示法的宗旨就是,舍去所有常量,把它归入cpu,平台等因素造成的时间,假设这些常量总体为K,则上面那个程序所花费的时间是n+K,按照这种计算方式,每个程序的运行时间都会转化为xn+K,所以我们可以把K舍去。

    最终,以大O表示法,这个程序的运行时间是O(N)。

    如果是一个嵌套循环呢,比如:
示例 2:
for(int i=0;i<n;i++
{
    
for(int j=0;j<i;j++)
    {
        代码;
    }
}

这段代码的运行时间就为O(N2)了 (自己按照上面那种方法掐指算一下)。

    如果把实例2添加进示例1中的返回语句前,则运行时间为n+n2,以大O表示法则为O(n2)。

    看到了吧,大O表示法是没有加号的,所有这些都被忽略了,没有常数,只有迭代次数。

    很多与我一样数学底子不好的同学,遇到O(logN)等这样带对数的时候就会迷茫,其实也不难,拿二分搜索举例,它的运行时间是O(logN)。

    什么是二分搜索?我来举个例子,李咏大哥让你猜个电器的价格,猜中了就归你了,如果你聪明的话,就不会乱猜,你会首先随机猜一个自己认为适合的价格(比如一个电视,你猜5000),如果他喊低了,就继续往上加,但是他喊高了,你会选择刚才价格的一半(2500),如果他喊高了,则继续折一半(1250),这次他喊低了,你就猜3750,按照这种原则,你最终猜对了,是3750,你只用了3次。

    按照这种方法,最坏的情况下(即猜的次数最多),N个数所用的次数X<=log2N ,因为2x<=n,比如10个数,最多猜测3次,即23<=10 ,3<=log210 。
    
    现在大致明白了log形式的运行时间了吧。

    这里列出一些运行时间计算的一些法则,是从《数据结构与算法分析C++描述(第三版)》上面摘录的

法则1:for循环  一个for循环的运行时间至多是该for循环内语句(包括测试)的运行时间乘以迭代的次数。

法则2:嵌套循环  从里向外分析这些循环。在一组嵌套循环内部的一条语句总的运行时间为该语句的运行时间乘以该组所有循环的大小的乘积。

法则3:顺序语句  将各个语句的运行时间求和即可(这意味着,其中的最大值就是所得的运行时间)。

法则4:IF/ELSE语句  一个if/else语句的运行时间从不超过判断再加上每个主体中运行时间较长者的总的运行时间。

    最后,总结一下,其实运行时间O就是相对增长率,我们所比较的运行时间,就是把他们的相对增长率进行比较,这里的运行时间,都是在最坏情况下得出的,因为数据量充满不确定性,不保守估计的话,会出错,了解了运行时间的算法,对一个算法的好坏的判断就有基准了,以后会用到这里(尤其是排序算法)。

    我所理解的很可能有错误,希望高手拍砖指正,谢绝打击的言论,毕竟我不懂高数,这个设计到了极限。


ps:我们当时排序算法就只教了冒泡,就连快速排序都不知道是什么,现在同学们遇到排序,都是冒泡
还好,我学了比较多的排序算法,每个都有自己的应用场景,我以后的笔记会讨论排序的,真希望我的同学们能看看这些笔记。
posted @ 2008-04-05 16:00 黑暗伯爵 阅读(363) | 评论 (4)编辑


ALEXANDER CALDER
Ritou I, 1946
Hanging mobile: painted sheet metal, wire and rod
Height: 32 inches (81.3 cm); Span: 31 inches (78.7 cm)

    最近一段时间学习 数据结构和算法分析 ,由于数学底子很差,比较吃力,但还是尽力去学了,现在开始做笔记,把那些生涩的理论转化成比较容易懂的语言,希望和我一样底子差的朋友能学的更好。 我参考的书目有《数据结构和算法分析 c++描述》和《java数据结构和算法》。

已更新至:
  1. (c#)数据结构与算法分析 --运行时间计算
  2. (c#)数据结构与算法分析 --栈与队列
  3. (c#)数据结构与算法分析 --数组、向量和表
  4. (c#)数据结构与算法分析 --树
  5. (c#)数据结构与算法分析 --递归 
posted @ 2008-04-05 14:08 黑暗伯爵 阅读(370) | 评论 (0)编辑

2008年4月3日

      昨天下了两本Ajax方面的书籍:《Ajax基础教程》和《AJAX实战》,都是扫描的,遗憾的是没有书签目录,看起来甚是不便,于是花了4个小时做了个书签目录,累死,那个《AJAX实战》本来90来MB,用 Adobe Acrobat 8 Pro加了书签后竟然飙升为180MB,真搞不清怎么会这样..................
      由于《AJAX实战》太大,没法上传,就把《Ajax基础教程》上传到mofile了:


下载  提取码:3601642301711317

下载的朋友记得留留言啊,加上书签真的是苦力活。

posted @ 2008-04-03 14:06 黑暗伯爵 阅读(80) | 评论 (1)编辑

公告

拙劣的文字记录颓废的生活

导航

<2008年10月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

统计

与我联系

搜索

 

常用链接

留言簿(2)

我的标签

随笔分类

随笔档案

相册

nasboq

最新评论

阅读排行榜

评论排行榜