数据结构—顺序表

本文介绍了顺序表的概念,包括静态和动态顺序表,重点讲述了如何实现动态顺序表,包括初始化、检查容量、打印、插入、删除、查找和修改等操作,并讨论了顺序表的优化和其在头插、头删时的时间复杂度问题,指出其在效率上的局限性,为后续引入链表做铺垫。
摘要由CSDN通过智能技术生成

目录

1.顺序表概念

2.顺序表分类:

3.实现动态顺序表

      3.1初始化顺序表  SLInit

      3.2 检查顺序表容量   SLCheckCapacity

      3.3 打印顺序表  SLPrint

      3.4尾插 SLPushBack

      3.5头插 SLPushFront

      3.6尾删 SLPopback

      3.7头删  SLPopFront 

      3.8 顺序表查找 SLFind 

      3.9  顺序表修改 SLModify

  4. 顺序表总结

       4.1 顺序表优化

       4.2 顺序表的缺点


1.顺序表概念

       顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组 上完成数据的增删查改


2.顺序表分类:

   2.1 静态顺序表:使用定长数组存储元素。(不实用)

   2.2动态顺序表:使用动态开辟的数组存储。


3.实现动态顺序表

      3.1 初始化顺序表  SLInit

void SLInit(SL* ps)
{
	assert(ps != NULL);

	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

      3.2 检查顺序表容量   SLCheckCapacity

void SLCheckCapacity(SL* ps)
{
	assert(ps != NULL);

	// 检查容量空间,满了扩容
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			//exit(-1);
			return;
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}
}

       3.3 打印顺序表  SLPrint

void SLPrint(SL* ps)
{
	assert(ps != NULL);
	//assert(ps);

	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

       3.4 尾插 SLPushBack

void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps != NULL);

	SLCheckCapacity(ps);

	ps->a[ps->size] = x;
	ps->size++;

	//SLInsert(ps, ps->size, x);
}

    3.5 头插 SLPushFront

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps != NULL);

	SLCheckCapacity(ps);

	// 挪动数据
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];
		--end;
	}

	ps->a[0] = x;
	ps->size++;

	//SLInsert(ps, 0, x);
}

   3.6 尾删 SLPopback

 void SLPopBack(SL* ps)

{
   
  assert(ps->size > 0);//暴力检查,顺序表为空不能删

	ps->size--;
}

   3.7 头删  SLPopFront 

void SLPopFront(SL* ps)
{
	assert(ps != NULL);
	assert(ps->size > 0);

	int begin = 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		++begin;
	}

	ps->size--;

	//SLErase(ps, 0);
}

  3.8 顺序表查找 SLFind 

int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
			return i;
	}

	return -1;
}

  3.9  顺序表修改 SLModify

void SLModify(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);

	ps->a[pos] = x;
}

  4. 顺序表总结

       4.1 顺序表优化

       使用SLInsert函数实现 尾插,头插

       使用SLErase函数实现 尾删,头删

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);

	SLCheckCapacity(ps);

	// 挪动数据
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		--end;
	}

	ps->a[pos] = x;
	ps->size++;
}
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);

    //两种方法实现
	//int begin = pos;
	//while (begin < ps->size-1)
	//{
	//	ps->a[begin] = ps->a[begin + 1];
	//	++begin;
	//}

	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		++begin;
	}

	ps->size--;
}

 4.2 顺序表的缺点

   由于头插和头删需要移动数据,所以时间复杂度为O(N),所以后面引入链表实现。

  • 85
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 55
    评论
评论 55
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小余要努力

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

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

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

打赏作者

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

抵扣说明:

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

余额充值