初阶数据结构-顺序表

顺序表的概念

  顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组
上完成数据的增删查改。
  顺序表一般可以分为:1. 静态顺序表:使用定长数组存储元素。2. 动态顺序表:使用动态开辟的数组存储。
在这里插入图片描述

接口实现

  静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。

顺序表基本功能

//初始化
void SLInit(SL *ps1);

//销毁
void SLDestroy(SL *ps1);
//打印
void SLPrint(SL* ps1);

//STL命名风格
//尾插
void SLPushBack(SL* ps1, SLDatatype x);
//头插
void SLPushFront(SL* ps1, SLDatatype x);
//尾删
void SLPopBack(SL* ps1);
//头删
void SLPopFront(SL* ps1);

//中间插入
void SLInsert(SL* ps1, int pos, SLDatatype x);
//中间删除
void SLErase(SL* ps1, int pos);

//查找
int SLFind(SL* ps1, SLDatatype x);

//修改
void SLModify(SL* ps1, int pos, SLDatatype x);

静态顺序表的创建

#define N 10
typedef int SLDatatype;

struct Seqlist
{
	SLDatatype a[N];
	int size;
};

动态顺序表的创建

typedef int SLDatatype; 
typedef struct SeqList
{
	SLDatatype* a;
	int size;//存储的有效数据的个数
	int capacity; //容量
}SL;

顺序表的初始化

对指针初始化为空,数据个数初始化为0,数据容量动态开辟初始化为4

void SLInit(SL* ps1)
{
	ps1->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);
	if (ps1->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps1->capacity = 4;
	ps1->size = 0;
}

顺序表的销毁

对指针置空,数据个数置0,数据容量置0

void SLDestroy(SL* ps1)
{
	free(ps1->a);
	ps1->a=NULL;
	ps1->size = 0;
	ps1->capacity = 0;
}

顺序表的打印

对顺序表的所有数据进行打印

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

顺序表的检查容量函数

如果数据个数等于数据容量,用realloc进行2倍扩容

void SLCheckCapacity(SL* ps1)
{
	if (ps1->size == ps1->capacity)
	{
		SLDatatype* tmp = (SLDatatype*)realloc(ps1->a, sizeof(SLDatatype) * ps1->capacity* 2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps1->a = tmp;
		ps1->capacity *= 2;
	}
}

顺序表的尾插

在这里插入图片描述
将数据放到最后一个数据后面,再将size++

void SLPushBack(SL* ps1, SLDatatype x)
{
	//ps1->a[ps1->size] = x;
	//ps1->size++;

	/*SLCheckCapacity(ps1);
	ps1->a[ps1->size++] = x;*/
	SLInsert(ps1, ps1->size, x);
}

顺序表的头插

在这里插入图片描述
将end从后往前挪动数据,最后将数据放到第一个位置

void SLPushFront(SL* ps1, SLDatatype x)
{
	//SLCheckCapacity(ps1);
	挪动数据
	//int end = ps1->size - 1;
	//while (end >= 0)
	//{
	//	ps1->a[end + 1] = ps1->a[end];
	//	--end;
	//}
	//ps1->a[0] = x;
	//ps1->size++;
	SLInsert(ps1, 0, x);
}

顺序表的尾删

在这里插入图片描述
直接对size–

void SLPopBack(SL* ps1)
{
	暴力检查
	//assert(ps1->size > 0);
	温柔的检查
	if (ps1->size == 0)
	//	//return;
	ps1->a[ps1->size - 1] = 0;
	//ps1->size--;

	SLErase(ps1, ps1->size - 1);
}

顺序表的头删

在这里插入图片描述
用后面的数据来覆盖前面的数据,直到start到size-2的位置

void SLPopFront(SL* ps1)
{
	暴力检查
	//assert(ps1->size > 0);
	///*int start = 0;
	//while (start < ps1->size-1)
	//{
	//	ps1->a[start - 1] = ps1->a[start];
	//	start++;
	//}*/

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

	SLErase(ps1, 0);
}

顺序表的中间插入

在这里插入图片描述
从end位置开始从前往后覆盖,最后在pos位置插入数据

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

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

顺序表的中间删除

在这里插入图片描述
从start后面的一个位置开始往前覆盖数据,直到start为size-1

void SLErase(SL* ps1, int pos)
{
	assert(0 <= pos && pos < ps1->size);
	//assert(ps1->size > 0);

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

顺序表的查找

找到返回下标,没有找到返回-1

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

顺序表的修改

对pos位置的数据进行修改

void SLModify(SL* ps1, int pos, SLDatatype x)
{
	assert(0 <= pos && pos < ps1->size);
	ps1->a[pos] = x;
}

顺序表的测试主函数

void menu()
{
	printf("********************************\n");
	printf("*****1.尾插数据 2.尾删数据******\n");
	printf("*****3.头插数据 4.头删数据******\n");
	printf("*****5.打印数据 -1.退出*********\n");
	printf("********************************\n");
}

int main()
{
	int option = 0;
	SL s;
	SLInit(&s);
	while (option != -1)
	{
		menu();
		printf("请输入你的操作:");
		scanf("%d", &option);
		if (option == 1)
		{
			/*printf("请输入要尾插的数据,以-1结束:");
			int x = 0;
			scanf("%d", &x);
			while (x != -1)
			{
				SLPushBack(&s, x);
				scanf("%d", &x);
			}*/
			int n = 0;
			printf("请输入要尾插的数据个数,再依次输入要插入的数据:");
			scanf("%d", &n);
			int x = 0;
			while (n > 0)
			{
				scanf("%d", &x);
				SLPushBack(&s, x);
				n--;
			}
		}
		else if (option == 5)
		{
			SLPrint(&s);
		}
		else if (option == -1)
		{
			break;
		}
		else
		{
			printf("无此选项,请重新输入");
		}
	}
	SLDestroy(&s);
	//TestSeqList1();
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值