线性表顺序存储结构

线性表顺序存储结构

顺序存储结构:指的是用一段地址连续的存储单元一次存储线性表的数据元素。(理解成一维数组,既把第一个数据元素存到数组下表为0的位置中,接着把线性表相邻的元素存储在数组中相邻的位置)。

 

一、结构

#define MAXSIZE 20//存储空间初始化分配量
typedef int ElemType;//此处可能是个结构体,练习使用int型足够了
typedef struct
{
	ElemType data[MAXSIZE];//数组存储数据元素,最大存储量MAXSIZE
	int length;//链表长度
}SqList;

描述线性表顺序存储结构需要三个属性:

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

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

3. 线性表的当前长度:length

注意:数组的长度是存放线性表的存储空间的长度,存储分配后这个量是一般是不变的。线性表的长度是线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是变化的。在任意时刻,线性表的长度应该小于等于数组的长度。


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

二、线性表顺序存储插入操作


算法思路:

1. 如果插入位置不合理,抛出异常;

2. 如果线性表长度大于等于数组长度,则抛出异常或动态增加容量;

3. 从最后一个元素向前遍历到第i个位置,分表将他们都向后移动一个位置;

4. 将要插入元素填入位置i处;

5. 链表长度加1

三、线性表顺序存储删除操作


算法思路:

1. 如果删除位置不合理,抛出异常;

2. 取出删除元素;

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

4. 链表长度减1

四、时间复杂度

线性表的顺序存储结构,在存、读数据是,不管是哪个位置,时间复杂度都是O(1);而插入或删除是时间复杂度都是O(n)。说明它比较适合元素个数不太变化,而更多是存取数据的应用。

五、优缺点

优点

缺点

1. 无须为表示表中元素之间的逻辑关系而增加额外的存储空间;

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

1. 插入和删除操作需要移动大量元素;

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

3. 造成存储空间的“碎片”

 

六、代码示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define OK 1
#define ERROR 0

#define MAXSIZE 20//存储空间初始化分配量
typedef int ElemType;//此处可能是个结构体,练习使用int型足够了
typedef struct
{
	ElemType data[MAXSIZE];//数组存储数据元素,最大存储量MAXSIZE
	int length;//链表长度
}SqList;

//初始化操作,建立一个空的线性表L
void InitList(SqList *L);
//若线性表为空返回TRUE,否则返回FALSE
int ListEmpty(SqList L);
//将线性表清空
void ClearList(SqList *L);
/*在线性表L中查找给定值e相等的元素,
  *如果查找成功返回该元素在表中序号
  *表示成功;否则,返回0表示失败。
*/
int LocateElem(SqList *L,ElemType e);

//返回线性表L的元素个数
int ListLength(SqList *L);

//初始条件:顺序表L已经存在,1=<i=<ListLength(L)
//操作结果:用e返回L中第i个数据元素的值
int GetElem(SqList *L,int i,ElemType *e);
//初始条件:顺序表L已经存在,1=<i=<ListLength(L)
//操作结果:删除L中第i个位置的数据元素,并用e返回其值,L的长度减1
int ListDelete(SqList *L,int i,ElemType *e);
//初始条件:顺序表L已经存在,1=<i=<ListLength(L)
//操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
int ListInsert(SqList *L,int i,ElemType e);

/*将所有的在线性表Lb中但是不在La中的元素插入到La中*/
void swapList(SqList *La,SqList *Lb);

int ListPrint(SqList *L);


//初始化操作,建立一个空的线性表L
void InitList(SqList *L)
{
	memset(L,0,sizeof(SqList));
}
//若线性表为空返回TRUE,否则返回FALSE
int ListEmpty(SqList L)
{
	if(0 == L.length)
	{
		printf("[%s %d]链表为空\n",__FUNCTION__,__LINE__);
		return ERROR;
	}
	return OK;
}
//将线性表清空
void ClearList(SqList *L)
{
	memset(L,0,sizeof(SqList));
}
/*在线性表L中查找给定值e相等的元素,
  *如果查找成功返回该元素在表中序号
  *表示成功;否则,返回0表示失败。
*/
int LocateElem(SqList *L,ElemType e)
{
	int i = 0;
	if(L->length == 0)//线性表为空
	{
		printf("[%s %d]链表为空\n",__FUNCTION__,__LINE__);
		return ERROR;
	}

	for(i = 0;i < L->length;i++)
	{
		if(e == L->data[i])
		{
			return i;
		}
	}
	printf("[%s %d]链表L中不存在元素e:%d\n",__FUNCTION__,__LINE__,e);
	return ERROR;
}

//返回线性表L的元素个数
int ListLength(SqList *L)
{
	return L->length;
}

//初始条件:顺序表L已经存在,1=<i=<ListLength(L)
//操作结果:用e返回L中第i个数据元素的值
int 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已经存在,1=<i=<ListLength(L)
//操作结果:删除L中第i个位置的数据元素,并用e返回其值,L的长度减1
int ListDelete(SqList *L,int i,ElemType *e)
{
	int k;
	if(L->length == 0)//线性表为空
	{
		return ERROR;
	}
	if(i< 0 || i> L->length)//删除位置不正确
	{
		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;
}
//初始条件:顺序表L已经存在,1=<i=<ListLength(L)
//操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
int ListInsert(SqList *L,int i,ElemType e)
{
	int k;
	if(L->length == MAXSIZE)//顺序线性表已满
	{
		return ERROR;
	}
	if(i< 0 || i> L->length)//当i不在范围内时
	{
		return ERROR;
	}
	if(i< L->length)//若插入位置不在表尾
	{
		for(k = L->length;k>= i;k--)//将要插入的位置后数据元素向后移动一位
		{
			L->data[k+1] = L->data[k];
		}
	}
	L->data[i] = e;//将新元素插入
	L->length++;
	return OK;
}

/*将所有的在线性表Lb中但是不在La中的元素插入到La中*/
void swapList(SqList *La,SqList *Lb)
{
	int La_len,Lb_len,i;
	ElemType e;//声明与La个Lb相同的数据元素e
	La_len = ListLength(La);//求线性表的长度
	Lb_len = ListLength(Lb);
	for(i = 1;i <= Lb_len;i++)
	{
		GetElem(Lb,i,&e);//取Lb中第i个数据元素赋值给e
		if(!LocateElem(La,e))//La中不存在和e相同的数据元素
		{
			ListInsert(La,++La_len,e);//插入
		}
	}
}

int ListPrint(SqList *L)
{
	int i = 0;
	if(L->length == 0)//线性表为空
	{
		printf("[%s %d]链表为空\n",__FUNCTION__,__LINE__);
		return ERROR;
	}

	for(i = 0;i < L->length;i++)
	{
		printf("[%s %d]位置:%d,元素:%d\n",__FUNCTION__,__LINE__,i,L->data[i]);
	}
	return OK;
}


int main()
{
    SqList L;
	int i = 0;
	int ret = ERROR;
	ElemType e = 0;
	InitList(&L);
	//插入数据
	printf("[%s %d]------------插入数据------------------\n",__FUNCTION__,__LINE__);
	for(i = 0;i < 15;i++)
	{
		ret = ListInsert(&L,i,i);
		if(ERROR == ret)
		{
			printf("[%s %d]插入数据失败,位置:%d,元素:%d\n",__FUNCTION__,__LINE__,i,i);
		}
	}

	//打印链表
	ret = ListPrint(&L);
	if(ERROR == ret)
	{
		printf("[%s %d]打印链表失败\n",__FUNCTION__,__LINE__);
	}

	//插入数据
	printf("[%s %d]------------指定位置插入数据------------------\n",__FUNCTION__,__LINE__);
	ret = ListInsert(&L,10,22);
	if(ERROR == ret)
	{
		printf("[%s %d]插入数据失败,位置:%d,元素:%d\n",__FUNCTION__,__LINE__,i,i);
	}

	//打印链表
	ret = ListPrint(&L);
	if(ERROR == ret)
	{
		printf("[%s %d]打印链表失败\n",__FUNCTION__,__LINE__);
	}
	//获取单个元素
	printf("[%s %d]------------获取单个元素------------------\n",__FUNCTION__,__LINE__);
	ret = GetElem(&L,5,&e);
	if(ERROR == ret)
	{
		printf("[%s %d]获取位置5的数据失败\n",__FUNCTION__,__LINE__);
	}
	else
	{
		printf("[%s %d]e:%d\n",__FUNCTION__,__LINE__,e);
	}
	//获取长度
	printf("[%s %d]------------获取长度------------------\n",__FUNCTION__,__LINE__);
	ret = ListLength(&L);
	printf("[%s %d]链表长度:%d\n",__FUNCTION__,__LINE__,ret);

	printf("[%s %d]------------检查元素------------------\n",__FUNCTION__,__LINE__);
	ret = LocateElem(&L,5);
	if(OK == ret)
	{
		printf("[%s %d]5是链表中元素,位置:%d\n",__FUNCTION__,__LINE__,ret);
	}
	else
	{
		printf("[%s %d]5不是链表中元素\n",__FUNCTION__,__LINE__);
	}

	//删除数据
	printf("[%s %d]------------删除数据------------------\n",__FUNCTION__,__LINE__);
	ret = ListDelete(&L,10,&e);
	if(ERROR == ret)
	{
		printf("[%s %d]删除失败\n",__FUNCTION__,__LINE__);
	}
	else
	{
		printf("[%s %d]删除成功e:%d\n",__FUNCTION__,__LINE__,e);
	}

	//打印链表
	ret = ListPrint(&L);
	if(ERROR == ret)
	{
		printf("[%s %d]打印链表失败\n",__FUNCTION__,__LINE__);
	}
	printf("[%s %d]------------清空链表------------------\n",__FUNCTION__,__LINE__);
	if(ListEmpty(L))
	{
		printf("[%s %d]链表不为空\n",__FUNCTION__,__LINE__);
	}
	ClearList(&L);
	if(ListEmpty(L))
	{
		printf("[%s %d]链表不为空\n",__FUNCTION__,__LINE__);
	}

//void swapList(SqList *La,SqList *Lb);
	return OK;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值