zoukankan      html  css  js  c++  java
  • 数据结构与算法--线性表系列(顺序存储结构的线性表)

      hello,everybody!又与大家见面了,因为线性表这章内容比较多一些,还有一些代码需要practice,所有好多天没有写博客。今天让我们一起来学习数据结构---线性表吧。

    线性表的定义:

    顾名思义,线性表,就是具有线性质的一种数据结构。书中的例子是这样说的:本书作者去幼儿园接孩子,发现了一个very interesting 的现象。孩子们每次都是排着队放学,每个孩子前面有个唯一的小朋友,后面也有一个唯一的小朋友。他们之间的关系是一对一的关系。好像是一条线把他们栓在了一起似的,这个例子很形象的向线性表做了诠释。

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

    首先,数据元素要有限,不能是无限多个数据元素。其次,他们之间是有秩序的,是按顺序来存储https://signup.wordpress.com/activate/9e822d27ba11e157 的。就像,幼儿园的小朋友排队似的,是按顺序来。

    线性表是数据结构中,用的最多的,也是最简单的一种数据结构。学好线性表很重要,她重要,必须学好。她简单,更要学好,把简单的学好了,我们才有信心学习之后较复杂的数据结构。

    线性表的抽象数据类型:

    通过前面的线性表的定义,我们知道了,线性表结构是相同数据元素之间的有限序列。所以,我们可以用数组来表示线性表。创建固定大小的数组,就相当于在内存中找个了一段地址连续的存储空间,我们可以把线性表存入到数组中。们把线性表的元素个数,称为线性表的长度。这里我们要区分两个概念线性表长度””数组长度”

    线性表的长度:是指表中所存元素的多少,她会随着元素的改变而改变。

    数组的长度:它是来存放线性表的,相当于在内存总的开辟的空间。它一般是不会改变的。

    一般情况下,线性表的大小小于等于数组的大小。

    现在我们来看一下线性表的抽象数据类型:

    image

    image

    我们来分析一下,线性表都会有哪些操作?

    Firstly,创建线性表。InitList(*L)

    Secondly,判断线性表是否为空.ListEmpty(L)

    Thirdly,清空线性表。ClearList(*L)

    Fourthly,读取线性表中某个位置的元素。GetElem(L,I,*e)

    Fifthly,匹配元素。LocateList(L,e)

    sixthly,插入元素。ListInsert(*L,I,e)

    seventhly,删除元素。ListDelete(*L,I,*e)

    eighthly,计算线性表的长度.

    以上是些基本的线性表操作,对于一些复杂的操作,我们可以组合这些基础操作来完成。例如,两个线性表的并集操作。

    线性表的存储结构

    在第一章,讲解数据结构的概叙时,我们提到了,数据结构分为逻辑结构,物理结构。逻辑结构,是描述数据之间的存在关系。物理结构又称为存储结构,是将逻辑关系在内存中表现出来。存储结构分为两种,一种为顺序存储,一种为线性存储。

    我们先来学习一下线性表的顺序存储。

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

    image

    线性表的顺序存储的结构代码:

    image

    这里,我们发现描述线性表的顺序存储的结构需要三个属性:

    Firstly,存储空间的起始位置:数组data,它的起始位置就是存储空间的起始位置。

    Secondly,线性表的最大存储容量:数组的长度。

    Thirdly,线性表的当前长度:length.

    线性表顺序存储结构的操作

    获得元素操作:

    获得元素的算法思路:

    Firstly:线性表L必须存在,不为空.

    Secondly:位置i必须在线性表的合理位置。

    #define ok 1
    #define Error 0
    #define TRUE 1
    #define False 0
    typedef int Status; /*Status是函数的类型,其值是函数结果状态码,如OK等*/

    /*初始条件:顺序线性表L已存在,1《=i《=ListLength(L)*/
    /*操作结果:用e返回L中第i个数据元素的值*/
    Status GetElem(SqlList L,int I,ElemType *e)

    {

           if(i<1||i>L.length||L.length==0)

    return Error;

    else

    *e=L.data[i-1];

    return Ok;

    }

    线性表的插入操作:

    插入的算法思路:

    Firstly,插入位置i要合理,否则抛出异常。

    Secondly,线性表的长度大于或等于数组长度,抛出异常或动态增加容量。

    Thirdly,从表中最后一位开始,一直遍历到位置i.依次向后移动一个位置。

    Fourthly, 将要插入的元素插入i位置。

    Fifthly,线性表的长度增加1.

    Status ListInsert(SqlList *L,int I,EnlemType e)

    {

        int k;

       if(L->length==MAXSIZE)/*线性表的容量等于数组容量,线性表已满*/

    return ERROR;

    if(i<1||i>L->length+1)/*i位置不合理*/

    return ERROR;

    if(i<=L->length)/*判断不是向表尾插入数据*/

    {

                for(k=L->length-1;k>=i-1;k—)

                L->data[k+1]=L->data[k];   /*将要插入位置元素以及之后的所有元素向后移动一位*/

    }

           L->data[i-1]=*e; /*将要插入的数据插入i位置*/

    L->length++;/*线性表的长度加1*/

    return OK;

    }

    线性表的删除操作:
    删除操作的算法思路:

    Firstly,删除位置i合理,否则抛出异常。

    Secondly,将i位置的元素赋值给e。

    Thirdly,,从i位置开始,直到最后一位元素,依次向前移动一个位置。

    Fourthly,线性表的长度减1.

    Status ListDelete(SqlList *L,int I,EnlemType *e)

    {

    int k;

    if(L->length==0)/*线性表为空*/

    return ERROR;

    *e=L->data[i-1];

    if(i<1||i>L.length)

    return ERROR;

    if(i<L.length)

    {

    for(k=1;k<length;k++)

      L->data[k-1]=L->data[k];

    }

    L->length—;

    return OK;

    }

    我们仔细观察,发现了如果是存取数据,线性表的顺序存储结构的时间复杂度为O【1】.如果是插入、删除,时间复杂度为O【n】.那么我们就得出了一个结论,对于线性表中元素移动变化不大,更多的是存储数据的应用,那么我们顺序存储结构是不错的选择。

    线性表顺序存储结构的优缺点

    优点:

    Firstly,可以快速存取线性表中任一位置的元素。

    Secondly,无需为了表示表中的数据之间的逻辑关系而增加额外的存储空间

    缺点:

    Firstly,插入、删除元素会影响其他元素,需要移动大量的数据。

    Secondly,当线性表的容量变化较大时,难以确定存储空间的容量。

    Thirdly,造成存储空间的“碎片”。

    因为线性表内容比较多,我会分多篇文章介绍。

  • 相关阅读:
    原型模式
    哈希表原理
    Pow共识算法
    C++虚函数的工作原理
    TCP三次握手与四次分手
    TCP重置报文段及RST常见场景分析
    Ping、Traceroute工作原理
    ARP协议
    Rust生命周期bound用于泛型的引用
    Linux下core dump
  • 原文地址:https://www.cnblogs.com/VitoCorleone/p/3764619.html
Copyright © 2011-2022 走看看