线性表类型的实现——顺序映象

线性表的顺序映像

含义:用一组地址连续的存储单元依次存放线性表中的数据元素

a 1 a_1 a1 a 2 a_2 a2 … \dots a i − 1 a_{i-1} ai1 a i a_i ai … \dots a n a_n an

a 1 a_1 a1是线性表的起始地址,称作线性表的基地址

  • 以“存储位置相邻”表示有序对< a i − 1 , a i a_{i-1},a_i ai1,ai>,即: L O C ( a i ) = L O C ( a i − 1 ) + C LOC(a_i)=LOC(a_{i-1})+C LOC(ai)=LOC(ai1)+C其中C为一个数据元素所占的存储量。

  • 所有元素的位置取决于第一个数据元素的存储位置: L O C ( a i ) = L O C ( a 1 ) + ( i − 1 ) × C LOC(a_i)=LOC(a_1)+(i-1)\times C LOC(ai)=LOC(a1)+(i1)×C其中 L O C ( a i ) LOC(a_i) LOC(ai)为基地址

顺序映像的C语言描述
#define LIST_INIT_SIZE  80  //线性表存储空间的初始分配量
#define LISTINCREMENT   10  //线性表存储空间的分配增量
typedef struct{
  ElemType *elem;  //存储空间基址
  int length;  //当前长度
  int listsize;  //当前分配的存储容量
}Sqlist; //顺序表
线性表的初始化操作
Status InitList_Sq(SqList&L){
  //构造一个空的线性表
  L.elem = (ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
  if(!L.elem) exit(OVERFLOW);
  L.length = 0;
  L.listsize = LIST_INIT_SIZE
  return OK;
}// InitList_Sq
线性表操作LocateElem(L,e,compare())的实现:
int LocateElem_Sq(SqList L, ElemType e,
  Status(*compare)(ElemType, ElemType)){
  // 时间复杂度为O(表长)
    i = 1;   //i的初值为第1元素的位序
    p = L.elem;   //p的初值为第一元素额存储位置
    while(i<=L.length && !(*compare)(*p++, e)) ++i;
    if(i<=L.length) return i;
    else return 0;
  }//LocateElem_Sq
线性表操作ListInsert(&L,i,e)的实现:
  • 插入元素时,线性表的逻辑关系发生了什么变化?
    ( a 1 , … , a i − 1 , … , a n ) (a_1,\dots,a_{i-1},\dots,a_n) (a1,,ai1,,an)改变为 ( a 1 , … , a i − 1 , e , a i … , a n ) (a_1,\dots,a_{i-1},e,a_i\dots,a_n) (a1,,ai1,e,ai,an)
    e前面的元素不变,后面的元素后移,表的长度增加1
Status ListInsert_Sq(SqList &L, int pos,ElemType e){
//时间复杂度为O(ListLength(L))(最坏情况)
if(pos<1 || pos>L.length+1) return ERROR; //输入位置不合法
  if(L.length>=L.listsize){  //当前存储空间已满,增加分配
    newbase = (ElemType *)realloc(L.elem,(L.liatsize+LISTINCRMENT)*sizeof(ElemType);
    if(!newbase) exit(OVERFLOW);  //存储分配失败
    L.elem = newbase;   //新基址
    L.listsize = LISTINCREMENT;  //增加存储容量
  }
  q = &(L.elem[pos-1]);  //q指示插入位置
  for(p=&(L.elem[L.length-1]);p>=q; --p)
    *(p+1)=*p;  //插入位置及之后的元素右移
    *q = e;  //插入e
    ++L.length;  //表长增1
    return OK;
}//ListInsert_Sq
  • 最坏情况下时间复杂度为O(ListLength(L))
  • 考虑平均的情况:
    假设在第i个元素之前插入的概率为 p i p_i pi,则在第i个元素之前插入需移动的次数为n-i+1,则在长度为n的线性表中插入一个元素所需移动元素次数的期望值为: E = ∑ i = 1 n + 1 p i ( n − i + 1 ) E=\sum_{i=1}^{n+1}p_i(n-i+1) E=i=1n+1pi(ni+1)
    若假定在线性表中任何一个位置上进行插入的概率都是相等的,则移动元素的期望值为 E = 1 n + 1 ∑ i = 1 n + 1 ( n − i + 1 ) = n 2 E=\frac{1}{n+1}\sum_{i=1}^{n+1}(n-i+1)=\frac{n}{2} E=n+11i=1n+1(ni+1)=2n
线性表操作Listelete(&L,i,&e)的实现:
  • 删除元素时,线性表的逻辑结构发生了什么变化?
    ( a 1 , … , a i − 1 , a i , a i + 1 , … , a n ) (a_1,\dots,a_{i-1},a_i,a_{i+1},\dots,a_n) (a1,,ai1,ai,ai+1,,an)改变为 ( a 1 , … , a i − 1 , a i + 1 , … , a n ) (a_1,\dots,a_{i-1},a_{i+1},\dots,a_n) (a1,,ai1,ai+1,,an)
    被删除元素之前的数据元素不变,后面的元素前移
Status ListDelete_Sq(SqList &L, int pos, ElemType &e){
  if((pos<1)||(pos>L.length)) return ERROR;  //删除位置不合法
  p = &(L.elem[pos-1])  //p设为被删除元素的位置
  e = *p;   //被删除元素的值赋给e
  q = L.elem+L.length-1   //表尾元素的位置
  for(++p; p<=q; ++p)   *(p-1) = *p;  //被删除元素之后的元素左移
  --L.length;   //表长减1
  return OK;
}//ListDelete_Sq
  • 算法的时间复杂度为O(ListLength(L))
  • 考虑平均的情况:
    假设删除第i个元素的概率为 q i q_i qi,则在长度为n的线性表中删除一个元素所需移动元素次数的期望值为: E d l = ∑ i = 1 n q i ( n − i ) E_{dl}=\sum_{i=1}^nq_i(n-i) Edl=i=1nqi(ni)
    若假定在线性表中任何一个位置上进行删除的概率是相等的,则移动元素的期望值为: E d l = 1 n ∑ i = 1 n ( n − i ) = n − 1 2 E_{dl}=\frac{1}{n}\sum_{i=1}^n(n-i)=\frac{n-1}{2} Edl=n1i=1n(ni)=2n1
顺序表的优缺点
  • 优点:可以对每个数据元素进行随机存取,表长是显值
  • 缺点:在进行元素插入或删除时要进行数据元素的移动,每次大致要移动表的一般的元素
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值