线性表顺序存储结构

目录

线性表的定义

线性表抽象数据结构定义

线性表的顺序存储结构

顺序存储结构的插入与删除

插入操作

删除操作

顺序存储结构的优点和缺点

代码

main.c

List.c

List.h


 


线性表的定义

线性表(List): 零个或者多个数据元素的有限序列

注意: 序列说明元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有,且只有一个前驱和后继,

是有限的,事实上,计算机处理的对象都是有限的

线性表抽象数据结构定义

前面给出了线性表的定义,现在分析一下线性表应该有哪些操作:

首先线性表中的元素类型都是一样的,

对表进行操作那首先得创建表, 没有元素就是空表,然后往里边填数据元素-初始化, 有些数据需要查找,有些不合适需要删除,也可以往里边增加数据

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

ADT线性表(List)

Data

线性表中的数据对象集合为{a1,a2,....,an},每个数据元素的类型均为DataType.其中除了第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个后继元素.数据元素之间的关系是一对一的关系

Operation

InitList( *L ): 初始化操作,建立一个空的线性表L

ListEmpty(L): 若线性表为空,返回ture, 否则返回false

ClearList(*L): 将线性表清空

GetElem(L, i, *e): 将线性表L中的第i个元素值返回给e

LocateElem(L, e): 在线性表中查找与给定值e相等的元素,若查找成功返回该元素在表中的序号表示成功;否则返回0表示失败

ListInsert(*L, i, e): 线性表中L中第i个位置插入新元素e

ListDelet(*L, i, *e): 删除线性表中第i个位置元素,并用e返回其值

ListLengeh(L): 返回线性表L的元素个数

endADT

 

线性表的顺序存储结构

上面介绍了线性表的抽象数据类型,现在介绍一下其俩种物理结构中的第一种--顺序存储结构

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素,线性表的顺序存储示意如下:

从上面的示意图可以看出,线性表的顺序存储结构,其实就是一个一维数组,在内存中找块地儿,通过占位的形式,把一定的内存空间给占了,然后将相同的数据元素依次存放在这块空地中,

那么我们可以给出线性表的顺序存储的结构代码:

#define MAXSIZE 20 //存储空间的初始分配量 typedef int ElemType; //ElemType是线性表中元素的类型 typedef struct { ElemType data[MAXSIZE]; //数据存储结构元素,最大空间为MAXSIZE int length; //线性表当前长度 }SqList;

这里可以发现顺序存储结构需要三个属性:

  • 存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置

  • 线性表的最大存储容量: 数组长度MAXSIZE

  • 线性表当前长度: length

数据元素和存放它的数组下标之间存在对应关系.如下图

用数组存储顺序意味着要分配固定长度的数组空间,由于线性表中可以进行插入和删除操作,于是分配的数组空间是要大于等于当前线性表的长度

存储器中的每个存储单元都有自己的编号,这个编号称为地址,之间有如下关系(LOC表示获得存储位置的函数)

LOC(ai+1) = LOC(ai) + c

LOC(ai) = LOC(a1) + (i-1)*c

通过这个公式可以随意算出线性表中任意位置的地址,而且都是相同的时间,无论在线性表中存入还是取出数据,从时间复杂度来说就是O[1], 对于这种时间复杂度是O[1]的存储结构称为随机存取结构

 

顺序存储结构的插入与删除

对于线性表的顺序存储结构来说,如果要实现GetElem操作,只需将其第i个位置元素值返回,也就是下标是i-1的值返回就可:

#define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef int Status; /* Status是函数的类型,其值是函数结果状态的代码 */ /* 初始条件: 顺序线性表L已存在,1<=i<=Length */ /* 操作结果: 用e返回L中第i个数据元素的值 */ Status GetElem(SqList L, int i, ELemType *e) { if(L.length == 0 || i<1 || i>L.length) return ERROR; *e = L.data[i-1]; return OK; }

插入操作

ListInsert

思路:

  • 由于需要对线性表进行操作,所以需要进行指针操作

  • 如果插入位置不合理,输出异常

  • 如果线性表当前长度大于等于数组长度,输出异常,或者动态增加容量

  • 从最后一个元素开始遍历到第i个位置,分别将他们都向后移动一个位置

  • 将要插入的元素填入位置i中

  • 表长+1

代码在后面

删除操作

ListDeldte

思路:

  • 如果删除位置不合理,输出异常

  • 取出删除元素

  • 从删除元素位置开始遍历到最后一个元素的位置,分别将他们都向前移动一个位置

  • 表长+1

平均操作次数:(n-1)/2 插入和删除时间复杂度: O[n]

存,读时间复杂度:O[1]

由此可见顺序线性表比较适合元素个数不怎么变化,而更多是存取数据的应用

顺序存储结构的优点和缺点

  • 优点:

1. 无须为表示表中之间的罗技关系而增加额外的存储空间

2. 可以快速得存取表中任一位置的元素

  • 缺点

1. 插入和删除操作需要移动大量的数据

2. 当线性表长度变化较大时候,难以缺点存储空间的容量

代码

main.c

/* main.c */
#include <stdio.h>
#include "List.h"

int main()
{
	ElemType a,b,c;
	int g,i,d;
	SqList L = {{1,2,3,4,5,6},6};
	
	ScanList(L);
	/* 查询一个线性表单元 */
	printf("Get_number: ");
	scanf("%d", &g);
	GetELem(L, g, &a);
	printf("Get_Elem : %d\n",a);
	/* 插入一个线性表单元 */ 
	printf("Insert_number:");
	scanf("%d", &i);
	printf("Insert_data:");
	scanf("%d", &b);
	ListInsert(&L, i, b);
	ScanList(L);
	/* 删除一个线性表单元 */
	printf("Delete_number:");
	scanf("%d", &d);
	ListDelete(&L, i, &c);
	ScanList(L);
	printf("delete data: %d\n", c);
	return 0;
 } 


List.c

/* List.c */
#include <stdio.h>
#include "List.h"

/* 从线性表L中取出第i个元素,并用e返回 */
Status GetELem(SqList L, int i, ElemType *e)
{
	if(L.length==0 || i<1 ||i>L.length)
		return ERROR;
	*e = L.data[i-1];
	return OK;
}

/* 遍历一个线性表L */
void ScanList(SqList L) 
{
	int i;
	for(i=0; i<L.length; i++)
		printf("%d\n",L.data[i]);
}
/* 从线性表L中第i个位置之前插入数据元素e */
Status ListInsert(SqList *L, int i, ElemType e) 
{
	int k;
	if(L->length == MAXSIZE) return ERROR;
	if(i<1 || i>L->length+1) return ERROR;
	if(i<=L->length)
	{
		for(k=L->length-1; k>=i-1; k--)
			L->data[k+1] = L->data[k];
	}
	L->data[i-1] = e;
	L->length++;
	return OK; 
}
/* 从线性表L中第i个位置删除数据元素,用e返回其值 */
Status ListDelete(SqList *L, int i, ElemType *e) 
{
	int k;
	if(L->length == 0) return ERROR;
	if(i<1 || i>L->length+1) return ERROR;
	*e = L->data[i-1];
	if(i<=L->length)
	{
		for(k=i; k<=L->length; k++)
			L->data[k-1] = L->data[k];
	}
	L->length--;
	return OK; 
}

List.h

#ifndef _LIST_H_
#define _LIST_H

#define MAXSIZE 20
#define OK 1
#define ERROR 0
#define TURE 1
#define FALSE 0

typedef int Status;
typedef int ElemType; 
typedef struct
{
	ElemType data[MAXSIZE];
	int length;
}SqList, *pSqList;

Status GetELem(SqList L, int i, ElemType *e);
void ScanList(SqList L);
Status ListInsert(SqList *L, int i, ElemType e);
Status ListDelete(SqList *L, int i, ElemType *e);


#endif 

输出结果如下:

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值