摘要: 十三、左偏树(Leftist Tree)树这个数据结构内容真的很多,上一节所讲的二叉堆,其实就是一颗二叉树,这次讲的左偏树(又叫“左翼堆”),也是树。二叉堆是个很不错的数据结构,因为它非常便于理解,而且仅仅用了一个数组,不会造成额外空间的浪费,但它有个缺点,那就是很难合并两个二叉堆,对于“合并”,“拆分”这种操作,我觉得最方面的还是依靠指针,改变一下指针的值就可以实现,要是涉及到元素的移动,那就复杂一些了。左偏树跟二叉堆比起来,就是一棵真正意义上的树了,具有左右指针,所以空间开销上稍微大一点,但却带来了便于合并的便利。BTW:写了很多很多的程序之后,我发觉“空间换时间”始终是个应该考虑的编程方 阅读全文
posted @ 2012-02-16 11:11 北海石松 阅读(645) 评论(0) 推荐(0)
摘要: 十四、排序(Sort)这可能是最有趣的一节。排序的考题,在各大公司的笔试里最喜欢出了,但我看多数考得都很简单,通常懂得冒泡排序就差不多了,确实,我在刚学数据机构时候,觉得冒泡排序真的很“精妙”,我怎么就想不出呢?呵呵,其实冒泡通常是效率最差的排序算法,差多少?请看本文,你一定不会后悔的。1、冒泡排序(Bubbler Sort)前面刚说了冒泡排序的坏话,但冒泡排序也有其优点,那就是好理解,稳定,再就是空间复杂度低,不需要额外开辟数组元素的临时保存控件,当然了,编写起来也容易。其算法很简单,就是比较数组相邻的两个值,把大的像泡泡一样“冒”到数组后面去,一共要执行N的平方除以2这么多次的比较和交换的 阅读全文
posted @ 2012-02-16 11:11 北海石松 阅读(408) 评论(0) 推荐(0)
摘要: 十二、二叉堆(Binary Heap)经历了上一篇实现AVL树的繁琐,这篇就显得非常easy了。首先说说数据结构概念——堆(Heap),其实也没什么大不了,简单地说就是一种有序队列而已,普通的队列是先入先出,而二叉堆是:最小先出。这不是很简单么?如果这个队列是用数组实现的话那用打擂台的方式从头到尾找一遍,把最小的拿出来不就行了?行啊,可是出队的操作是很频繁的,而每次都得打一遍擂台,那就低效了,打擂台的时间复杂度为Ο(n),那如何不用从头到尾fetch一遍就出队呢?二叉堆能比较好地解决这个问题,不过之前先介绍一些概念。完全树(Complete Tree):从下图中看出,在第n层深度被填满之前,不 阅读全文
posted @ 2012-02-16 11:10 北海石松 阅读(349) 评论(0) 推荐(0)
摘要: 十、二叉查找树(BST)前一篇介绍了树,却未介绍树有什么用。但就算我不说,你也能想得到,看我们Windows的目录结构,其实就是树形的,一个典型的分类应用。当然除了分类,树还有别的作用,我们可以利用树建立一个非常便于查找取值又非常便于插入删除的数据结构,这就是马上要提到的二叉查找树(Binary Search Tree),这种二叉树有个特点:对任意节点而言,左子(当然了,存在的话)的值总是小于本身,而右子(存在的话)的值总是大于本身。这种特性使得我们要查找其中的某个值都很容易,从根开始,小的往左找,大的往右找,不大不小的就是这个节点了;插入一样的道理,从根开始,小的往左,大的往右,直到叶子,就 阅读全文
posted @ 2012-02-16 11:09 北海石松 阅读(449) 评论(0) 推荐(0)
摘要: 七、哈希表(Hash Table)及散列法(Hashing)数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为“链表的数组”,如图:左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。元素特征转变为数组下标的 阅读全文
posted @ 2012-02-16 11:08 北海石松 阅读(3158) 评论(0) 推荐(0)
摘要: 八、树(Tree)树,顾名思义,长得像一棵树,不过通常我们画成一棵倒过来的树,根在上,叶在下。不说那么多了,图一看就懂:当然了,引入了树之后,就不得不引入树的一些概念,这些概念我照样尽量用图,谁会记那么多文字?树这种结构还可以表示成下面这种方式,可见树用来描述包含关系是很不错的,但这种包含关系不得出现交叉重叠区域,否则就不能用树描述了,看图:面试的时候我们经常被考到的是一种叫“二叉树”的结构,二叉树当然也是树的一种了,它的特点是除了叶以外的节点都有两个子,图:由此我们还可以推出“三叉树”:当然还有“四叉树”,“五叉树”,“六叉树”……但太难画了,节点太多,略过。九、树的遍历(Traversal 阅读全文
posted @ 2012-02-16 11:08 北海石松 阅读(788) 评论(0) 推荐(0)
摘要: 六、二分法查找(Binary Search)如何从数组里找一个元素的位置?如果排列是无序的,我们只能从头到尾找,但如果排列是有序的,我们则可以用别的更好的方法,二分查找法就类似我们在英汉词典里找一个单词的方法。如下图所示(假如我们要查找的数字是“88”):下面我给出了一段demo代码,来演示二分查找法比顺序查找快多少,代码为了方便起见,初始化有序表的时候填入的数字都是均匀的,而事实上数字可以不均匀。你可以调整一下代码中TABLE_SIZE的值,从500,调到5000,再调到10000,再调到30000……你会发觉两者差距越来越明显。我在第一篇的地方提到二分查找法的复杂度为Ο(logn),而顺序 阅读全文
posted @ 2012-02-16 11:07 北海石松 阅读(632) 评论(0) 推荐(0)
摘要: 四、栈(Stack)前一篇讲解了最基本的东西,这篇就稍微前进一点点,讲一下栈,栈在英文中叫Stack,翻译成中文又叫“堆栈”,但决不能称为“堆”,这个要搞清楚,我们说的“栈”和“堆栈”指的都是Stack这种数据结构,但“堆”却是另外一个概念了,这里且不提。栈最大特点是先进后出,如图:可以看出,栈有几个最常见的方法,或者说必备的方法,Push,Pop和Top,即进栈,出栈和取最顶元素。从代码上看,栈如何实现呢?用数组好还是用单向链表好呢?其实都可以,我下面的例子是用数组实现的。说了那么多,栈有什么用呢?下面就举一个最经典的例题——逆波兰表达式(RPN,Reversed Polish Notati 阅读全文
posted @ 2012-02-16 11:06 北海石松 阅读(737) 评论(0) 推荐(0)
摘要: 五、队(Queue)前一篇讲了栈(Stack),队和栈其实只有一个差别,栈是先进后出,队是先进先出,如图:从图中可以看出,队有两个常用的方法,Enqueue和Dequeue,顾名思义,就是进队和出队了。队和栈一样,既可以用数组实现,也可以用链表实现,我还是偏向于用数组,我的实现示意图如下:队有啥用呢?一个最常用的用途就是“buffer”,即缓冲区,比如有一批从网络来的数据,处理需要挺长的时间,而数据抵达的间隔并不均匀,有时快,有时慢,先来的先处理,后来的后处理,于是你创建了一个队,用来缓存这些数据,出队一笔,处理一笔,直到队列为空。当然队的作用远不止于此,下面的例子也是一个很经典的例子,希望读 阅读全文
posted @ 2012-02-16 11:06 北海石松 阅读(375) 评论(0) 推荐(0)
摘要: 《数据结构》这门课是计算机专业的核心课程,但往往却让人头痛,因为比较抽象,当然了,也许你足够聪明,并不觉得它有多难,但对我而言,是有点难度,后来我仔细想了想,到底哪里难?我得出这么个结论:长篇大论,缺乏图表。现在的人都喜欢看电影,看电视剧,很少人还热衷于看小说吧,密密麻麻的文字不如一些图来得直观。另外,我们大多数人是做应用的,不是做研究的,所以我们只需要知道2+3=5,而不需要知道a+b=c。所以我就不深入理论,再说自己也没那个能力。好,接下去我就用最一般的例子,最通俗易懂的图,算法和尽量少的文字,描述某作者需要长篇大论方可完成教材。一、大圈表示法面试时候如果让你写一个算法,要求复杂度为Ο(n 阅读全文
posted @ 2012-02-16 11:05 北海石松 阅读(666) 评论(0) 推荐(0)
摘要: 今天偶然看到一个找出N个数中最大的前500个数,一个不错的解法是使用堆来进行选择,每一次读取一个数判断是否需要放到堆中,这样比较下来就可以找到最大或最小的前500个数了,自己晚上就参考别人的代码写了一个最小堆的结构,后期继续补充。View Code #include <stdio.h>#include <stdlib.h>typedef int ElemType;struct heap{ ElemType *num; int heapsize; int maxSize;};struct heap HP;int init_heap(int size){ if(size . 阅读全文
posted @ 2012-02-16 00:03 北海石松 阅读(268) 评论(0) 推荐(0)