数据结构--顺序表

1.顺序表的概念

1.1线性表

具有相同特性的数据元素的有限序列,再逻辑结构上呈现线性,但是在物理结构上不一定是线性(也就是在内存中非线性)

顺序表是线性表中的一种,他的底层逻辑就是数组,就是对数组的一种封装形式,有了增删改查等用法;

注:数组在逻辑结构和物理结构都是线性的;

1.2顺序表的分类

顺序表可分为:动态顺序表和静态顺序表

1.2.1静态顺序表

例如:

struct L
{
	int a[100];
    int size //当前有效数据个数
};

1.2.2动态顺序表

strcut
{
    int* a;
    int size
    int ca//当前空间大小
}

动态顺序表对于内存处理更加灵活;对于扩容更加方便,不需要整个数组进行修改,增加了数据的安全性。

1.3顺序表的头文件

1.3.1顺序表基础

//包含头文件
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//关键字转变
typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;
	int capacity;
}SQ;

第一,typedef int SLDateType;可以更好改变数据变量的类型;

第二,

typedef struct SeqList
{
	SLDateType* a;
	int size;
	int capacity;
}SQ;

把名叫SeqList的结构体typedef成SQ,方便未来对此结构体的调用。

    SLDateType* a;->a指向的空间就是顺序表存储的位置。
    int size;->顺序表成员的数量
    int capacity;->顺序表空间的大小

1.3.2顺序表基本应用

// 对数据的管理:增删查改 
//初始化
void SeqListInit(SQ* ps);
//结构体的清除
void SeqListDestroy(SQ* ps);
//结构体打印
void SeqListPrint(SQ* ps);
//尾插
void SeqListPushBack(SQ* ps, SLDateType x);
//头插
void SeqListPushFront(SQ* ps, SLDateType x);
//头删
void SeqListPopFront(SQ* ps);
//尾删
void SeqListPopBack(SQ* ps);
// 顺序表查找
int SeqListFind(SQ* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SQ* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SQ* ps, int pos);
顺序表初始化
#include "SeqList.h"

void SeqListInit(SQ* ps)
{
	assert(ps);

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

a的空间指向NULL,size成员数量和空间大小都置为0;

顺序表清除
void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

首先判断ps是否为空,为空则中断,不为空则为继续执行,此处assert(x),x为真

才不会被中断。

free(ps->a)把a所指向的空间置为NULL;

a的指针置为空,size,capacity为0;

顺序表的打印
void SeqListPrint(SQ* ps)
{
	assert(ps);

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

	printf("%\n");
}
顺序表空间开辟
void CheckCacpity(SQ* ps)
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		ps->a = (SLDateType*)realloc(ps->a, newcapacity*sizeof(SLDateType));
		ps->capacity = newcapacity;
	}
}

当size的大小和capacity的大小一样的时候,则表示空间满了,当空间capacity和size大小为空时,也会开辟空间;

创建newcapacity(判断capacity是非为0,为0则开辟为4,不为0,则*2)

realloc(存储空间,重新开辟空间的大小)

之后再把capacity置为新空间大小。

1.3.3顺序表的增删改查

顺序表的尾部插入
void SeqListPushBack(SQ* ps, SLDateType x)
{
	assert(ps);
	CheckCacpity(ps);

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

首先断言ps是否为空指针,之后开辟一个空间,其中ps->a[ps->size],ps所指向的数组a的下标为ps->size的元素(新开辟空间的下标),因为下标是从0开始的,所以原数组最大下标为size-1,新开辟的则为size。

不要忘记size还需要增加。

顺序表的头部插入
void SeqListPushFront(SQ* ps, SLDateType x)
{
	assert(ps);

	CheckCacpity(ps);

	int end = ps->size;
	while (end > 0)
	{
		ps->a[end] = ps->a[end - 1];
		--end;
	}

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

首先进行断言和开辟空间,设置一个新整型end存放最大元素个数size,end用来控制变量。

循环判定条件是end>0,循环体内部将数组元素向后移动,之后将end减小,直至end=0时,循环终止。

之后再将a[0]置为新的数字x,size又增大一位。

顺序表的头部删除
void SeqListPopFront(SQ* ps)
{
	assert(ps);

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

	--ps->size;
}

先断言ps,创建一个整型变量,置为0,循环体内将整个数组进行遍历,原理是用后面的元素把前面的覆盖掉,从小到大覆盖,最后将size-1;

顺序表的尾部删除
void SeqListPopBack(SeqList* ps)
{
	assert(ps);

	ps->a[ps->size - 1] = 0;
	ps->size--;
}

老规矩,先断言,ps为空就不能进行插入删除,此处凸显了顺序表的好处,能够很灵活的调用顺序表内的各个成员(因为有下标的关系),

只需要将最后一个元素置为0,之后将size-1即可。

1.3.4顺序表其他应用

找到数据位x下标位置
int SeqListFind(SQ* ps, SLDateType x)
{
	for (int i = 0; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}

	return -1;
}

再循环体内,生成一个新整型i,对其进行增加操作,遍历数组,如果下标为i的元素等于要找的x,则返回下标i,如果没找到则返回-1;

顺序表在pos位置插入x
void SeqListInsert(SQ* ps, size_t pos, SLDateType x)
{
	assert(ps);
	assert(pos <= ps->size);

	CheckCacpity(ps);

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


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

断言ps,断言下标pos不能小于size,开辟一个待插入的新空间

while循环将pos小标之后的元素集体向后移动一位,

最后留下pos位置置为x,size增加1;

顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos)
{
	assert(ps && pos < ps->size);

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

	ps->size--;
}

断言,start是pos的下一个;

循环前置,pos之后的数据集体向前覆盖,把pos覆盖,最后size--,表示原数组最后一位不在读取。

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值