数据结构——顺序表

引言

  在计算机科学中,数据结构是组织和存储数据的方式,它影响着数据的访问和修改效率。顺序表作为最简单且直观的数据结构之一,以连续内存空间存储数据,为数据的快速访问提供了便利。本文将深入探讨顺序表的实现机制,包括其基本原理、关键操作及应用场景,旨在为初学者和进阶学习者提供一份全面的指南。

一.顺序表的定义及其特点

定义

    顺序表是一种基本的数据结构,它通过连续的内存空间来存储数据元素,每个元素占据相同的存储空间,且在逻辑上相邻的元素在物理位置上同样相邻(存储结构)

特点

1. 随机访问,访问速度快,顺序表在随机访问方面具有O(1)的时间复杂度。

2.存储密度高:顺序表在内存中是连续存储的,它不需要额外的空间来存储指针或其他控制信息。

3.扩展容量不方便:顺序表中的元素数量达到其容量极限时,为了插入新的元素,需要进行内存的重新分配

4.插入和删除元素不方便:插入和删除操作可能需要O(n)的时间复杂度,通常可能涉及大量元素的移动。

二.顺序表的实现 (静态分配和动态分配)

准备工作

头文件

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

[1] 定义静态顺序表的最大长度和动态顺序表的初始最大容量

#define Maxsize 10  //静态顺序表的最大长度
#define InitSize 10 //动态顺序表的默认最大初始容量

[2]  自定义c语言的bool变量

#define true 1
#define false 0

[3] 自定义数据元素的类型

typedef int Elemtype;

结构体

   我们使用俩种方法实现顺序表。其中data为数据的类型,length为顺序表数当前的长度,动态分配比静态分配多一个参数 maxsize,用于记录顺序表的最大容量。

代码:

 // <1>静态分配
typedef struct  SqList {
	Elemtype data[Maxsize];//用静态数组存放数据元素
	int length;  //顺序表当前长度
}SqList;

 // <2>动态分配
typedef struct SeqList
{
	Elemtype* data;//用动态指针 分配数组
	int length;//当前长度
	int maxsize;//最大容量
}SeqList;

顺序表的初始化

  注意:我们在主函数中引用定义一个顺序表再引用该函数,并将顺序表的指针传入函数。

  对于插入,删除等操作 参数为指针  (SqList *L),这样在方法中对顺序表的修改效果才能实际生效。

  对于查找顺序表的元素、和输出顺序表的值,他们的参数不为指针(为 SqList  L),因为我们不需要对表进行改变。

// <1>顺序表的初始化(静态分配)
bool InitSqList(SqList* L)//参数为指针,要对表内做出改变
{
	L->length = 0;//初始化表长

	//for (int i = 0; i < Maxsize; i++) //初始化元素
	//{
	//	L->data[i] =0;
	//}
	return true;
}
// <2>顺序表的初始化(动态分配)
bool InitSeqList(SeqList* L)
{
	L->length = 0;//初始化表长
	L->maxsize = InitSize;//初始化动态顺序表的最大容量
	L->data = (Elemtype*)malloc(sizeof(Elemtype) * InitSize);//malloc
	return true;
 }

顺序表的输出

//<1>静态顺序表的输出
bool SqListPrint(SqList L)
{
	//<1>判断是否为空
	if (L.length == 0)
	{
		printf("This sequence table is empty! \n");
		return false;
	}
	//<2>输出
	printf("SqList: \n");
	for (int i = 0; i < L.length; i++)
	{
		printf("%d-->",L.data[i]);
	}
	printf("end\n");
	return true;
}
//<2>动态顺序表的输出
bool SeqListPrint(SeqList L)
{
	//<1>判断是否为空
	if (L.length == 0)
	{
		printf("This sequence table is empty! \n");
		return false;
	}
	//<2>输出
	printf("SeqList: \n");
	for (int i = 0; i < L.length; i++)
	{
		printf("%d-->", L.data[i]);
	}
	printf("end\n");
	return true;
}

插入元素实现

插入操作涉及以下几个步骤

1.检查插入操作的合法性:插入位置是否合理?插入的表元素是否满了?

2.移动元素以腾出空间:从要插入的位置i开始,将顺序表中的元素向后移动,为新元素腾出空间。这通常通过一个从后向前的循环来实现

3.插入新元素:在腾出的空间中放置新元素。

4.更新顺序表的长度:插入新元素后,顺序表的长度需要增加1。

//<1>顺序表的元素插入(静态分配)
//在顺序表的第i个位置插入一个新元素e
bool SqListInsert(SqList* L ,int i, Elemtype e)
{

	//[1]判断插入操作是否合法
	if (i<1 || i>L->length + 1)//length 为当前长度
	{
		printf("The position of the element to be inserted is invalid \n");
		return false;
	}

	if (L->length >= Maxsize)
	{
		printf("This sequence table is full! \n");
		return false;
	}
	//[2]移动元素,空出待插入的位置
	for (int j = L->length; j >= i; j--)
	{
		L->data[j] = L->data[j - 1];
	}
	//[3]将新元素插入到正确的位置 -----区分数组小标和元素位序的排列
	L->data[i - 1] = e;
	//[4]表长加一
	L->length++;
	//[5]返回,插入成功
	return true;
}

// <2>顺序表的插入 (动态分配)
bool SeqListInsert(SeqList* L, int i, Elemtype e)
{

	//[1]判断插入操作是否合法
	if (i<1 || i>L->length + 1)//length 为当前长度
	{
		printf("The position of the element to be inserted is invalid \n");
		return false;
	}

	if (L->length >= L->maxsize)
	{
		printf("This sequence table is full! \n");
		return false;
	}
	//[2]移动元素,空出待插入的位置
	for (int j = L->length; j >= i; j--)
	{
		L->data[j] = L->data[j - 1];
	}
	//[3]将新元素插入到正确的位置 -----区分数组小标和元素位序的排列
	L->data[i - 1] = e;
	//[4]表长加一
	L->length++;
	//[5]返回,插入成功
	return true;
}

删除元素实现(按位删除)

//<1>静态顺序表的元素删除
//将顺序表的第i个位置的元素删除,并把删除元素的值返回给e
bool SqListElemDelete(SqList* L, int i, Elemtype *e)
{
	//[1]判断操作的合法性
	if (i<1 || i>L->length + 1)//length 为当前长度
	{
		printf("The position of the element to be delete is invalid \n");
		return false;
	}

	if (L->length <= 0)
	{
		printf("This sequence table is empty! \n");
		return false;
	}
	//[2]将待删除的元素赋值给e
	*e = L->data[i - 1];
	//[3]将第i位以及后面的元素都往前移一位
	for (int j = i; j < L->length; j++)
	{
		L->data[j - 1] = L->data[j];
	}
	//[4]表长减一
	L->length--;
	//返回
	return true;
}
//<2>动态顺序表的元素删除
//将顺序表的第i个位置的元素删除,并把删除元素的值返回给e
bool SeqListElemDelete(SeqList* L, int i, Elemtype* e)
{
	//[1]判断操作的合法性
	if (i<1 || i>L->length + 1)//length 为当前长度
	{
		printf("The position of the element to be delete is invalid \n");
		return false;
	}

	if (L->length <= 0)
	{
		printf("This sequence table is empty! \n");
		return false;
	}
	//[2]将待删除的元素赋值给e
	*e = L->data[i - 1];
	//[3]将第i位以及后面的元素都往前移一位
	for (int j = i; j < L->length; j++)
	{
		L->data[j - 1] = L->data[j];
	}
	//[4]表长减一
	L->length--;
	//返回
	return true;
}

查找元素实现(按值查找)

//<1>静态顺序表的元素按值查找,并返回位序
int SqListLocElem(SqList L, Elemtype e)
{
	for (int i = 0; i < L.length; i++)
	{
		if (L.data [i] == e)
		{
			return i + 1;
		}
	}
	return 0;
}
//<2>动态顺序表的元素按值查找,并返回位序
int SeqListLocElem(SeqList L, Elemtype e)
{
	for (int i = 0; i < L.length; i++)
	{
		if (L.data[i] == e)
		{
			return i + 1;
		}
	}
	return 0;
}

扩容

/*【9】动态顺序表  --- 扩容*/
bool IncreaseSize(SeqList* L, int len)
{
	//[1]生成指向原来顺序表的存储空间的指针
	Elemtype* p = L->data;
	//[2]为顺序表开辟一块更大的空间
	L->data = (Elemtype*)malloc(sizeof(Elemtype) * (Maxsize + len));
	//[3]转移数据
	for (int i = 0; i < L->length; i++)
	{
		L->data[i] = p[i];  //p[i] == = *(p +i)
	}
	//修改顺序表的最大长度
	L->maxsize += len;
	//释放原来的空间
	free(p);
	//成功返回
	return true;
}

测试

int main()
{
	SqList L1; //静态顺序表L1
	SeqList L2;  //动态顺序表 L2

   //顺序表的初始化
	InitSqList(&L1);
	InitSeqList(&L2);
	printf("%d", L2.maxsize);


	//插入一些元素
	SqListInsert(&L1, 1, 1);
	SqListInsert(&L1, 2, 2);
	SqListInsert(&L1, 3, 3);
	SqListInsert(&L1, 4, 4333);
	SqListInsert(&L1, 5, 5);
	SqListInsert(&L1, 6, 6);
	SqListInsert(&L1, 7, 7);

	SeqListInsert(&L2, 1, 1);
	SeqListInsert(&L2, 2, 2);
	SeqListInsert(&L2, 3, 3);
	SeqListInsert(&L2, 4, 4);
	SeqListInsert(&L2, 5, 5);
	SeqListInsert(&L2, 6, 6999);
	SeqListInsert(&L2, 7, 7);
	SqListPrint(L1);
	SeqListPrint(L2);
	printf("L1 's 4333 is: %d\n", SqListLocElem(L1, 4333));
	printf("L2 's 6999 is: %d\n", SeqListLocElem(L2, 6999));
	int e;
	SqListElemDelete(&L1, 4, &e);
	printf("%d\n", e);
	SeqListElemDelete(&L2, 6, &e);
	printf("%d\n", e);
	SqListPrint(L1);
	SeqListPrint(L2);

	printf("L1 's 4333 is: %d\n", SqListLocElem(L1, 4333));
	printf("L2 's 6999 is: %d\n", SeqListLocElem(L2, 6999));


	IncreaseSize(&L2, 20);
	SeqListPrint(L2);
	printf("L2 Maxsize: ---- %d", L2.maxsize);


	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值