数据结构之顺序表及其实现!

目录

​编辑

[1. 顺序表的概念及结构](#1. 顺序表的概念及结构)

[2. 接口的实现](#2. 接口的实现)

[2.1 顺序表的初始化](#2.1 顺序表的初始化)

[2.2 检查顺序表容量是否已满](#2.2 检查顺序表容量是否已满)

[2.3 顺序表的尾插](#2.3 顺序表的尾插)

​编辑

[2.4 顺序表的尾删](#2.4 顺序表的尾删)

[2.5 顺序表的头插](#2.5 顺序表的头插)

[2.6 顺序表的头删](#2.6 顺序表的头删)

[2.7 顺序表在pos位置插入](#2.7 顺序表在pos位置插入)

[2.8 顺序表在pos位置删除](#2.8 顺序表在pos位置删除)

[2.9 顺序表的查找](#2.9 顺序表的查找)

[2.10 顺序表的销毁](#2.10 顺序表的销毁)

[2.11 顺序表的打印](#2.11 顺序表的打印)

[3. 我在实现顺序表时的测试代码](#3. 我在实现顺序表时的测试代码)

[4. 完结散花](#4. 完结散花)


悟已往之不谏,知来者犹可追

创作不易,宝子们!如果这篇文章对你们有帮助的话,别忘了给个免费的赞哟~

1. 顺序表的概念及结构

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

1. 静态顺序表:用指定长度数组存储元素~


2. 动态顺序表:用动态开辟的数组存储~

2. 接口的实现

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

我们创建一个Test.h里面包含了所有的接口函数声明和各种头文件的声明~

这样我们一个一个实现,正所谓天下难事必做于细~

#define _CRT_SECURE_NO_WARNINGS
#pragma once//避免头文件的多次包含
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SLDataType;//便于类型的改动

//定义一个动态顺序表的结构体变量
typedef struct SeqList
{
	SLDataType* arr;
	size_t num;//记录有效数据的个数
	size_t capacity;//该顺序表的容量大小
}SL;//将该结构体类型重命名为SL

//加入增删查改接口

//1. 顺序表初始化
void SeqListInit(SL* p);

//2. 检查顺序表容量是否已满
void CheckSeqList(SL* p);

//3. 顺序表的尾插
void SeqListPushBack(SL* p, SLDataType x);

//4. 顺序表的尾删
void SeqListPopBack(SL* p);

//5. 顺序表的头插
void SeqListPushFront(SL* p, SLDataType x);

//6. 顺序表的头删
void SeqListPopFront(SL* p);

//7. 顺序表在pos位置插入
void SeqListInsert(SL* p, size_t pos,SLDataType x);

//8. 顺序表在pos位置删除
void SeqListErase(SL* p, size_t pos);

//9. 顺序表的查找
int SeqListFind(SL* p,SLDataType x);//如果该数字存在则返回该数字的下标,否则返回-1

//10 顺序表的销毁
void SeqListDestory(SL* p);

//11. 顺序表的打印
void SeqListPrint(SL* p);

我们将所有函数的实现放在SeqList.c文件中~

2.1 顺序表的初始化

//1. 顺序表初始化
void SeqListInit(SL* p)
{
	assert(p);//判断指针的有效性
	p->arr = NULL;
	p->capacity = 0;
	p->num = 0;
}

注意我们这里一定要传址调用~

2.2 检查顺序表容量是否已满

注释写的很详细了,这里就不做过多的解释~

//2. 检查顺序表容量是否已满
void CheckSeqList(SL* p)
{
	assert(p);//判断指针的有效性
	if (p->num == p->capacity)
	{
		 size_t newcapacity=p->capacity == 0 ? p->capacity = 4 : p->capacity * 2;
		//如果原来没有空间,就给上4,有的话就扩大为原来的两倍
		 SLDataType* ptr = (SLDataType*)realloc(p->arr, newcapacity * sizeof(SLDataType));//动态扩容
		 if (ptr == NULL)
		 {
			 perror("realloc fail;");
			 return;
		 }
		 //也可以用assert断言一下
		 p->arr = ptr;//开辟成功将地址传给arr
		 p->capacity = newcapacity;//更新容量
	}
}

2.3 顺序表的尾插

//3. 顺序表的尾插
void SeqListPushBack(SL* p, SLDataType x)
{
	assert(p);//判断指针的有效性
	CheckSeqList(p);//尾插前先判断有没有容量或容量够不够
	p->arr[p->num] = x;//尾部插入数据
	p->num++;//有效数加一
}

2.4 顺序表的尾删

//4. 顺序表的尾删
void SeqListPopBack(SL* p)
{
	assert(p);//判断指针的有效性
	assert(p->num > 0);//断言存在有效数据
	p->num--;//尾删一个数据
}

2.5 顺序表的头插

//5. 顺序表的头插
void SeqListPushFront(SL* p, SLDataType x)
{
	assert(p);//判断指针的有效性
	CheckSeqList(p);//先判断容量是否满了
	size_t end = p->num;
	while (end)
	{
		p->arr[end] = p->arr[end - 1];//整体向后移动
		end--;
	}
	p->arr[0] = x;//头插
	p->num++;//有效数据加一
}

2.6 顺序表的头删

//6. 顺序表的头删
void SeqListPopFront(SL* p)
{
	assert(p);//判断指针的有效性
	assert(p->num > 0);//有数据才删除
	size_t begin = 1;
	while (begin<p->num)
	{
		p->arr[begin - 1] = p->arr[begin];//整体向前移动
		begin++;
	}
	p->num--;// 有效数据减一

}

整体往前挪,把头覆盖~

2.7 顺序表在pos位置插入

//7. 顺序表在pos位置插入
void SeqListInsert(SL* p, size_t pos, SLDataType x)
{
	assert(p);//判断指针的有效性
	assert(p->num > pos);//pos必须小于num并且大于0
	CheckSeqList(p);//判断容量是否满了
	for (int i = p->num; i >pos-1 ; i--)
	{
		p->arr[i] = p->arr[i - 1];//将pos后面的元素往后挪
	}
	p->arr[pos - 1] = x;//在pos位置加入数据
	p->num++;//有效个数加一
}

2.8 顺序表在pos位置删除

//8. 顺序表在pos位置删除
void SeqListErase(SL* p, size_t pos)
{
	assert(p);//判断指针的有效性
	assert(p->num > pos);//pos必须小于num并且大于0
	assert(p->num > 0);//有数据才能删除
	for (int i = pos; i <p->num; i++)
	{
		p->arr[i-1] = p->arr[i];//将pos后面的元素往后挪
	}
	p->num--;//有效个数减一
}

2.9 顺序表的查找

遍历数组查找~

//9. 顺序表的查找
int SeqListFind(SL* p, SLDataType x)//如果该数字存在则返回该数字的下标,否则返回-1
{
	assert(p);//断言
	for (int i = 0; i < p->num; i++)
	{
		if (p->arr[i] == x)
		{
			return i;//查到返回下标
		}
	}
	return -1;//没有查到
}

2.10 顺序表的销毁

//10 顺序表的销毁
void SeqListDestory(SL* p)
{
	assert(p);//判断指针的有效性
	free(p->arr );//释放动态内存开辟的空间
	p->arr = NULL;
	p->capacity = 0;//容量置为0
	p->num = 0;//有效个数置为0
}

2.11 顺序表的打印

//11. 顺序表的打印
void SeqListPrint(SL* p)
{
	assert(p);//判断指针的有效性
	if (p->num == 0)
	{
		printf("顺序表为空!\n");
		return;
	}
	for (int i = 0; i < p->num; i++)
	{
		printf("%d ", p->arr[i]);//打印数据
	}
	printf("\n");
}

3. 我在实现顺序表时的测试代码

我创建了一个Test.c来测试各个部分的功能~

#define _CRT_SECURE_NO_WARNINGS
#include"Test.h"

void TestSeqList()
{
	SL s1;
	SeqListInit(&s1);//初始化
	SeqListPushBack(&s1, 1);//尾插一个1;
	SeqListPushBack(&s1, 2);//尾插一个2;
	SeqListPushBack(&s1, 3);//尾插一个3;
	SeqListPushBack(&s1, 4);//尾插一个4;
	SeqListPushBack(&s1, 5);//尾插一个5;
	SeqListInsert(&s1, 3, 9);//在第三个位置插入9
	SeqListErase(&s1, 3);//删除第三个位置
	int ret=SeqListFind(&s1, 3);
	if (ret != -1)
		printf("你要查找的数据的下标为:%d\n", ret);
	else
		printf("抱歉,你要查找的数据没有找到!\n");
	//SeqListPopBack(&s1);//尾删一个数据
	//SeqListPushFront(&s1,30);//头插一个数据
	//SeqListPopFront(&s1);//头删一个数据
	SeqListPrint(&s1);//打印数据
}

int main()
{
	//测试顺序表
	TestSeqList();
	return 0;
}

4. 完结散花

好了,这期的分享到 这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

相关推荐
爪哇学长3 分钟前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
爱摸鱼的孔乙己5 分钟前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
永乐春秋11 分钟前
WEB-通用漏洞&SQL注入&CTF&二次&堆叠&DNS带外
数据库·sql
烦躁的大鼻嘎35 分钟前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
打鱼又晒网1 小时前
【MySQL】数据库精细化讲解:内置函数知识穿透与深度学习解析
数据库·mysql
大白要努力!1 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
C++忠实粉丝1 小时前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
tatasix2 小时前
MySQL UPDATE语句执行链路解析
数据库·mysql
南城花随雪。2 小时前
硬盘(HDD)与固态硬盘(SSD)详细解读
数据库
儿时可乖了2 小时前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite