Fork me on GitHub

第三讲.线性表(读书笔记)

一.线性表(List)概念

   线性表(List):零个或多个数据元素的有限序列。

   元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继。

二.线性表的抽象数据类型

   对于一个线性表来说,插入数据和删除数据都是必须的操作。

   注意一个很容易混淆的地方:当你传递一个参数给函数的时候,这个参数会不会在函数内被改动决定了使用什么参数形式。如果需要被改动,则需要传递指向这个参数的指针,如果不用被改动,可以直接传递这个参数。

 

 

三.线性表的顺序存储结构

     1.线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。

  我们就发现描述顺序存储结构需要三个属性:

    1>.存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置。
    2>.线性表的最大存储容量:数组长度MaxSize。
    3>.线性表的当前长度:length

   需要注意: 数组的长度是存放线性表的存储空间的长度,存储分配后这个量一般是不变的。

线性表的长度是线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是变化的。
在任意时刻,线性表的长度应该小于等于数组的长度。

 

    2.地址计算方法

 

 

    用数组存储顺序表意味着要分配固定长度的数组空间,由于线性表中可以进行插入和删除操作,因此分配的数组空间要大于等于当前线性表的长度。

 

       我们通常把具有这一特点的存储结构称为随机存取结构。

    3.顺序存储结构的插入与删除

顺序存储结构的插入与删除

 

 

四.线性表的链式存储结构

 

 

 

    1.概念和特点:线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意味着,这些数据元素可以存在内存未被占用的任意位置

   我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称做指针或链。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。

 

 

    2.头指针和头结点的异同

 

示意图:

 

 

   3.单链表的读取

   获得链表第i个数据的算法思路:
    1>.声明一个指针p指向链表第一个结点,初始化j从1开始;
    2>.当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1;
    3>.若到链表末尾p为空,则说明第i个结点不存在;
    4>.否则查找成功,返回结点p的数据。

   4.单链表的插入与删除

插入:

    它的作用就是生成一个新的结点,其类型与Node是一样的,其实质就是在内存中找了一小块空地,准备用来存放数据e的s结点。

删除:

    单链表第i个数据删除结点的算法思路:
    1>.声明一指针p指向链表头结点,初始化j从1开始;
    2>.当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;
    3>.若到链表末尾p为空,则说明第i个结点不存在;
    4>.否则查找成功,将欲删除的结点p->next赋值给q;
    5>.单链表的删除标准语句p->next=q->next;
    6>.将q结点中的数据赋值给e,作为返回;
    7>.释放q结点;
    8>.返回成功。

总结:

    第一部分就是遍历查找第i个结点;第二部分就是插入和删除结点。

    我们希望从第i个位置,插入10个结点,对于顺序存储结构意味着,每一次插入都需要移动n-i个结点,每次都是O(n)。而单链表,我们只需要在第一次时,找到第i个位置的指针,此时为O(n),接下来只是简单地通过赋值移动指针而已,时间复杂度都是O(1)。显然,对于插入或删除数据越频繁的操作,单链表的效率优势就越是明显。

 

   5.单链表的整表创建

         对于每个链表来说,它所占用空间的大小和位置是不需要预先分配划定的,可以根据系统的情况和实际的需求即时生成。
         所以创建单链表的过程就是一个动态生成链表的过程。即从“空表”的初始状态起,依次建立各元素结点,并逐个插入链表。

   6.单链表的整表删除

  单链表整表删除的算法思路如下:
    1>.声明一指针p和q;
    2>.将第一个结点赋值给p;
    3>.循环:

 

 

   7.单链表结构与顺序存储结构优缺点

 

 

 

    1>.若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。若需要频繁插入和删除时,宜采用单链表结构。比如说游戏开发中,对于用户注册的个人信息,除了注册时插入数据外,绝大多数情况都是读取,所以应该考虑用顺序存储结构。而游戏中的玩家的武器或者装备列表,随着玩家的游戏过程中,可能会随时增加或删除,此时再用顺序存储就不太合适了,单链表结构就可以大展拳脚。当然,这只是简单的类比,现实中的软件开发,要考虑的问题会复杂得多。
    2>.当线性表中的元素个数变化较大或者根本不知道有多大时,最好用单链表结构,这样可以不需要考虑存储空间的大小问题。而如果事先知道线性表的大致长度,比如一年12个月,一周就是星期一至星期日共七天,这种用顺序存储结构效率会高很多。
   3>.总之,线性表的顺序存储结构和单链表结构各有其优缺点,不能简单的说哪个好,哪个不好,需要根据实际情况,来综合平衡采用哪种数据结构更能满足和达到需求和性能。

 

五.静态链表

 

     总的来说,静态链表其实是为了给没有指针的高级语言设计的一种实现单链表能力的方法。尽管大家不一定会用得上,但这样的思考方式是非常巧妙的,应该理解其思想,以备不时之需

 

六.循环链表

    将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表(circular linked list)。

   从刚才的例子,可以总结出,循环链表解决了一个很麻烦的问题。如何从当中一个结点出发,访问到链表的全部结点。

七.双向链表

    双向链表在遍历查找时,克服了单链表每次都要从头开始循环一遍的做法,双向链表每个元素都有前后两个指针,可以随时遍历查找,不用从头遍历.

    双向链表的前后遍历容易,但在插入和删除时要注意,也是双向的指针.

 

以插入为例子:

 

 

八.总结回顾
    这一章,我们主要讲的是线性表。
   先谈了它的定义,线性表是零个或多个具有相同类型的数据元素的有限序列。然后谈了线性表的抽象数据类型,如它的一些基本操作。

    之后我们就线性表的两大结构做了讲述,先讲的是比较容易的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。通常我们都是用数组来实现这一结构。
   后来是我们的重点,由顺序存储结构的插入和删除操作不方便,引出了链式存储结构。它具有不受固定的存储空间限制,可以比较快捷的插入和删除操作的特点。然后我们分别就链式存储结构的不同形式,如单链表、循环链表和双向链表做了讲解,另外我们还讲了若不使用指针如何处理链表结构的静态链表方法。
    总的来说,线性表的这两种结构(如图3-15-1所示)其实是后面其他数据结构的基础,把它们学明白了,对后面的学习有着至关重要的作用。

 

posted @ 2015-09-25 22:15  DengHuiCheng  阅读(290)  评论(0编辑  收藏  举报