第25讲:顺序表专题

1.什么是数据结构

2.顺序表概念及结构

3.顺序表分类

4.实现动态顺序表

1.什么是数据结构

数据结构是计算机存储、组织数据的方式。可以用来完成通讯录项目。

2.顺序表概念及结构

2.1线性表

线性表是n个具有相同特性的数据元素的有限序列

常见的线性表:顺序表,链表,栈队列,字符串

线性表在逻辑上是线性的,但在物理结构上却不一定,也就是在内存上的存储不一定是连续的

3.顺序表分类

静态顺序表:空间是固定的,给多了浪费空间,给少了空间不够

缺点多,不建议使用

动态顺序表:空间可以扩大,但扩大空间会浪费时间

相较于静态顺序表优点多,建议使用

4.实现动态顺序表

文件名:SeqList.c

#define _CRT_SECURE_NO_WARNINGS
#include "Seqlist.h"
void initSeqList(SL* pSL)//初始化顺序表
{
	pSL->pa = NULL;
	pSL->size = 0;
	pSL->capacity = 0;
}

void cheak(SL* psl1)//检查空间是否足够
{
	if (psl1->size == psl1->capacity)
		expandSL(psl1);
}

void expandSL(SL* pSL)//扩容
{
	int newcapacity = pSL->capacity == 0 ? 4 : 2 * pSL->capacity;
	SLdatatype* pSLm = realloc(pSL->pa, (size_t)newcapacity * sizeof * (pSL->pa));
	if (pSLm == NULL)
	{
		perror("relloc");
		exit(1);
	}
	else
		pSL->pa = pSLm;
	pSL->capacity = newcapacity;
}

void printSL(SL* pSL)//打印顺序表
{
	assert(pSL);
	int i;
	for (i = 0; i < pSL->size; i++)
		printf("%d ", pSL->pa[i]);
}

void backaddSL(SL* pSL, SLdatatype n)//后增
{
	assert(pSL);
	cheak(pSL);
	pSL->pa[pSL->size++] = n;
}

void frontaddSL(SL* pSL, SLdatatype n)//前增
{
	assert(pSL);
	cheak(pSL);
	int i;
	for (i = 0; i < pSL->size; i++)
	{
		pSL->pa[pSL->size - i] = pSL->pa[pSL->size - i - 1];
	}
	pSL->pa[0] = n;
	pSL->size++;
}

void backdel(SL* pSL)//后删
{
	assert(pSL != NULL);
	assert(pSL->size > 0);
	pSL->size--;
}

void frontdel(SL* pSL)//前删
{
	assert(pSL != NULL);
	assert(pSL->size > 0);
	int i;
	for (i = 0; i < pSL->size - 1; i++)
	{
		pSL->pa[i] = pSL->pa[i + 1];
	}
	pSL->size--;
}

void posaddSL(SL* pSL, SLdatatype n, int pos)//指定位置插入
{
	assert(pSL);
	int i = 0;
	for (i = 0; i < pSL->size - pos + 1; i++)
	{
		pSL->pa[pSL->size - i] = pSL->pa[pSL->size - i - 1];
	}
	pSL->pa[pos - 1] = n;
	pSL->size++;
}

void posdelSL(SL* pSL, int pos)//指定位置删除
{
	assert(pSL);
	int i = 0;
	for (i = 0; i < pSL->size - pos + 1; i++)
	{
		pSL->pa[pos - 1 + i] = pSL->pa[pos + i];
	}
	pSL->size--;
}

void SLfind(SL* pSL, int n)//元素查找
{
	int i = 0, flag = 1;
	for (i = 0; i < pSL->size; i++)
	{
		if (pSL->pa[i] == n)
		{
			printf("元素下标为%d\n", i);
			flag = 0;
		}
	}
	if (flag)
		puts("没有该元素");
}

void SLalter(SL* pSL, int n, int pos)//元素修改
{
	pSL->pa[pos - 1] = n;
}

void SLdesdroy(SL* pSL)//销毁
{
	assert(pSL);
	if (pSL->pa != NULL)
	{
		free(pSL->pa);
		pSL->pa = NULL;
	}
	pSL->size = 0;
	pSL->capacity = 0;
}

文件名:SeqList.h

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int SLdatatype;
typedef struct SeqList
{
	SLdatatype* pa;//数组首元素地址
	int size;//元素个数
	int capacity;//数组容量
}SL;

//初始化顺序表
void initSeqList(SL* pSL);

//判断空间是否足够
void cheak(SL* psl1);

//扩容
void expandSL(SL* pSL);

//打印顺序表
void printSL(SL* pSL);

//后增
void backaddSL(SL* pSL, SLdatatype n);

//前增
void frontaddSL(SL* pSL, SLdatatype n);

//后删
void backdel(SL* pSL);

//前删
void frontdel(SL* pSL);

//指定位置插入
void posaddSL(SL* pSL, SLdatatype n, int pos);

//指定位置删除
void posdelSL(SL* pSL, int pos);

//元素查找
void SLfind(SL* pSL, int n);

//元素修改
void SLalter(SL* pSL, int n, int pos);

//销毁
void SLdesdroy(SL* pSL);

文件名:test.c

#define _CRT_SECURE_NO_WARNINGS
#include "Seqlist.h"
void test1(SL* psl1)//测试后增
{

	backaddSL(psl1, 5);
	backaddSL(psl1, 6);
	backaddSL(psl1, 7);
	printSL(psl1);
}
void test2(SL* psl1)//测试前增
{
	frontaddSL(psl1, 5);
	frontaddSL(psl1, 6);
	frontaddSL(psl1, 7);
	frontaddSL(psl1, 8);
	frontaddSL(psl1, 9);
	frontaddSL(psl1, 5);
	frontaddSL(psl1, 6);
	printSL(psl1);
	putchar('\n');
}
void test3(SL* psl1)//测试后删
{
	backdel(psl1);
	printSL(psl1);
}
void test4(SL* psl1)//测试前删
{
	frontdel(psl1);
	printSL(psl1);
}
void test5(SL* psl1)//测试指定位置插入
{
	posaddSL(psl1, 80, 3);
	printSL(psl1);
}
void test6(SL* psl1)//测试指定位置删除
{
	posdelSL(psl1, 3);
	printSL(psl1);
}
void test7(SL* psl1)//测试元素查找
{
	SLfind(psl1, 100);
}
void test8(SL* psl1)//测试元素修改
{
	SLalter(psl1, 100, 3);
	printSL(psl1);
}
void test9(SL* psl1)//测试销毁
{
	SLdesdroy(psl1);
	printSL(psl1);
}
int main()
{
	SL sl1;
	initSeqList(&sl1);
//	test1(&sl1);
	test2(&sl1);
//	test3(&sl1);
//	test4(&sl1);
//	test5(&sl1);
//	test6(&sl1);
//	test7(&sl1);
//	test8(&sl1);
	test9(&sl1);
	return 0;
}

第5行,将int重命名。

目的:若想替换代码中所有的int,可以改变第5行的int,做到一键替换

注意:capacity说明的是最多可以容纳多少个元素,不是空间的大小,单位不是字节

第六行:创建结构体存储数据

第8和第9行,通过首元素地址下标访问,可以访问到数组中的每一个元素,元素个数是为了方便访问的,体现在后面的代码实现中

第10行:设置界限,数元素个数等于数组容量,说明需要扩容,否则不能写入数据

第一步,顺序表的初始化,没什么好说的

数元素个数等于数组容量,说明需要扩容,否则不用

第18行:newcapacity说明扩容后是最多可以容纳多少个元素

现在的问题是:一次要开辟多少空间,开辟多了,那么开辟的次数就少了,可以节省时间,但浪费的空间较多。开辟少了,那么开辟的次数就多了,浪费时间,但是相对前一个可以节省时间。

所以,我们采取一个折中的办法,也是性价比较高的一个。那就是将空间扩大到原来的两倍。第一次开辟比较特殊,初始化后,空间是0,不能扩大到原来的两倍,因为0*2=0,也就是没扩大。所以,就有了第18行的写法。

第19行:要开辟的字节数应是一个元素的大小*开辟后最大元素个数

其余的写法参考动态内存管理,这里不再赘述

若传来的是空指针,会出现错误,所以,要用assert断言一下

第一步:assert防止空指针

第二步:检查空间够不够,不够就会扩容,保证在写入元素时空间大小足够

第三步:写入元素,写完后要让元素个数加一

第一步:断言

第二步:检查空间

第3步:让所有元素往后挪一格

最后:在前面写入元素,元素个数加一

第一步:断言防空指针

第二步:断言防止顺序表中没有数据

第三步:删除元素

问题:为什么这里元素个数减1就行了?

空间里会默认存随机数,所以我们无论给需删除的地方赋什么值都不合适

所以,我们只需要能正常使用就行了,假设那个元素被删除了就行了

问题:元素个数减1是不是必要的?

是的,不减会影响正常使用,体现的后面的代码中

第一步:双断言

第二步:让所有元素像前移动一格

第三步:元素个数减一

第一步:指定位置和后面的元素都向后移动一个

第二步:插入元素

第三步:元素个数加1

第一步:指定位置后面的元素往前移动一格

第二步:元素个数减一

第一步:一个一个比较,有相同的说明找到了,打印该元素的下标,使flag为0

第二步:没找到说明flag是1,打印“没找到”。

直接修改就行了,没什么好说的

第一步:assert断言

第二步:如果pa不指向NULL,说明pa是有分配空间的,free掉,并使pa指向NULL。

第三步:使元素个数和最大元素个数为0

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

INUYACHA

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

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

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

打赏作者

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

抵扣说明:

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

余额充值