线性表的顺序表示及实现

线性表的定义和特点

1. 定义

线性表(Linear List):由n(n>=0)个具有相同特性的数据元素(结点)a1,a2, … , 组成的有限序列。

  • 其中数据元素的个数n定义为表的长度;
  • 当n = 0 时称为空表;
  • 将非空的线性表(n>0)记作:(a1 , a2 , … , an)
  • 这里的数据元素ai(1 <= i <= n)只是一个抽象的符号,其具体含义在不同的情况下可以不同。
2.线性表的逻辑特征
  1. 在非空的线性表中,有且仅有一个开始结点a1,它没有直接前趋,而仅有一个直接后继;
  2. 有且仅有一个终端结点a1,它没有直接后继,而仅有一个直接前趋a n-1
  3. 其余的内部结点ai(2 <= i <= n-1)都有且仅有一个直接前趋a n-1和一个直接后继a n+1
  4. 线性表是一种典型的线性结构

抽象数据类型线性表的定义如下:

ADT List{
	数据对象 : D = {a[i] | a[i]属于Element,(i=1,2,...,n)}
	数据关系 : R = {<a[i-1],a[i]> | a[i-1],a[i]属于D,(i=1,2,...,n)}
	基本操作 :
	 InitList(&L);       DestroyList(&L);
	 ListInsert(&L,i,e);   ListDelete(&L,i,&e);
	 ......等等
}ADT List

线性表的顺序表示

逻辑相邻的数据元素存储在物理上相邻存储单元中的存储结构。知道某个元素的存储位置就可以计算出其他元素的存储位置。
假设线性表的每个元素需占 l 个存储单元,则第i+1个数据元素的存储位置和第i个数据元素的存储位置之间满足关系:
Loc(ai+1) = Loc(ai) + l
由此,所有数据元素的存储位置均可由第一个数据元素的存储位置得到
Loc(ai) = Loc(a1) + (i +1) x l

顺序表的元素地址连续、依次存放、随机存取、类型相同,所以可用数组来表示顺序表; 线性表的长度可变,因此用一变量表示顺序表的长度属性。

#define LIST_INIT_SIZE 100    //线性表存储空间的初始分配量
typedef struct {
	ElemType elem[LIST_INIT_SIZE ];
	int length;    //当前长度
}

例如,多项式的顺序存储结构类型定义为:
pn(x) = p1(x)xe1 + p2(x)xe2 + … + pm(x)xem,
线性表 P = ( (p1,e1) , (p2,e2) , … , (pm,em) );

#define MAXSIZE 1000    //多项式可能达到的最大长度

typedef struct {    //多项式非零项的定义
	float p;        //系数
	int e;          //指数
}Polynomial;

typedef struct {
	Polynomial *elem;        //存储空间的基地址
	int length;              //多项式中当前项的个数
}SqList;                     //多项式的顺序存储结构类型为SqList

顺序表的基本实现

1. 线性表L的初始化

Status initList_Sq(SqlList &L){          //构造一个空的顺序表L
	L.elem = new ElemType[MAXSIZE];      //为顺序表分配空间
	if(!L.elem)                          //存储空间分配失败
		return;
	L.length = 0;                        //空表长度为0
	return;
}

2. 销毁顺序表L

void DestroyList(SqList &L){
	if(L.elem)
		delete L.elem;         //释放存储空间
}

3. 清空顺序表L

void ClearList(SqList &L){
	L.length = 0;              //将线性表的长度置为0
}

4. 求线性表L的长度

int DestroyList(SqList L){
	return L.length;

5. 判断线性表是否为空

int IsEmpty(SqList L){
	if(L.length == 0) return 1;
	else return 0;
}

6. 顺序表的求值(根据位置i获取相应位置数据元素的内容)

int GetElem(SqList L,int i,ElemType &e){
	if(i<1||i>L.length)
		return ERROR;       //判断i值是否合理,若不合理,返回ERROR
	e = L.elem[i-1];        //第i-1的单元存储着第i个数据
	return OK;
}

7. 顺序表的查找

算法思想:

  • 在线性表L中查找与指定e相同的数据元素的位置
  • 从表的一段开始,逐个进行记录的关键字和给定值的比较。找到,返回该元素的位置序号,未找到,返回0。
int LocateElem(SqList L,Element e){
//在线性表L中查找值为e的数据元素。返回其序号(是第几个元素)
	for(i=0li<L.length;i++)
		if(L.elem[i] == e) return i+1;   //查找成功,返回序号
	return 0;                  //查找失败,返回0
}

顺序表的查找算法分析:

平均查找长度ASL(Average Search Length):
为确定记录在表中的位置,需要与给定值进行比较的关键字的个数的期望值(平均值)叫做查找算法 的平均查找长度。

对含有n个记录的表,查找成功时:
在这里插入图片描述
其中,Pi为找到第i个记录需要比较的次数。Ci为第i个记录被查找的概率。
顺序查找的平均查找长度:
ASL=P1 + 2P2 + … + (n-1)Pn-1 + nPn,
假设每个记录的查找概率相等:
则:在这里插入图片描述由此,得顺序表查找的时间复杂度为O(n) ~ n

8. 顺序表的插入
线性表的插入运算是指在表的第i个位置上,插入一个新结点e,使长度为n的线性表(a1,… ,ai-1,ai,…,an)变成长度为n+1的线性表(a1,… ,ai-1, e ,ai,…,an)。

算法思想:

  • 判断插入位置i是否合法,
  • 判断顺序表的存储空间是否已满,
  • 将第n至第i位的元素依次向后移动一个位置,空出第i个位置,
  • 将要插入的新元素e放入第i个位置,
  • 表长加1。
Status ListInsert_Sq(SqList &L,int i,ElemType e){
	if(i<1||i>L.length) return;   //i值不合法
	if(L.length == MAXSIZE) return;   //当前存储空间已满
	for(j=L.length-1;j>=i-1;j++){
		L.emel[j+1] = L.elem[j];      //插入位置及之后的元素后移
	}
	L.elem[i-1]=e;                   //将新元素e放入第i个位置
	L.length++;                      //表长加1
	return;
}

在这里插入图片描述
9. 顺序表的删除
线性表的删除操作运算是指将表的第i个结点删除,使长度为n的线性表(a1,… ,ai-1,ai,ai+1…,an)变成长度为n-1的线性表(a1,… ,ai-1, ai+1,…,an)。

算法思想:

  • 判断删除位置i是否合法,
  • 将欲删除的元素保留在e中,
  • 将第i+1至第n位的元素依次向前移动一个位置,
  • 表长减1,删除成功。
Status ListDelete_Sq(SqList &L,int i){
	if(i<1||i>L.length) return;   //i值不合法
	for(j=i;j<=L.length-1;j++){
		L.emel[j-1] = L.elem[j];      //被删除元素之后的元素前移
	}
	L.length--;                      //表长加1
	return;
}

总结

顺序表的优缺点:
优点:

  • 存储密度大(结点本身所占存储量/结点结构所占存储量)
  • 可以随机存取表中任一元素

缺点

  • 在插入、删除某一元素时,需要大量移动元素
  • 浪费存储空间
  • 属于静态存储形式,数据元素的个数不能自由扩充
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. 顺序存储结构中数据中数据元素之间逻辑关系是由( )表示的,链接存储结构中的数据元素之间的逻辑关系是由( )表示的。 A.线性结构 B.非线性结构 C.存储位置 D.指针 2. 线性表是( )。 A.一个有限序列,可以为空 B. 一个有限序列,不能为空 C. 一个无限序列,可以为空 D. 一个无限序列,不能为空 3. 已知一维数组A采用顺序存储结构,每个元素占用4个存储单元,第9个元素的地址为144,则第一个元素的地址是( )。 A. 108 B. 180 C. 176 D. 112 4. 在单链表中删除指针p所指结点的后继结点,则执行( )。 A. p->next= p->next->next B. p->next= p->next C. p= p->next->next D. p= p->next; p->next= p->next->next 5. 若某链表最常用的操作是在最后一个结点之后插入一个结点删除最后一个结点,则采用( )存储方式最节省时间。 A. 单链表 B. 双链表 C. 带头结点的双循环链表 D. 单循环链表 6.二维数组A[7][8]以列序为主序的存储, 计算数组元素A[5][3] 的一维存储空间下标 k=( )。 A. 38 B. 43 C. 26 D. 29 二、完成下列填空题(每空3分,共9分)。 1.在顺序表L中第i个位置上插入一个新的元素e: Status ListInsert_Sq(SqList &L , int i , ET e){ if ( iL.length+1) return ERROR; if(L.length >= L.listsize){ p=(ET*)realloc(L.elem,(L.listsize+10)*sizeof(ET)); if (p==NULL) exit(OVERFLOW); L.elem=p; } for( j=L.length ; j>=i ; --j ) L.elem[j]=L.elem[j-1] ; L.elem[j]=e ; ++L.length ; return OK; } 2. 删除双向链表中p所指向的节点算法: status delete(DuLinkList L, DuLinkList p) { if (p= =L) return ERROR; else { p->prior->next=p->next; p->next->prior=p->prior ; } free(p); return OK; } 三、编程题(共27分)。 1. (共12分)用顺序表表示集合,设计算法实现集合的求差集运算,要求不另外开辟空间。 顺序表的存储结构定义如下: #define Maxsize 100 typedef struct { ElemType data[MaxSize]; // ElemType表示不确定的数据类型 int length; // length表示线性表的长度 }SqList; 将如下函数,伪码补充完整(8分),代码前先用文字描述自己的算法思想(4分)。 文字描述算法:略(4分) void Difference(SqList A, SqList B) {//参考代码如下如下(8分) for (i=0;i<A.length;i++) for(j=0;j<B.length;j++) if(A.data[i]==B.data[j]) { A.data[i]=’#’; break; } for (k=0,i=0;inext == L) return; p = L; while (p->next != L)   { if (p->next->data != e) P = p->next; else { q = p->next;p->next = q->next; free(q);} } } 时间复杂度分析:(2分) 时间复杂度为O(n)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1 + 1=王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值