顺序表 增删查(找)

这里写目录标题

序言

在敲代码之前我们应该设置三个文件
在这里插入图片描述
类似于工程一样的 这样显得比较有层次性
我先说明一下待会儿需要写的函数

#pragma once 
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;//储存数据的个数
	int capacity;//存储空间的大小
}SL,SeqList;
void SeqListPrint(SeqList* psl);//打印顺序表
void SeqListInit(SeqList* psl);//初始化						
void SeqListDestroy(SeqList* psl);//销毁
void SeqListCheckCapacity(SeqList* psl);//检查顺序表是否满
void SeqListPushBack(SeqList* psl, SLDateType x);//在顺序表尾插入一个元素
void SeqListPopBack(SeqList* psl);//弹出一个元素
void SeqListPushFront(SeqList* psl, SLDateType x);//头插
void SeqListPopFront(SeqList* psl);//头删
void SeqListInsert(SeqList* psl, size_t pos, SLDateType x);//在pos的位置插入元素x
void SeqListErase(SeqList* psl, size_t pos);//删除pos位置的元素
int SeqListFind(SeqList* psl,SLDateType x);//查找

**注:一定要加一个#pragma once
#pragma once是一个比较常用的C/C++预处理指令,只要在头文件的最开始加入这条预处理指令,就能够保证头文件只被编译一次。
因为我们在后面还有两个.c文件 一个是执行的文件,应该是函数的定义文件

介绍一下我们整个顺序表的结构体

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;//储存数据的个数
	int capacity;//存储空间的大小
}SL,SeqList;

刚开始初始化顺序表

void SeqListInit(SeqList* psl)//初始化	
{
	assert(psl);//断言一定是不能忘记的忘记了后果很严重
	psl->a = NULL;
	psl->size = 0;
	psl->capacity = 0;
}

assert:表示断言 可以简单理解一下:其作用是如果它的条件返回错误,则终止程序执行。是终止程序运行 只要不符合括号里面的条件,那么便会终止程序,初始化中的assert(psl)表示如果是空指针便终止程序运行

再来学习一下顺序表的销毁

void SeqListDestroy(SeqList* psl)//销毁
{

	assert(psl);
	free(psl->a);
	psl->a = NULL;//防止a成为野指针
	psl->capacity = psl->size = 0;


}

需要注意的点是在free动态开辟的内存后必须记得将前一个地址也就是a赋值为空指针 不然a就会变成一个野指针,要养成这个习惯。

打印顺序表没什么好说的

void SeqListPrint(SeqList* psl)  //打印顺序表          
{
	assert(psl);
	for (int i = 0; i < psl->size; i++)
		printf("%d ", psl->a[i]);
	printf("\n");
}

头插 ,尾插 与在某个位置插入

头插:
在插入之前,我们要做一件事情,判断顺序表是否满了,由于我的顺序表是动态开辟的,不是静态的,所以我们应该要查找一下是否满

void SeqListCheckCapacity(SeqList* psl)//检查顺序表是否满
{
	assert(psl);

	if (psl->size == psl->capacity)
	{
		size_t newCapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
		SLDateType* tmp = (SLDateType *)realloc(psl->a, sizeof(SeqList) * newCapacity);
		if (tmp==NULL)
		{
			printf("realloc fail\n");
			exit(-1);//这边的弹出是直接退出整个程序 但是return 就是退出这个函数

		}
		else
		{
			psl->a = tmp;
			psl->capacity = newCapacity;//容量也应该是变得呀!!!
		}
	}
}

查是否满在接下来还会用到,所以直接封装成一个函数较好
这边强调两个东西
realloc:表示的是在原来的地址上动态扩容,如果原来的地址为空,那么功能作用就类似于malloc
在这里插入图片描述

exit(-1);//这边的弹出是直接退出整个程序 但是return 就是退出这个函数

头插的原理简单讲一下
头插就是在顺序表元素为0的地址插入 然后其他元素依次后退一格
在这里插入图片描述

void SeqListPushFront(SeqList* psl, SLDateType x)//头插
{
	assert(psl);//1 2 3 6 4 8 6   
	SeqListCheckCapacity(psl);
		int end = psl->size;
		while (end > 0)
		{
			psl->a[end] = psl->a[end - 1];
			end--;
		}
		psl->a[0] = x;
		psl->size++;
	//SeqListInsert(psl, 0, x);

}

头插结束了 尾插更是简单 原理相似 也是线检查是否应该扩容

void SeqListPushBack(SeqList* psl, SLDateType x)//在顺序表尾插入一个元素
{
	assert(psl);  
	SeqListCheckCapacity(psl);
		psl->a[psl->size] = x;
		psl->size++;

}

在某个位置插入
一定要先判断一下插入位置的合理性 所以应该先断言 合理的位置应该是0-size
其余的话我们可以类比头插 头插是位置0 后的元素一次往后挪动 现在是某个位置后的元素往后挪动

void SeqListInsert(SeqList* psl, size_t pos, SLDateType x)//在pos的位置插入元素x
{
	assert(psl);
	assert(pos <= psl->size);
	SeqListCheckCapacity(psl);
	int end = psl->size;
	while (end > pos)
	{
		psl->a[end] = psl->a[end - 1];
		end--;
	}
	psl->a[pos] = x;
	psl->size++;

}

总结:所以插入之前都必须判断是否需要扩容 即size==capacity!
提升:
因此我们头插可以写成在位置为0插入x 跟头插功能相似
头插可以这样写

void SeqListPushFront(SeqList* psl, SLDateType x)//头插
{
	assert(psl);//1 2 3 6 4 8 6   
	//SeqListCheckCapacity(psl);
	//	int end = psl->size;
	//	while (end > 0)
	//	{
	//		psl->a[end] = psl->a[end - 1];
	//		end--;
	//	}
	//	psl->a[0] = x;
	//	psl->size++;
	SeqListInsert(psl, 0, x);

}

头删 尾删 在某个位置删除元素

插入的时候我们都应该要判断是否需要扩容,同理,在删除的时候,我们应该要判断此时顺序表中是否有元素即size是否大于0
首先是头删

void SeqListPopFront(SeqList* psl)//头删
{
	assert(psl);
	//1 2 3 6 4 8 6   
	if (psl->size > 0)
	{
		int end = 1;
		while (end < psl->size)
		{
			psl->a[end-1] = psl->a[end];
			end++;
		}
		psl->size--;
	}
	//SeqListErase(psl, 0);

}

尾删

void SeqListPopBack(SeqList* psl)//弹出顺序表尾一个元素
{
	assert(psl);
	if (psl->size > 0)
	{
		psl->size--;

	}
}

这边简单说明一下 为什么直接size–
因为我们遍历的时候直接到size为止 后面是啥我们不关心 所以可以直接这样
在某个位置删除

与上面的在某个位置插入一样 我们删除的位置应该合理 合理的区域应该是0到size-1; 只要删除后元素的移动原理和插入刚好相反

void SeqListErase(SeqList* psl, size_t pos)//删除pos位置的元素
{
	assert(psl);//1 2 3 6 4 8 6
	assert(pos < psl->size);
	if (psl->size > 0)
	{
		int begin = pos;
		while (begin < psl->size-1)
		{
			psl->a[begin] = psl->a[begin + 1];
			begin++;
		}
		psl->size--;
	}

}
查(找)

没啥好说的

int  SeqListFind(SeqList* psl, SLDateType x)//查找
{
	assert(psl);
	for (int i = 0; i < psl->size; i++)
	{
		if (psl->a[i] == x)
			return i;
	}
	return -1;
}

自我的一个小总结 不足之处见谅!
链表见!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

每天少点debug

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

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

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

打赏作者

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

抵扣说明:

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

余额充值