数据结构学习笔记01——顺序表

什么是数据结构

数据结构 是 计算机存储组织数据的形式。
1)能够存储数据(如顺序表、链表等结构)
2)存储的数据能方便查找

最基础的数据结构——数组

但是对于数据量庞大的情况来说,最基础的数据结构能够提供的操作已经不能完全满足复杂算法的实现

线性表

顺序表

底层结构是数组
通过对数组的封装,实现了常用的增删改查等接口

顺序表分类

1.静态顺序表
概念:使用定长数组存储元素。

//静态顺序表
//用typedef定义数据类型
typedef int SLDataType;
#define M 7
typedef sturct SeqList
{
 SLDataType a[M];//定长数组
 int size;//有效数据个数
}SL;

数据按照线性排列
缺陷:容量固定,空间给少了不够用,空间给多了浪费。

2.动态顺序表

2.1结构

//动态顺序表——按需申请
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;//动态内存的指针
int size;		     //有效数据的个数
int capacity;      //空间容量
}SL;

以上是动态顺序表的结构
在这里插入图片描述
2.2初始化

void SLInit(SL*ps)
{
ps->a=NULL;
ps->capacity=ps->size=0;
}

bool SLIsEmpty(SL*ps)
{
assert(ps);
return ps->size==0;
}

把指针置空
把有效数据个数清零
同时把空间大小初始化。

2.3销毁

void SLDestroy(SL*ps)
{
	if(ps->a)	//先判断指针下是否动态开辟空间
		{
		free(ps->a);//将a动态开辟的内存释放
		}
	ps->a=NULL; //将指针置空
	ps->size=ps->capacity=0;//将空间大小和有效数据个数清零
}

容易忘记的是先判断指针下是否开辟动态内存
2.3打印数据

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

2.4扩容

void SLCheckCapapcity(SL*ps)
{
		if(ps->size==ps->capacity)
		{
			//判断空间容量是否已满
			//扩容(原容量的两倍 )
			int newCapacity =ps->capacity==0?4:2*ps->capacity;
			//如果原容量为零就给4个空间,非零就给原容量两倍
			//动态开辟内存
			SLDataType* tmp=(SLDataType*)realloc(p->a,newCapacity*sizeof(SLDataType));
			if(tmp==NULL)
			{
				perror("realloc fail!");
				return 1;
			}
			ps->a=tmp;
			tmp=NULL;
			//更新原来空间大小
		    ps->capacity=newCapacity;
		}
}

流程:
判断容量是否满(ps->size==ps->capacity)–>
满就继续–>新空间大小的声明(三目操作符的使用)–>动态内存的扩容(开辟)–>更新ps->capacity.

2.5尾部插入数据

void SLPushBack(SL*ps,SLDataType x)
{
//碰到有关指针的函数,记得断言
assert(ps);
//先检查容量并扩容
SLCheckCapacity(ps);
//然后插入数据
ps->a[size++]=x;
}

//思路很简单,别忘了size++
还有!assert断言!

2.6头部插入数据

void SLPushFront(SL*ps)
{
	assert(ps);//还是要断言
	SLCheckCapacity(ps);
	for(size_t i=ps->size;i>0;i--)
	{
	ps->a[i]=ps->a[i-1];
	}
	ps->size++
}

2.7尾部删除数据

void SLPopBack(SL*ps)
{
assert(ps);
//判断顺序表是否为空
assert(!SLIsEmpty(ps));//assert括号为0,不会报错,括号非0,就会报错
ps->size--;
}
				----------------------2024.02.21--------------------

				----------------------2024.03.02--------------------

2.8头部删除数据

void SLPopBack(SL*ps)
{
	//判断指针
	assert(ps);
	//判断顺序表是否为空
	
	assert(!SLIsEmpty);
	
	for(size_t i;i=0;i<ps->size-1;i++)
	{
		ps->a[i]=ps->a[i+1];
	}
	ps->size--;
}

思路很简单,直接覆盖前一个数据就行,不用管最后一个数据的值,因为size–.

2.8在指定位置插入数据

void SLInsert(SL*ps,int pos,SLDatatType x);

这里的pos是指数据的下标

void SLInsert(SL*ps,int pos)
{
		//经典assert断言
		assert(ps);
		assert(pos>=0&&pos<size)
		//经典判断空间是否足够
		SLCheckEmpty(ps);
		//开始插入数据,同时将插入数据下标的原来数据后挪(**后面的数据先挪**,然后依次往前)
		for(size_t i=ps->size;i>pos;i--)
		{
		ps->a[i]=ps->a[i-1];
		}
		ps->a[pos]=x;
		ps->size++
}

容易忘记的地方:插入位置的下标一定要限定好!(最后一个元素的下标是size-1!)

2.9在指定位置删除数据

void SLErase(SL*ps,int pos);
void SLErase(SL*ps,int pos)
{
	//经典得不能再经典的assert
	assert(ps);
	//不要忘记pos的范围控制
	assert(pos>=0&&pos<ps->size);
	//删除数据的函数,记得检查原来空间**是否没有数据**
	assert(!SLIsEmpty(ps));
	//开始删除数据(pos位置的**后一个数据**开始往前移动)
	for(size_t i=pos;i<size-1;i++)
	{
		p->a[i]=p->a[i+1];
	}
	ps->size--;
}

注意i的取值范围

2.10顺序表的小总结
以上是通过以数组为底层,实现动态顺序表初始化、销毁、扩容、增加数据、删除数据的的顺序表实现。
其中重点

  1. Check函数

  2. assert断言的使用

  3. size的更新

  4. 删除数据记得判断是否空间没有数据

  5. i的下标

    ---------------------顺序表完结--------------------
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值