您的位置:首页 > 理论基础 > 数据结构算法

<数据结构>(严版)第1~4章学习总结

2007-01-25 21:14 423 查看
截至今夜为止,数据结构的前四章的学习终于算是暂告一段落。基本已经记不清楚所用的时间了,大约是用了两星期左右吧,当然这是复习,在此之前已经看过若干遍的数据结构,只是一直觉得未曾完全把握所学的内容。至此,也并不意味着已经彻底掌握了,只是在较以前的基础上,又进一步理解了书中所述的主要内容。而现在,就此作一个简单的总结。

  在这四章中,第一章不用说,主要是开场白,介绍数据结构这一门课程的基本概念,以及所用到的描述语言,并介绍了算法这个关键的概念,以及衡量一个算法的两个重要性能指标:时间复杂度和空间复杂度。在这一部份中,时间复杂度的计算是一个难点。这里要注意程序运行步数与时间复杂度的区别。程序运行步数是其中所有循环作用下所有语句加在一起的总共的执行次数,而时间复杂度是指这个执行次数在复杂性以及用时的多少基本上达到哪一个阶,一般以O(1),O(n),O(log n),O(nlog n),O(nn),这样的一些阶数来衡量。这里的阶就象数学中的个位,十位,百位一样,是指一个级别,一个范围,也即如果一个程序的执行步数主要与(n-1)的倍数成线性关系,或是n的倍数成线性关系,它们的复杂度都大抵差不多,故而不用详细地分为是n-1的阶还是n的阶,一律看成大约是n阶,这是一个范围。

  第二章讲到的是线性表。线性表是数据结构的四大逻辑结构之一。在这一章里只是介绍了常见的最基本的线性表,在后面几章中还会介绍在基本的线性表上稍作一些规定与限制的线性表(栈,队列,串,广义表)。最基本的线性表就是数据之间存在着线性的关系,都是一对一的关系,一个结点跟接在另一个结点后面,成一条线的关系。每个结点只有一个前驱和一个后继(除第一个结点和最后一个结点而外)。
  为了处理这些线性的数据,我们在计算机的内部怎样存储它呢?我们可以采取两种最基本的存储方式,一种是:顺序存储结构,它采用数组来进行存储,也就是说数据是存储在数组里面的,这种结构适合于在整个程序的执行过程中对数据的操作并不影响它的结构,一般只进行查询检索等简单的操作;而所用到的该数组的分配方法可以是静态的也可以是动态的。静态的就是自始至终数组的长度是不变的,比如分配了100个,那就一直是100个,运行前后即运行时都只有这么个固定的空间。但如果是动态的,那么在程序运行过程中,可以根据实际需要空间的情况,而进行动态地增加空间。一般是预先给它分配M个字节左右的空间,如果不够,再固定地增加N个,如果还是不够,再增加N个等,以这样的方式进行。在严版的书上会有相关的程序说明与介绍。
  线性表的另一种存储结构就是传说中的以指针来处理的链表。(其实在第一种中用动态数组时也会简单地涉及到指针的操作,但这里是完全的指针操作,就连每一个结点也是用指针的形式来定义。)在这里,常有单链表,双链表,循环链表,等多种结构。结构多一些,也就是说方式多一些。方法多一些,这样我们应用起来的时候就灵活一些。先说说单链表,单链表中,它先定义单链表的结点,也就是说既然是一个单链表的话,它的结点应该具有单链表的风格,每个结点由两个域组成:数据域+指针域。然后可以在此的基础上定义什么是一个单链表。一个单链表就是由这样的一些结点,一个指着一个连接起来的。a->b->c->d... 成为一个链子。而这个链子只所以能够链在一起,靠的就是它的每个结点中的所定义的那个称之为指针域的指针。每个结点都固定的有一个指针,指向它后面的结点。因此,在单链表的操作中,如果需要增加数据或是删除数据,都只需要移动指针即可。也即对指针进行操作即可。修改指针的指向。
  无论是用顺序表结构来存储线性表还是链表结构来存储线性表,我们所需要的实现操作都得先在几种存储结构的ADT的基础上实现。也就是说,如果要真正把程序写出来,并执行出数据结构的话,首先得要用计算机语言向程序说明该存储结构的存储方式,所需要用到的操作种类,以及每一种操作所需要实现时在计算机内部直接对存储结构应该作什么样的操作。说明了这些以后,才有可能在主程序中调用这些子程序功能实现模块,一一进行调试实践并得出程序的运行结果。
  在以上两种结构中,由于顺序表是以数组为基本存储结构的,所以具有直接随机访问的特点,而链表呢只能逐一地向后移动到相应的数据上才能进行读取,所以具有顺序存取访问的特点。
  另外,在链表中,很多时候我们都需要加一个头结点,这是为了简化算法的方便。在殷人昆版的《数据结构》中对此作出了详细的说明,在此我们就不再详述。
第三章介绍的是栈和队列以及有关它们的应用.前面提到,栈和队列都是操作受限的线性表.也就是说,它们都属于线性表.但是它们在访问上受到了限制.栈这种结构,它的特点就是要求:先进后出.而队列是:先进先出.栈,比如说我们给一个订书机放入订书针,放进去的时候,头朝里的却是最后才订出来.又如果从一个玩具枪的枪口往里放子弹,一个个放入以后,出来时,是后进去的先打出来.(这当然是随意举个例子,只图形象生动一些,而并不科学,真正科学的例子,课本上已经给出了很多,在此就不列举了.)队列的例子就好举了,排队打饭的时候,排在前面的就先打到先离开,这就是一个队伍,也是队列.而栈和队列还有许多变形,有可能是两个栈放在一个数组中,栈顶相对着增长;还有队列也有可能是两个并排的队列,两头都可进可出,等等,在原有的基础上进行演绎,这些就是更多的一些内容,更大的范围.在这里我们就都不说了,简单提提栈与队列的存储结构.它们具有线性表的特质,也就是说即可以顺序数组存储也可以链表存储.相应的于是就有:顺序栈,链栈,顺序队列,链队.它们的程序实现起来,也还是蛮有意思的.
  在应用的时候,我们结合现实工作与生活中的一些具体情况,根据我们的需要,可以选择这些相应的存储结构进行一些程序设计,来帮助我们更好地实现所要做的事情.比如:利用栈可以进行:逆置数组,回文游戏,进制互换,括号匹配,表达式转换或计算,以及树部份的利用栈实现非递归遍历算法等,还有迷宫游戏,汉诺塔问题等等.而栈还有手动栈和系统自动栈等.系统自动栈就是说系统的内部还设置了栈,可以自动进行栈结构的操作.比如做一个递归程序,需要用到递归工作栈的时候,计算机系统自动会使用内部程序已经设置好的递归工作栈,进行层层递归,来实现程序操作.而如果说不用系统定义的栈,那就要自己手动地定义一个栈,并指定所有的栈所需要的操作以及用程序语言来实现它.这需要熟悉栈的算法.扯远了,接着讲队列吧.
  队列的应用也是较为广泛的.银行问题,航空售票系统等,这些就可以用队列来实现啦.而前面的最基本的线性表呢,学了以后,也可以实现计算多项式的加加减减等这样的操作.还是挺好的啦.

  接下来进入第四章吧.第四章介绍的是串.串也同样是线性表中的一种了,只是它的特殊性在于它所有的数据都是字符组成的.这些数据的处理在存储结构上就有三种:定长顺序,堆栈,块链.其中顺序是常见的一种了,书上的很多算法都基本是基于这种顺序存储结构来进行讲解的.比如串的查找,KMP算法等这些都是假设在定长顺序的存储结构上进行的.也就是说以数组来存储啦.而堆栈同样也是以地址连续的存储单元来实现的,所不同的是它能够在空间不够的情况下用relloc()再次进行申请增加空间.块链就是一个字符一个链结点或是多个字符成一个链接点,一块一块地由链子链在一起了,这里的块可以是一个字符或是多个字符,按具体情况来选择.
  在第四章中,除了replace,substring,contact这样的一些基本操作之外,最难的要数index, 和在index上的改进的KMP啦.KMP应该是本章中的最难点之一.而KMP又是一个比较精华的思想,而其精华之精华又在于getnext函数,即求next[]值的方法.在有了next[]之基础上,还可以再次进行改进,产生了一个nextval[],即修正以后的next值.
  本人学KMP,前后用了总共两星期左右的时间.第一次用的是殷版的书,上面说得比较详细,而第二次用的就是严版的书了,看严版的时候,由于有了殷版的基础,所以就主要是以听课件讲解的形式进行.当然,感觉还是看书的效果要好一些.所以如果有人看这帖子的话,奉劝还是多看教材为妙.在殷版与严版之间,还有一些差异,关于next值的定义上,殷好象是用了-1一律表示K值之外的情况时next的值.而严版分别有0和1两种数值来表示next值.另外,对于K的具体取值两本书也有不同的规定.当然,这对算法的本质上是没有区别的.
  在看KMP的时候,细细地比较改进前与改进后的差异,并搞清楚next[]值具体是怎么求的,这很关键.在弄熟悉这部份的内容以后,可以达到"看"一下串,就能够"看"出它的next[]数组的值来.这是一个很快的计算过程.

  至此,已经基本将前面部份的内容总结完了.一共是四章.后面第五章是广义表,它同样属于线性表,但它是一种广义的线性表,也就是说它在某种意义上拓广了线性表的概念,故而称之为广义表.后面若有空,还是会在学习之后进行总结,并同大家交流的.谢过看帖的朋友,如果看后有什么意见的话,欢迎跟帖,或是加入"数据结构"交流群(QQ群号码:27196587)与大家交流.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: