【数据结构】C语言实现顺序表

news/2024/5/20 10:32:51 标签: 数据结构, c语言, 顺序表

C语言实现顺序表

  • 一、顺序表概念
  • 二、顺序表接口定义
  • 三、顺序表实现
    • 3.1 初始化、销毁与打印
    • 3.2 尾插pushback
    • 3.3 头插pushfront
    • 3.4 尾删popback
    • 3.5 头删popfront
    • 3.6 插入Insert-改写头插尾插
    • 3.7 删除erase-改写头删尾删
    • 3.8 查找Find
    • 3.9 修改Modify
    • 3.10 顺序表测试
  • 四、顺序表存在的问题
  • 五、源码


一、顺序表概念

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

顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储元素。
  2. 动态顺序表:使用动态开辟的数组存储。
// 静态顺序表
// 给小了不够用,给多了浪费
#define N 10000
typedef int SeqListDatatype;
struct SeqList
{
	SeqListDatatype array[N];
	int size;
};
// 动态顺序表
typedef int SeqListDatatype;
typedef struct SeqList
{
	SeqListDatatype* array;
	int size;       // 存储的有效数据的个数
	int capacity;   // 容量
}SeqList;

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

二、顺序表接口定义

// 初始化、销毁
void SeqListInit(SeqList* psl); 
void SeqListDestroy(SeqList* psl);

// 打印顺序表
void SeqListPrint(SeqList* psl);

// 尾插、头插
void SeqListPushBack(SeqList* psl, SeqListDatatype x);
void SeqListPushFront(SeqList* psl, SeqListDatatype x);

// 尾删、头删
void SeqListPopBack(SeqList* psl);
void SeqListPopFront(SeqList* psl);

// 指定位置插入、删除
void SeqListInsert(SeqList* psl, int pos, SeqListDatatype x);
void SeqListErase(SeqList* psl, int pos);

// 查找与修改
int SeqListFind(SeqList* psl, SeqListDatatype x);
void SeqListModify(SeqList* psl, int pos, SeqListDatatype x);

三、顺序表实现

3.1 初始化、销毁与打印

初始化我们预置了4个容量。

void SeqListInit(SeqList* psl)
{
	assert(psl);
	psl->array = (SeqListDatatype*)malloc(sizeof(SeqListDatatype) * 4);
	if (psl->array == NULL)
	{
		perror("malloc fail");
		return;
	}

	psl->capacity = 4;
	psl->size = 0;
}
void SeqListDestroy(SeqList* psl)
{
	assert(psl);
	free(psl->array);
	psl->array = NULL;
	psl->size = 0;
	psl->capacity = 0;
}
void SeqListPrint(SeqList* psl)
{
	assert(psl);
	for (int i = 0; i < psl->size; i++)
	{
		printf("%d ", psl->array[i]);
	}
	printf("\n");
}

3.2 尾插pushback

插入之前都要检查容量。

void SeqListPushBack(SeqList* psl, SeqListDatatype x)
{
	assert(psl);

	SeqListCheckCapacity(psl);

	psl->array[psl->size++] = x;
}

3.3 头插pushfront

插入之前都要检查容量。

void SeqListPushFront(SeqList* psl, SeqListDatatype x)
{
	assert(psl);

	SeqListCheckCapacity(psl);

	// 挪动数据
	int end = psl->size - 1;
	while (end >= 0)
	{
		psl->array[end + 1] = psl->array[end];
		--end;
	}

	psl->array[0] = x;
	psl->size++;
}

3.4 尾删popback

void SeqListPopBack(SeqList* psl)
{
	assert(psl);
	assert(psl->size > 0);

	psl->size--;
}

3.5 头删popfront

void SeqListPopFront(SeqList* psl)
{
	assert(psl);
	assert(psl->size > 0);

	/*int start = 0;
	while (start < psl->size-1)
	{
		psl->array[start] = psl->array[start + 1];
		start++;
	}*/

	int start = 1;
	while (start < psl->size)
	{
		psl->array[start - 1] = psl->array[start];
		start++;
	}

	psl->size--;
}

3.6 插入Insert-改写头插尾插

插入之前都要检查容量。

void SeqListInsert(SeqList* psl, int pos, SeqListDatatype x)
{
	assert(psl);
	assert(0 <= pos && pos <= psl->size);

	SeqListCheckCapacity(psl);

	int end = psl->size - 1;
	while (end >= pos)
	{
		psl->array[end + 1] = psl->array[end];
		--end;
	}

	psl->array[pos] = x;
	psl->size++;
}
void SeqListPushBack(SeqList* psl, SeqListDatatype x)
{
	assert(psl);

	SeqListInsert(psl, psl->size, x);
}
void SeqListPushFront(SeqList* psl, SeqListDatatype x)
{
	assert(psl);

	SeqListInsert(psl, 0, x);
}

3.7 删除erase-改写头删尾删

void SeqListErase(SeqList* psl, int pos)
{
	assert(psl);
	assert(0 <= pos && pos < psl->size);

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

	psl->size--;
}
void SeqListPopBack(SeqList* psl)
{
	assert(psl);
	assert(psl->size > 0);

	SeqListErase(psl, psl->size - 1);
}
void SeqListPopFront(SeqList* psl)
{
	assert(psl);
	assert(psl->size > 0);

	SeqListErase(psl, 0);
}

3.8 查找Find

查找成功返回元素所在下标,查找失败返回-1。

int SeqListFind(SeqList* psl, SeqListDatatype x)
{
	assert(psl);

	for (int i = 0; i < psl->size; i++)
	{
		if (psl->array[i] == x)
		{
			return i;
		}
	}

	return -1;
}

3.9 修改Modify

如果修改位置合法直接修改为指定元素。

void SeqListModify(SeqList* psl, int pos, SeqListDatatype x)
{
	assert(psl);
	assert(0 <= pos && pos < psl->size);

	psl->array[pos] = x;
}

3.10 顺序表测试

int main(int argc, char* argv[]) {
	
	TestSeqList();

	printf("bye bye\n");
	return 0;
}

void TestSeqList()
{
	SeqList sl;
	SeqListInit(&sl);

	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPushBack(&sl, 6);
	SeqListPrint(&sl); // 1 2 3 4 5 6

	SeqListPopFront(&sl);
	SeqListPrint(&sl); // 2 3 4 5 6

	int pos = SeqListFind(&sl, 6);
	if (pos != -1)
	{
		SeqListErase(&sl, pos);
	}
	SeqListPrint(&sl); // 2 3 4 5

	SeqListDestroy(&sl);
}

四、顺序表存在的问题

问题:

  1. 中间/头部的插入删除,时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

如何解决以上问题呢?链表

五、源码

gitee地址


http://www.niftyadmin.cn/n/230805.html

相关文章

【密码算法 之七】GCM 浅析

文章目录1. 概述1.1 GHASH1.3 GCTR2. GCM 加密3. GCM 解密4. 总结在我的另一篇博客【密码算法 之三】分组密码工作模式 &#xff08;ECB \ CBC \ CFB \ OFB \ CTR \ XTS&#xff09;浅析 中已经详细的介绍了对称算法&#xff08;也称为“分组密码算法”&#xff09;的各种工作模…

小黑子—Java从入门到入土过程:第七章

Java零基础入门7.0Java系列第七章1. 游戏打包exe2. API2.1 Math2.2 练习2.2.1 判断质数2.2.2 判断水仙花数&#xff08;自幂数&#xff09;2.3 System2.4 Runtime2.5 Object2.5.1 Object 的成员方法(1) toString(2) equals 比较两个对象是否相等(3) clone方法&#xff08;Objec…

django进阶DRF

一、FBV与CBV FBV def login(request): if request.method "GET": return else: return CBV from django.view import View class LoginView(View) : def get(self,request): pass def post(self,request): pass 二、前后端分离模式 三、

Docker环境安装

Docker环境安装Docker简介Docker工作原理Docker的应用场景Docker 的优点CentOS Docker 安装与配置Docker 安装Docker 配置Docker容器概念Docker容器操作拉取镜像删除镜像容器相关命令创建并启动容器停止和恢复容器删除容器Docker简介 Docker 是一个开源的应用容器引擎&#xf…

JVM指令手册

指令码 助记符 说明 0x00 nop 什么都不做 0x01 aconst_null 将null推送至栈顶 0x02 iconst_m1 将int型-1推送至栈顶 0x03 iconst_0 将int型0推送至栈顶 0x04 iconst_1 将int型1推送至栈顶 0x05 iconst_2 将int型2推送至操作数栈顶 0x06 iconst_3 将int型3推送至栈顶 0x07 icons…

【数据结构启航!】数据结构开胃菜之顺序表

【数据结构启航&#xff01;】数据结构开胃菜之顺序表一、线性表简介二、目标三、实现1、初始化工作2、顺序表的尾插2.1、图解原理2.2、代码实现3、顺序表的尾删3.1、图解原理3.2、代码实现4、打印顺序表5、顺序表的增容6、顺序表的头插6.1、图解原理6.2、代码实现7、顺序表的头…

如何驱动模拟舵机-Controller 1.0b软件的使用

1.支持平台 win10、win7 win10打开Controller 1.0.exe即可运行&#xff1b;win7需要先安装Controller1.0b资料包\NetFarmwork文件夹中的.net框架组件。 2.电子硬件 我们用以下硬件为例来讲解Controller 1.0b软件的使用&#xff1a; 主控板 Basra主控板&#xff08;兼容Arduino…

Javascript cookie和session

在网站中&#xff0c;http请求是无状态的&#xff0c;当我们与服务端做一次数据请求&#xff0c;请求完毕后&#xff0c;第二次数据请求服务器端仍然不知道是哪个用户&#xff0c;cookie的出现就是为了解决这个问题。 一 Session与Cookie的区别 1 相同点 它们都是用于存…