双向链表
继续我们刚才的例子,你平时都是从_h海一路停留到北京的,可是这一次,你得先到北京开会,谁叫北京是首都呢,会就是多。开完会后,你需要例行公事,
走访齐个城市,此时你怎么办、
有人又出主意了,你可以先回上海,一路再乘火车走遍这几个城市,到了北京后,你再飞回上海。你会感慨,人生中为什么总会有这样出主意的人存在呢?真要气死人才行。哪来这么麻烦,我一路从北京坐火车或汽车回去不就完了吗。
对呀,其实生活中类似的小智慧比比皆是,井不会那么的死板教条。我们的单链表,总是从头到尾找结点,难道就不可以正反遍历都可以吗?当然可以,只不过需要加点东西而已。我们在单链表中,右了next指针,这就使得我们要查找下一结点的时间复杂度为O〔1〕0 p!是如果我们要查找的是上一结点的话,那最坏的时间复杂度就是o(n} f,f}}为我们每次都要从头开始遍历查找。为了克服单!却陕这一缺点,我们的老科学家们,设I E'出了双向链表。双向链表 {dnuhle linked list}是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以在双向链表中的结点都有两个指针域个指向肖接后继,另一个指向直接前驱。
既然单链表也可以有循环链表,那么双n1链表当然也,〕丁以是循环表。双向链表的循环带头结点七点的空链表如下图所示。
由一于.这是双向链表,}f}么对T链表中的某一个结点p,它的后继的前驱是谁?当然还是它自己。’色的前驱的后继自然也是它自己,即 这就如同上海的下一站是苏州、Ails么上海的下一站的前一站是哪里?哈哈、有点废话的感觉。双向链表是单链表中打,’展出来的结构,所以它的很多操作是和单链表相同的,比如求长度的ListLength,查找TC素的GetElern ,获得JL'索位置
的Lo}ateElem等。a}些操作都只要涉及一个方向的指针即可,另一指针多了也不能提供什么帮助。就像人生一样,想享乐就得先努力,欲收获就得付代价。双向链表既然是比单链表多了如可以反例遍历查找等数据结构,那么也就需要付出一些小的代价:在插人和删除时,需要更改两个指针变缈。插入操作时,其实并不复杂,不过顺序很重要,千万不能写反了。我们现在假设存储元素 e 的结点为,,要实现将结点 s 插入到结点 p 和 p -> next之间需要下面几步,如下图所示:
这一章,我们主要讲的是线性表先谈了它的定义1线性表是零个或多个具有相同类型的数据元素的有限序列。然后谈了线性表的抽象数据类型,如它的一些基本操作。之后我们就线性表的两大结构做了讲述,先讲的是比较容易的顺序存储结构,指的是用一段地址连续的存储单兀依次存储线性表的数据元素。通常我们都是用数组来实现这一结构。后来是我们的重点,由顺序存储结构的插入和删除操作不方便,引出了链式存储结构。它具有不受固定的存储空间限制,可以比较快捷的插人和删除操作的特点。然后我们分别就链式存储结构的不同形式,如单链表、循环链表和双向链表做了讲解,另外我们还讲了若不使用指针如何处理链表结构的静态链表方法。总的来说,线性表的这两种结构(如图3-15一1所示)其实是后面其他数据结构的基础、把它们学明自了,对后面的学习有着至关重要的作用。
继续我们刚才的例子,你平时都是从_h海一路停留到北京的,可是这一次,你得先到北京开会,谁叫北京是首都呢,会就是多。开完会后,你需要例行公事,
走访齐个城市,此时你怎么办、
有人又出主意了,你可以先回上海,一路再乘火车走遍这几个城市,到了北京后,你再飞回上海。你会感慨,人生中为什么总会有这样出主意的人存在呢?真要气死人才行。哪来这么麻烦,我一路从北京坐火车或汽车回去不就完了吗。
对呀,其实生活中类似的小智慧比比皆是,井不会那么的死板教条。我们的单链表,总是从头到尾找结点,难道就不可以正反遍历都可以吗?当然可以,只不过需要加点东西而已。我们在单链表中,右了next指针,这就使得我们要查找下一结点的时间复杂度为O〔1〕0 p!是如果我们要查找的是上一结点的话,那最坏的时间复杂度就是o(n} f,f}}为我们每次都要从头开始遍历查找。为了克服单!却陕这一缺点,我们的老科学家们,设I E'出了双向链表。双向链表 {dnuhle linked list}是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以在双向链表中的结点都有两个指针域个指向肖接后继,另一个指向直接前驱。
既然单链表也可以有循环链表,那么双n1链表当然也,〕丁以是循环表。双向链表的循环带头结点七点的空链表如下图所示。
由一于.这是双向链表,}f}么对T链表中的某一个结点p,它的后继的前驱是谁?当然还是它自己。’色的前驱的后继自然也是它自己,即 这就如同上海的下一站是苏州、Ails么上海的下一站的前一站是哪里?哈哈、有点废话的感觉。双向链表是单链表中打,’展出来的结构,所以它的很多操作是和单链表相同的,比如求长度的ListLength,查找TC素的GetElern ,获得JL'索位置
的Lo}ateElem等。a}些操作都只要涉及一个方向的指针即可,另一指针多了也不能提供什么帮助。就像人生一样,想享乐就得先努力,欲收获就得付代价。双向链表既然是比单链表多了如可以反例遍历查找等数据结构,那么也就需要付出一些小的代价:在插人和删除时,需要更改两个指针变缈。插入操作时,其实并不复杂,不过顺序很重要,千万不能写反了。我们现在假设存储元素 e 的结点为,,要实现将结点 s 插入到结点 p 和 p -> next之间需要下面几步,如下图所示:
这一章,我们主要讲的是线性表先谈了它的定义1线性表是零个或多个具有相同类型的数据元素的有限序列。然后谈了线性表的抽象数据类型,如它的一些基本操作。之后我们就线性表的两大结构做了讲述,先讲的是比较容易的顺序存储结构,指的是用一段地址连续的存储单兀依次存储线性表的数据元素。通常我们都是用数组来实现这一结构。后来是我们的重点,由顺序存储结构的插入和删除操作不方便,引出了链式存储结构。它具有不受固定的存储空间限制,可以比较快捷的插人和删除操作的特点。然后我们分别就链式存储结构的不同形式,如单链表、循环链表和双向链表做了讲解,另外我们还讲了若不使用指针如何处理链表结构的静态链表方法。总的来说,线性表的这两种结构(如图3-15一1所示)其实是后面其他数据结构的基础、把它们学明自了,对后面的学习有着至关重要的作用。