顺序表相关概念

  • 顺序表:用一组地址连续的存储单元依次存储线性表的数据元素,是一种随机存取的存储结构
  • 存取结构:分为随机存取和非随机存取(又称顺序存取)

(1) 随机存取就是直接存取,可以通过下标直接访问的那种数据结构,与存储位置无关,例如数组。

非随机存取就是顺序存取了,不能通过下标访问了,只能按照存储顺序一个个访问,与存储位置有关,例如链表。

(2) 顺序存取就是存取第N个数据时,必须先访问前(N-1)个数据 (list)。

随机存取就是存取第N个数据时,不需要访问前(N-1)个数据,直接就可以对第N个数据操作 (array)。

  • 顺序表插入或删除元素时,元素可直接通过下标访问,时间主要耗费在移动元素上(即移动元素为时间复杂度的基本操作)

顺序表的表示与相关操作的实现

  • 顺序表的表示
#define LIST_INIT_SIZE 100//线性表储存空间的初始分配量
#define LISTINCREMENT 10//线性表储存空间的分配增量

typedef struct{
    ElemType *base;//储存空间的基地址
    int length;//顺序表的长度
    int listSize;//当前分配储存容量(以sizeof(elemtype)为单位)
}List;
  • 相关操作函数
Status InitList(List *L);
//线性表初始化
Status InsertElemIntoList(List *L,int i,ElemType e);
//插入元素
Status DeleteElemFromList(List *L, int i);
//删除元素
Status ModifyElem(List *L, int i, ElemType e);
//修改元素
ElemType GetElemfromList(List L, int i);
//根据下标得到元素
int IsLocalElem(List L, ElemType e);
//判断元素是否在线性表中
int GetElemIndex(List L, ElemType e);
//根据元素得到下标
Status ClearList(List *L);
//清空顺序表
Status DestroyList(List *L);
//销毁线性表
Status TraverseList(List L);
遍历线性表的元素
  • 线性表初始化
Status InitList(List *L){
    L->base=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
    if(!L->base){
        return OVERFLOW;
    }
    L->length=0;
    L->listSize=LIST_INIT_SIZE;
    return OK;
}
  • 插入元素
Status InsertElemIntoList(List *L,int i,ElemType e){
    if(i<1||i>L->length+1){
        return ERROR;
    }//检查i是否在线性表中
    if(L->length>=L->listSize){
        ElemType *newBase=(ElemType*)realloc(L->base,(L->listSize+LISTINCREMENT)*sizeof(ElemType));
        if(!newBase){
            return OVERFLOW;
        }
        L->base=newBase;
        L->listSize+=LISTINCREMENT;
    }//检查插入后储存空间是否足够
    ElemType *insert=&L->base[i-1];
    for(ElemType *p=&L->base[L->length-1];p>=insert;p--){
        *(p+1)=*p;
    }//把第i个元素及之后元素向后平移一位
    *insert=e;
    L->length++;
    return OK;
}

在平移时要注意为何写作(p+1)=p,与后边删除操作时的平移作比较

  • 删除元素
ElemType DeleteElemFromList(List *L,int i,ElemType &e){
    if(i<1||i>L->length){
        return ERROR;
    }
    ElemType *target;
    target=&L->base[i-1];
    e=*target;
    //以下是对指针取址取值的比较
    //e=target
    //*取值,啥也不带是地址
   // e=L->base[i-1];
   //&取址,啥也不带是值
   int count=0;
    for(ElemType *p=&L->base[L->length-1];p>=target;p--){
        *(target+count)=*(target+1+count);
        count++;
    }
    L->length--;
    return e;
}

比插入时比较可发现,插入时是从后往前平移,而删除时是从前往后平移

  • 修改元素
Status ModifyElem(List *L,int i,ElemType e){
    if(i<1||i>L->length){
        return ERROR;
    }
    L->base[i-1]=e;
    return OK;
}
  • 根据下标获取元素
Status GetElemfromList(List L,int i){
    if(i<1||i>L.length){
        return ERROR;
    }
    return L.base[i-1];
}
  • 检查元素是否在线性表中
Status IsLocalElem(List L,ElemType e){
    for(int i=0;i<L.length;i++){
        if(L.base[i]==e){
            return 1;
        }
    }
    return 0;
}
  • 根据元素获取下标
Status GetElemIndex(List L,ElemType e){
    for(int i=0;i<L.length;i++){
        if(L.base[i]==e){
            return i+1;
        }
    }
    return 0;
}
  • 清空顺序表

Status ClearList(List *L){
    for(int i=0;i<L->length;i++){
        L->base[i]=0;
    }
    L->length=0;
    return OK;
}
  • 销毁顺序表

Status DestroyList(List *L){
    free(L->base);
    L->length=0;
    L->listSize=0;
    L->base=NULL;
    return OK;
}
  • 遍历线性表中的元素
Status TraverseList(List L){
    for(int i=0;i<L.length;i++){
        printf("The %dth elem is %d:",i+1,L.base[i]);
    }
    return OK;
}
关注公众号,让我们携手共进0.5.jpg

无欲则刚
76 声望15 粉丝