--------顺序表的定义

       线性表的顺序存储又称为顺序表。它是用一组地址连续的存储单元,依次存储线性表中的数据元素,

从而使得逻辑上相邻的两个元素在物理位置上也相邻。第 1 个元素存储在线性表的起始位置,第 i 个元素

元素的存储位置后面紧接着存储的是第  i + 1 个元素。因此,顺序表的特点是表中元素的逻辑顺序与其物理

顺序相同。

      假设线性表 L 存储的起始位置为 LOC(A) ,sizeof(ElemType) 是每个数据元素所占用存储空间的大小,

则表 L 所对应的顺序存储如下图:

      线性表的顺序表示 

      注意:线性表中的位序是从 1 开始的,而数组中元素的下标是从 0 开始的。

      -----------------------------------------------------------------------------------------------------

      假定线性表的元素类型为 ElemType ,线性表的顺序存储类型描述为:

       # define MaxSize 50                       // 定义线性表的最大长度

       typedef struct{

                ElemType    data[MaxSize] ;    // 顺序表的元素

                int   length ;                           // 顺序表的当前长度

      } SqList ;                                         // 顺序表的类型定义

     ----------------------------------------------------------------------------------------------------

       一维数组可以是静态分配的,也可以是动态分配的。在静态分配时,由于数组大小和空间

 事先已经固定,一旦空间占满,再加入新的数据将产生溢出,就会导致程序崩溃。

        而动态分配时,存储数据的空间是在程序执行过程中通过动态分配语句分配的,一旦数据

 空间占满,可以另外开辟一块更大的存储空间,用以替换原来的存储空间,从而达到扩充存储

 数组空间的目的,而不需要一次性地划分所有所需要空间给线性表。

      ----------------------------------------------------------------------------------------------------------

       #define InitSize 100

      typedef struct {

           ElemType   *data ;                     // 指示动态分配数组的指针

           int  MaxSize , length ;               // 数组的最大容量和当前个数

      }SeqList;                                      // 动态分配数组顺序表的类型定义

      -----------------------------------------------------------------------------------------------------------

     C 的初始动态分配语句为:

     L.data = (ElemType *)malloc( sizeof(ElemType) * InitSize );

    C++ 的初始动态分配语句为:

    L.data = new ElemType[InitSize] ;

    注意:动态分配并不是链式存储,同样还是属于顺序存储结构,其物理结构没有变化,依然是

  随机存取方式, 只是分配的空间大小可以在运行时决定。

 

     顺序表最主要的特点是:随机访问,即通过首地址和元素序号可以再O(1) 时间内找到指定的元素。

     顺序表的存储密度高,每个结点只存储数据元素。

    顺序表逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素。

 

-------------顺序表上基本操作的实现

   这里仅给出顺序表的插入操作删除操作按值查找的算法。

   (1)、插入操作

        在顺序表 L 的第 i (1 <=  i <= L.length+1) 个位置插入新元素 e 。如果 i 的输入不合法,则返回

false ,表示插入失败;否则,将顺序表的第 i 个元素以及其后的所有元素右移一个位置,腾出一个空位置

插入新元素 e ,顺序表长度增加 1 ,插入成功,返回 true 。

        ----------------------------------------------------------------------------------------------------------------------------------------

        bool  ListInsert( SqList   &L  , int i , ElemType e){

             // 本算法实现将元素 e 插入到顺序表 L 中第 i 个位置

             if ( i < 1 || i > L.length +1 ){           //  判断 i 的范围是否有效

                    return  false;

            }

            if ( L.length >= MaxSize ){           // 当前存储空间已满,不能插入

                    return  false;

           }

          for( int j = L.length ; j >= i : j--){      //将 第 i 个元素及之后的元素后移

               L.data[ j ] = L.data[ j-1 ] ;

          }

         L.data[ i -1 ] = e;                           // 在位置 i 处放入 e

         L.length++;                                  // 线性表的长度 加 1

         return true;

       }

----------------------------------------------------------------------------------------------------------------------------------------

      注意:区别顺序表的位序和数组下标。理解为什么判断插入位置是否合法时 if 语句中用 length +1 ,

     而移动元素的 for 语句只用 length ?

     《

         最好情况:在表尾插入(即 i = n + 1 ),元素后移动语句将不执行,时间复杂度为 O(1) 。

         最坏情况:在表头插入(即 i = 1 ),元素后移动语句将执行 n 次,时间复杂度为 O( n ) 。

        平均情况:假设 P(i)(P(i) = 1 / (n +1)) 是在第 i 个位置上插入一个结点的概率,则在长度为

                        n 的线性表中插入一个结点时所需移动结点的平均次数为:

                        线性表的顺序表示

         因此,线性表插入算法的平均时间复杂度为 O( n )

     》

 

(2)、删除操作

   删除顺序表 L 中第 i (1 <= i <= L.length)个为位置的元素,成功则返回 true ,并将被删除的元素用引

 用变量 e 返回,否则返回 false 。

   ----------------------------------------------------------------------------------------------------------------------------------------------

     bool  ListDelete( SqList  &L , int i , int  &e ) {

        // 本算法实现删除顺序表 L 中第 i 个位置的元素

            if( i < 1 || i > L.length ){                     // 判断 i 的范围是否有效

                 return false ; 

             }

           e = L.data[ i -1 ] ;                             // 将被删除的元素赋值给 e

           for( int j = i ; j < L.length ; j++ ){         // 将第 i 个位置之后的元素前移

                L.data[ j -1 ] = L.data[ j ]

           }

           L.length--;                                       // 线性表的长度减 1

           return true;

     }

-----------------------------------------------------------------------------------------------------------------------------------------------

   《

       最好情况:删除表尾元素(即 i = n),无须移动元素,时间复杂度为 O(1)。

       最坏情况:删除表头元素(即 i = 1),需要移动一个元素外的所有元素,时间复杂度为 O(n) 。

       平均情况:假设 P(i) (P(i) = 1 / n) 是删除第 i 个位置上结点的概率,则在长度为 n 的线性表中

                       删除一个结点所需移动结点的平均次数为:

       线性表的顺序表示

           因此,线性表删除算法的平均时间复杂度为 O( n ) 。  

 

(3)、按值查找(顺序查找)

          在顺序表 L 中查找第一个元素值等于 e 的元素,并返回其位序。

       ----------------------------------------------------------------------------------------------------------------------------

          int  LocateElem( SqList  L  , ElemType e){

          // 本算法实现查找顺序表中值为  e 的元素,如果查找成功,返回元素位序,否则返回 0

                 int i ;

                 for( i = 0 ; i < L.length ; i++){

                       if( L.data[ i ] == e){

                            return  i +1 ;                     // 下标为 i 的元素值等于 e ,返回其位序 i + 1

                      }

                     return  0;                                     //退出循环,说明查找失败

                }

         }

     -----------------------------------------------------------------------------------------------------------------------------------

    《

            最好情况:查找的元素就在表头,仅需比较一次,时间复杂度为 O(1) 。

            最坏情况:查找的元素在表尾(或不存在)时,需要比较 n 次,时间复杂度为 O(n)。

            平均情况:假设 P(i) (P(i) = 1 / n )是查找的元素在第 i (1 <= i <= L.length)额个位置上的

                            概率,则在长度为 n 的线性表中查找值为 e 的元素所需比较的平均次数为:

              线性表的顺序表示

              因此,线性表按值查找算法的平均时间复杂度为 O(n) 。

      》

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相关文章:

  • 2021-08-19
  • 2021-10-23
  • 2021-04-26
  • 2021-09-17
猜你喜欢
  • 2021-06-14
  • 2021-12-18
  • 2021-04-25
  • 2021-10-15
  • 2018-08-22
  • 2022-02-10
  • 2021-10-12
相关资源
相似解决方案