• 数据结构之线性表


    线性结构是最常用、最简单的一种数据结构。而线性表是一种典型的线性结构。其基本特点是线性表中的数据元素是有序且是有限的。在这种结构中:

    (1) 存在一个唯一的被称为“第一个”的数据元素;

    (2)存在一个唯一的被称为“最后一个”的数据元素;

    (3)除第一个元素外,每个元素均有唯一一个直接前驱;

    (4)除最后一个元素外,每个元素均有唯一一个直接后继。

    一、线性表的定义

      线性表:是由n(n≧0)个数据元素(结点)a1,a2, …an组成的有限序列。该序列中的所有结点具有相同的数据类型。其中数据元素的

    个数n称为线性表的长度。

      当n=0时,称为空表。

      当n>0时,将非空的线性表记作: (a1,a2,…an) a1称为线性表的第一个(首)结点,an称为线性表的最后一个(尾)结点。

      a1,a2,…ai-1都是ai(2≦i≦n)的前驱,其中ai-1是ai的直接前驱; ai+1,ai+2,…an都是ai(1≦i ≦n-1)的后继,其中ai+1是ai的直接后继。

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

    ADT List{

        数据对象:D = { ai | ai∈ElemSet, i=1,2,…,n, n≧0 }

        数据关系:R = {<ai-1, ai> | ai-1, ai∈D, i=2,3,…,n }

        基本操作:

          InitList( &L )

            操作结果:构造一个空的线性表L;

          ListLength( L )

            初始条件:线性表L已存在;

            操作结果:若L为空表,则返回TRUE,否则返回FALSE;

          ….

          GetElem( L, i, &e )

            初始条件:线性表L已存在,1≦i≦ListLength(L);

            操作结果:用e返回L中第i个数据元素的值;

          ListInsert ( L, i, &e )

            初始条件:线性表L已存在,1≦i≦ListLength(L) ;

            操作结果:在线性表L中的第i个位置插入元素e;

           …

    } ADT List

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

    (1)顺序存储的定义:

      把线性表的结点按逻辑顺序依次存放在一组地址连续的存储单元里。用这种方法存储的线性表简称顺序表。

    (2)顺序存储的特点:

      线性表的逻辑顺序与物理顺序一致;

      数据元素之间的关系是以元素在计算机内“物理位置相邻”来体现。

    (3)顺序存储方式:

      我们用结构类型来定义顺序表类型。

       #define OK 1

      #define ERROR -1

      #define MAX_SIZE 100

      typedef int Status ;

      typedef int ElemType ;

      typedef struct sqlist

        {   ElemType Elem_array[MAX_SIZE] ;

            int length ;

         } SqList ;

    (4)地址计算方法:

      设线性表的每个元素需占用l个存储单元,以所占的第一个单元的存储地址作为数据元素的存储位置。则线性表中第i+1个数据元素的存储位置

    LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间满足下列关系:

      LOC(ai+1)=LOC(ai)+l

      线性表的第i个数据元素ai的存储位置为:

       LOC(ai)=LOC(a1)+(i-1)*l

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

    (1)顺序表的初始化:

    Status Init_SqList( SqList *L )

      {  L->elem_array=( ElemType * )malloc(MAX_SIZE*sizeof( ElemType ) ) ;

         if ( !L -> elem_array ) return ERROR ;

        else { L->length= 0 ; return OK ; }

      }

    (2)顺序表的插入操作:

    插入操作的实现步骤:

      将线性表L中的第i个至第n个结点后移一个位置。

      将结点e插入到结点ai-1之后。

       线性表长度加1。

    算法描述:

    Status Insert_SqList(Sqlist *L,int i ,ElemType e)

      {  int j ; if ( i<0||i>L->length-1) return ERROR ;

         if (L->length>=MAX_SIZE)

        { printf(“线性表溢出! ”); return ERROR ; }

        for ( j=L->length–1; j>=i-1; --j )

        L->Elem_array[j+1]=L->Elem_array[j];

        /* i-1位置以后的所有结点后移 */

        L->Elem_array[i-1]=e;

        /* 在i-1位置插入结点 */

        L->length++ ;

        return OK ;

       }

    (3)顺序表的删除操作

    删除操作的实现步骤:

      将线性表L中的第i+1个至第n个结点依此向前移动一个位置。

      线性表长度减1。

    算法描述:

    ElemType Delete_SqList(Sqlist *L,int i)

      {   int k ; ElemType x ;

        if (L->length==0)

        { printf(“线性表L为空! ”); return ERROR; }

        else if ( i<1||i>L->length )

        { printf(“要删除的数据元素不存在! ”) ; return ERROR ; }

        else { x=L->Elem_array[i-1] ; /*保存结点的值*/

        for ( k=i ; k<L->length ; k++)

          L->Elem_array[k-1]=L->Elem_array[k]; /* i位置以后的所有结点前移 */

        L->length--; return (x);

        }

      }

    (4)插入和删除操作的时间复杂度:

      由于元素插入到第i个位置,或者删除第i个元素,需要移动第n-i个元素。根据概率原理,每个位置插入或者删除元素的可能性是相同的,也就是说位置靠前,

    移动元素多,位置靠后,移动元素少。最终平均移动次数和最中间的那个元素的移动次数相等,为(n-1)/2。因此,可以得出,平均时间复杂度还是O(n)。

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

    (1)优点:

      无须为表示表中元素之间的逻辑关系而增加额外的存储空间。

      可以快速的存取表中任意位置的元素。

    (2)缺点:

      插入和删除操作需要移动大量的元素。

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

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

  • 相关阅读:
    Java内存模型(JMM)
    线程安全问题的本质详解: 原子性、有序性、可见性
    Quartz实现分布式可动态配置的定时任务
    Java引用详解-StrongReference SoftReference WeakReference PhantomReference
    流行的报表生成工具-JXLS
    Java线程监控及中断
    IntelliJ IDEA 内存优化最佳实践
    Dapeng框架-开源高性能分布式微服务框架
    Scala实现Try with resources自动关闭IO
    Jvm启动,关闭及对应钩子
  • 原文地址:https://www.cnblogs.com/junjiang3/p/7822059.html
Copyright © 2020-2023  润新知