• 线性表顺序存储基本操作


    • 线性表的基本操作
     //线性表的基本操作
     /*
        Status,自定义的一个枚举类型,
        enum Status{
               success(成功),fail(失败),fatal(内存分配失败),range_error(连续空间访问失败越界) 
        } 
     */
     Status List_Init(SqListPtr L);//初始化线性表
     void List_Clear(SqListPtr L);//清空线性表
     void List_Destory(SqListPtr L);//销毁线性表 
     bool List_Empty(SqListPtr L);//判断线性表是否为空
     int List_Size(SqListPtr L);//线性表中元素的个数或线性表的长度
     Status List_Retrival(SqListPtr L,int pos,ElemType *elem);//在线性表L中的pos那个位置取出数据放在elem指针中
     Status List_Locate(SqListPtr L,ElemType elem,int *pos);//在线性表L中找出元素elem的位置放在pos指针中
     Status List_Prior(SqListPtr L,int pos,ElemType *elem);//在线性表L中求出pos那个位置元素的直接前驱放在elem指针中
     Status List_Next(SqListPtr L,int pos,ElemType *elem);//在线性表L中求出pos那个位置元素的直接后继放在elem指针中 
     //以上函数的参数是指针类型的,通常是指:我们希望通过函数所获得结果放到指针当中
     Status List_Insert(SqListPtr L,int pos,ElemType elem);//在线性表中插入一个元素
     Status List_Delete(SqListPtr L,int pos)://在线性表中删除一个元素 
    • 定义线性表结构体(空间分配,静态:数组;动态:指针)
     //定义线性表的结构体
     #define LIST_TNIT_SIZE 100 //线性表初始大小100
     #define LIST_INCREAMENT 10 //增量
     typedef int ElemType;
     typedef struct SqList{
         ElemType *elem;//elem指针,指向ElemType数据元素类型,连续存储空间的首地址的指针 
         int length=0;//线性表的长度,初始线性表的长度为0 
         int list_size;//线性表内存空间的大小 
     }SqList,*ptr;
     typedef ptr SqListPtr; 

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

    1、初始化—创建线性表

     //初始化,创建线性表
     Status List_Init(SqListPtr L){
         Status s=success;//状态初始假设是成功的
         L->list_size=LIST_INIT_SIZE;
         L->length=0;//没有数据元素,线性表的初始长度为0
         L->elem=(ElemType*)malloc(sizeof(ElemType)*L->list_size);
        if(L->elem==NULL)
             s=fatal;//内存分配失败,创建线性表失败 
         return s; //返回函数状态 
     } 

    2、线性表顺序存储结构上的查找(按位置查找值、按值查找位置)

    •  按位置查找值,首先确保位置是合法的,若查找成功,返回位置元素的详细信息,否则返回错误信息
     //按位置查找 
     Status List_Retrival(SqListPtr L,int pos,ElemType *elem){//查找在线性表pos位置的元素,放在elem指针中,该函数实现查找是否成功的状态信息 
         Status s=range_error;//假设初始状态,找不到,发生越界错误
        if(L){//如果线性表存在 
            if((pos-1)>=0&&(pos-1)<L->length){//判断位置的合法性,逻辑位置与实际位置差1 
                 *elem=L->elem[pos-1];//将查找pos位置的元素放在elem指针中
                 s=success//函数状态返回查找成功 
             }
         else
             s=fatal;//查找失败
         return s;//返回函数状态     
     } 
    • 按值查找位置,需要将线性表中的每一个元素进行比较,从第一个元素开始,一直比较到最后一个元素,时间复杂度根据差找的元素位置不同而有所,若查找的元素在线性表的前面,则查找速度快些,若在后面,则查找的速度慢些。
    //按值查找
    Status List_Locate(SqListPtr L,ElemType elem,int *pos){//找elem在线性表L当中的位置放在pos指针中 
        Status s=range_error;
        if(L){//如果线性表存在
            for(int i=0;i<L->length;i++){//对线性表中每一个元素和elem比较是否相等,如果相等则查找成功,否则查找失败 
                if(L->elem[i]==elem){
                    *pos=i+1;
                    s=success;
                    break;
                }
            } 
        }
        else
            s=fatal;//查找失败
        return s;//返回函数的状态 
    } 

    注:如果找到了就不找到需要再往后面找了,break跳出for循环,该按值查找的时间复杂度,最好的情况就是在第一个位置就找到,只需要比较1次,最坏的情况所查元素在最后一个或没有,需要比较n次,平均比较n/2次,时间复杂度是O(n)。

     3、线性表的顺序存储—插入操作

    • 检查插入位置是否合法,如果合法则继续,否则退出。
    • 判断表是否占满,因为事先分配空间,可能存在所分配的存储空间全部被占用的情况,此时也不能事先插入。
    • 若前面检查通过,则数据元素依次向后移动一个位置,为避免覆盖源数据,应从最后一个依次向前移动。
    • 新的数据元素放到恰当的位置。
    • 表长加1。
      //线性表的顺序存储—插入操作
      Status List_Insert(SqListPtr L,int pos,ElemType elem){//在线性表中pos位置插入新元素elem 
          Status s=range_error;
          if((pos-1)>=0&&(pos-1)<L->length-1){//如果插入位置合法 
              if(L&&L->length<L->List_Size){//如果线性表存在 
                  for(int i=L->length-1;i>=pos-1;i--)
                      L->elem[i+1]=L->elem[i];//从最后一个元素开始向后移动 
                   L->elem[pos-1]=elem;//将元素插入指定的pos位置
                   L->length++;//最后表长加1
                   s=success;
              }
          }
          else
              s=fail;//插入失败
          return s; //返回函数状态
      } 

    注:顺序表上实现插入操作需要移动表中一办的数据元素。时间复杂度为O(n),最坏的情况是在第一个元素插入(i=1),需要向后移动n个元素。这种顺序存储结构需要移动大量的数据元素,而每个数据元素可能是占据很大的内存空间,所以这种方法的效率是很低的。

    4、线性表的顺序存储—删除操作

    • 检查删除位置是否合法,同时判断线性表是否为空,因为空的线性表不能进行删除操作
    • 若检查通过,数据元素依次向前移动一个位置
    • 表长减1
    //线性表的顺序存储—删除操作
    Status List_Delete(SqListPtr L,int pos){//在线性表L中的pos位置删除元素 
        Status s=range_error;
        if((pos-1)>=0&&(pos-1)<L->length){//判断删除位置是否合法 
            if(L&&L->length>0){//判断线性表是否存在,且不为空 
                for(int i=pos-1;i<L->length;i++)
                    L->elem[i]=L->elem[i+1];//移动 
                L->length--;//表长减1 
                s=success;//修改状态 
            }
        }
        else
             s=fail;//删除失败
        return s; //返回函数状态
    } 

    注:插入和删除的基本操作就是移动数据元素,最好的情况下,删除最后一个,移动一个元素;最差的情况下,删除第一个元素,移动n-1个元素;平均情况下:删除第i个元素,需要移动第n-i个元素

    5、销毁线性表

    //销毁线性表
    void List_Destry(SqListPtr L){
        if(L->elem)
            free(L->elem);//释放指针 
        L->length=0;//表长置0 
    } 

    6、清空线性表

    void List_Clear(SqListPtr L){
        L->length=0;
    } 

    7、判断线性表是否为空

    //判断线性表是否为空
    bool List_Empty(SqListPtr L){
        if(L->length==0)
            return true;
        else
            return false;
    } 
    //或者用下面的函数也可以判断
    bool List_Empty(SqListPtr L){
        return L->length==0;
    } 

    8、求线性表的前驱

    Status List_Prior(SqListPtr L,int pos,ElemType *elem){//求线线表pos位置元素的前驱,将结果存放在elem指针中 
        Ststus s=fail;
        if(pos>=2&&pos<=L->length){//判断pos位置是否合法 
            *elem=L->elem[pos-2];
            s=success;
        }
        else
            s=fail;
        return s;
    }

    9、求线性表长度

    //求线性表长度
    int List_Length(SqListPtr L){
        return L->length;
    }

    10、求线性表的后继

    //求线性表的后继
    Status List_Next(SqListPtr L,int pos,ElemType *elem){//求线性表pos位置元素的后继,将结果存放在elem指针中 
        Status s=fail;
        if(pos>=1&&pos<L->length){//判断pos位置是否合法 
            *elem=L->elem[pos];
            s=successs; 
        }
        else
            s=fail;
        return s;
    } 
  • 相关阅读:
    数据更新
    MVC学习笔记
    const关键字同static readonly 的区别
    RSS
    C语言中取地址跟C++中的引用是一个意思吗?
    生产者消费者模式
    使用foreach的时候,不能对List进修改,怎么办?
    SQL查询
    Windows下的Java访问USB设备解决之道(翻译Java libusb / libusbwin32 wrapper)
    Java SE 6d新特性: 编译器 API
  • 原文地址:https://www.cnblogs.com/geziyu/p/9574449.html
Copyright © 2020-2023  润新知