数据结构:顺序表的奥秘

news2025/1/14 20:20:31

🎉个人名片:

🐼作者简介:一名乐于分享在学习道路上收获的大二在校生
🐻‍❄个人主页🎉:GOTXX
🐼个人WeChat:ILXOXVJE

🐼本文由GOTXX原创,首发CSDN🎉🎉🎉
🕊系列专栏:零基础学习C语言----- 数据结构的学习之路
🐓每日一句:如果没有特别幸运,那就请特别努力!🎉🎉🎉
————————————————

🎉文章简介:

🎉本篇文章对   用C语言实现顺序表 学习的相关知识进行分享!🎉

如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作动力的源泉,让我们一起加油,一起奔跑,让我们顶峰相见!!!🎉🎉🎉

目录

一.顺序表的概念及存储结构

1.1储存结构

二.顺序表的实现

一.功能函数的实现

1.初始化函数

2.顺序表的销毁

3.顺序表的打印

4.扩容函数

5.尾插函数

6.尾删函数

7.头插函数

8.头删函数

9.插入函数

10.删除函数

11.查找函数

12.修改函数

三.总代码

四.顺序表的性能分析


一.顺序表的概念及存储结构

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

顺序表可以分为静态顺序表和动态顺序表。

1.1储存结构

静态顺序表:使用定长数组存储元素;

动态顺序表:数组的大小是根据存储的数据个数,如果满了就动态开辟出来的,相对而言不会造成空间的浪费;

二.顺序表的实现

静态顺序表 只适用于确定知道需要存多少数据的场景;

静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。例如:如果数组的大小定为200,却只储存了几十个数据,和动态的顺序表相比,空间浪费更大;所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。

一.功能函数的实现(含图解)

1.初始化函数

功能:对结构体内成员进行初始化操作;

代码实现:

void InitList(SL* s)
{
	assert(s);        //断言,防止传入空指针

	s->a = (SLDateType* )malloc(sizeof(SLDateType) * 4);  
	if (s->a == NULL)   //这里最开始开辟四个存储数据类型的大小
	{
		perror("malloc fail");
		exit(-1);
	}
	s->size = 0;            //存储的有效数据个数为0
	s->capacity = 4;       //空间置成4
}

2.顺序表的销毁

功能:对动态开辟的空间进行销毁,空间释放

代码实现:

void DestoryList(SL* s)
{
	assert(s);

	free(s->a);       //释放动态开辟的空间
	s->a = NULL;      //置空
	s->capacity = s->size = 0;
}

3.顺序表的打印

代码实现:

void SListPrintf(SL* s)
{
	assert(s);

	if (s->size < 0)     //如果没有数据,则直接返回
	{
		return;
	}
	for (int i = 0; i < s->size; i++)
	{
		printf("%d ", s->a[i]);       //遍历依次打印
	}
	printf("\n");        //打印完换行
}

4.扩容函数

功能:检查是否需要扩容

代码实现:

void CheckCapacity(SL* s)
{
	assert(s);

	if (s->capacity == s->size)    //相等则说明空间已经满了
	{
		SLDateType* tmp = realloc(s->a, sizeof(SLDateType)* 2 * s->capacity);  //二倍扩容
		if (tmp == NULL)    
		{
			perror("realloc fail");
			exit(-1);
		}

		s->a = tmp;
		s->capacity *= 2;

	}
}

5.尾插函数

功能:在顺序表最后插入一个数据

代码实现:

void PushBack(SL* s, SLDateType n)
{
	assert(s);

	CheckCapacity(s);  //检查空间是否满
	s->a[s->size] = n;    //直接插入到数组最后
	s->size++;       //有效数据个数++
}

6.尾删函数

功能: 删除顺序表的最后一个数据

代码实现

void PopBack(SL* s)
{
	assert(s);
	assert(s->size > 0);     //当数组中有效数据个数为0时,不能再删除

	s->size--;         //数据个数--

}

7.头插函数

功能:在顺序表最前面插入一个数据

代码实现:

void PushFront(SL* s, SLDateType n)
{
	assert(s);
	CheckCapacity(s);    //检查扩容

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

图解:

性能分析:头插一个数据,首先需要将全部数据一次往后挪一个位置,时间复杂度:O(N)   

是在原数组上进行挪动的,空间复杂度:O(1)

8.头删函数

功能:删除表中第一个元素

代码实现:

void Popfront(SL* s)
{
	assert(s);
	assert(s->size > 0);   //size为0时,不能再删除

	for (int i = 0; i < s->size; i++)
	{
		s->a[i] = s->a[i+1];      //向前挪动数据
	}

	s->size--;
}

图解:

性能分析:头删一个数据,首先需要将全部数据一次往前挪一个位置,将第一个元素覆盖掉,时间复杂度:O(N)   

是在原数组上进行挪动的,空间复杂度:O(1)

9.插入函数

功能:在某个位置插入一个数据

代码实现:


void SListInsert(SL* s, int pos, SLDateType n)
{
	assert(s);
	assert(pos >= 0 && pos <= s->size);    //判断pos合法

	int end = s->size;
	int begin = pos;
	while (begin < end)
	{
		s->a[end] = s->a[end - 1];   //挪动数据
		end--;
	}
	s->a[pos] = n;       //修改数据
	s->size++;
}

图解:

性能分析:中间插入一个数据和头插差不多,首先需要将该位置后面的全部数据依次往后挪一个位置,将该位置空出来,再将该数据插入,时间复杂度:O(N)   

是在原数组上进行挪动的,空间复杂度:O(1)

10.删除函数

功能:删除数组中任何位置的数据

代码实现:

void SListErase(SL* s, int pos)
{
	assert(s);
	assert(pos >= 0 && pos < s->size);    //pos范围合法判断

	int cur = pos;
	while (cur < s->size)
	{
		s->a[cur] = s->a[cur+1];    //挪动位置
		cur++;
	}
	s->size--;

}

图解:

性能分析:删除一个数据与头删差不多,首先需要待删数据位置后面全部数据依次往前挪一个位置,将待删元素覆盖掉,时间复杂度:O(N)   

是在原数组上进行挪动的,空间复杂度:O(1)

11.查找函数

功能:查找顺序表中某个数据,返回下标

代码实现:

int SListFind(SL* s,SLDateType n)
{
	assert(s);

	for (int i = 0; i < s->size; i++)    //遍历寻找
	{
		if (s->a[i] == n)     //找到了返回下标
		{ 
			return i;
		}
	}

	printf("顺序表中无该数据\n");   
	exit(-1);

}

性能分析:将数组中的数据遍历一遍;时间复杂度:O(N)

空间复杂度:O(1)

12.修改函数

功能:修改数组中某个数据

代码实现:

void SListModify(SL* s, int pos,SLDateType n)
{
	assert(s);
	assert(pos >= 0 && pos < s->size);

	s->a[pos] = n;     //直接通过下标访问修改
}

三.总代码

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


typedef int SLDateType;

struct SeqList
{
	SLDateType* a;      //指向一个数组的指针
	int size;           //记录数据个数
	int capacity;       //记录容量,如果与数据个数相等就扩容
};

typedef struct SeqList SL;


void InitList(SL* s);

void SListPrintf(SL* s);

void PushBack(SL* s, SLDateType n);
void PushFront(SL* s, SLDateType n);
void PopBack(SL* s);
void Popfront(SL* s);

int SListFind(SL* s,SLDateType n);

void SListModify(SL* s, int pos, SLDateType n);
void SListErase(SL* s, int pos);
void SListInsert(SL* s, int pos, SLDateType n);


void DestoryList(SL* s);

#include"SeqList.h"



void InitList(SL* s)
{
	assert(s);        //断言,防止传入空指针

	s->a = (SLDateType* )malloc(sizeof(SLDateType) * 4);  
	if (s->a == NULL)   //这里最开始开辟四个存储数据类型的大小
	{
		perror("malloc fail");
		exit(-1);
	}
	s->size = 0;            //存储的有效数据个数为0
	s->capacity = 4;       //空间置成4
}

void SListPrintf(SL* s)
{
	assert(s);

	if (s->size < 0)     //如果没有数据,则直接返回
	{
		return;
	}
	for (int i = 0; i < s->size; i++)
	{
		printf("%d ", s->a[i]);       //遍历依次打印
	}
	printf("\n");        //打印完换行
}


void CheckCapacity(SL* s)
{
	assert(s);

	if (s->capacity == s->size)    //相等则说明空间已经满了
	{
		SLDateType* tmp = realloc(s->a, sizeof(SLDateType)* 2 * s->capacity);  //二倍扩容
		if (tmp == NULL)    
		{
			perror("realloc fail");
			exit(-1);
		}

		s->a = tmp;
		s->capacity *= 2;

	}
}

void PushBack(SL* s, SLDateType n)
{
	assert(s);

	CheckCapacity(s);  //检查空间是否满
	s->a[s->size] = n;    //直接插入到数组最后
	s->size++;       //有效数据个数++
}

void PushFront(SL* s, SLDateType n)
{
	assert(s);
	CheckCapacity(s);    //检查扩容

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

void PopBack(SL* s)
{
	assert(s);
	assert(s->size > 0);     //当数组中有效数据个数为0时,不能再删除

	s->size--;         //数据个数--

}


void Popfront(SL* s)
{
	assert(s);
	assert(s->size > 0);   //size为0时,不能再删除

	for (int i = 0; i < s->size; i++)
	{
		s->a[i] = s->a[i+1];      //向前挪动数据
	}

	s->size--;
}


int SListFind(SL* s,SLDateType n)
{
	assert(s);

	for (int i = 0; i < s->size; i++)    //遍历寻找
	{
		if (s->a[i] == n)     //找到了返回下标
		{ 
			return i;
		}
	}
	printf("顺序表中无该数据\n");   
	exit(-1);
}

void SListModify(SL* s, int pos,SLDateType n)
{
	assert(s);
	assert(pos >= 0 && pos < s->size);

	s->a[pos] = n;     //直接通过下标访问修改
}


void SListErase(SL* s, int pos)
{
	assert(s);
	assert(pos >= 0 && pos < s->size);    //pos范围合法判断

	int cur = pos;
	while (cur < s->size)
	{
		s->a[cur] = s->a[cur+1];    //挪动位置
		cur++;
	}
	s->size--;

}

void SListInsert(SL* s, int pos, SLDateType n)
{

	assert(s);
	assert(pos >= 0 && pos <= s->size);    //判断pos合法

	int end = s->size;
	int begin = pos;
	while (begin < end)
	{
		s->a[end] = s->a[end - 1];   //挪动数据
		end--;
	}

	s->a[pos] = n;       //修改数据
	s->size++;
}


void DestoryList(SL* s)
{
	assert(s);

	free(s->a);       //释放动态开辟的空间
	s->a = NULL;      //置空
	s->capacity = s->size = 0;
}

四.顺序表的性能分析

问题:


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

思考:如何解决以上问题呢?

下一章链表结构就可以解决这个问题;




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1497149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库设计说明书-word

2 数据库环境说明 3 数据库的命名规则 4 逻辑设计 5 物理设计 5.1 表汇总 5.2 表结构设计 6 数据规划 6.1 表空间设计 6.2 数据文件设计 6.3 表、索引分区设计 6.4 优化方法 7 安全性设计 7.1 防止用户直接操作数据库 7.2 用户帐号加密处理 7.3 角色与权限控制 8 数据库管理与维…

高级控件

1.下拉列表 package com.tiger.chapter08;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner;public class Spi…

短视频矩阵系统----矩阵系统源码搭建(技术门槛?)

短视频矩阵是什么意思&#xff1f;短视频矩阵的含义可以理解为全方位的短视频账号&#xff0c;通过不同的账号实现全方位的品牌展示。实际上是指一个短视频账号&#xff0c;通过不同的链接实现品牌展示&#xff0c;在不同的粉丝流量账号中互相转发同一个品牌&#xff0c;在主账…

SemanticKITTI点云地图拼接 SemanticKITTI语义地图

自己用点云分割的预测结果&#xff0c;和里程计的结果拼接出整个轨迹&#xff0c;某种程度上也算是语义语义地图 只需要pcl c就可以&#xff0c;参了以下博主 kitti点云地图拼接_kitti点云拼接-CSDN博客 SemanticKITTI点云拼接PCL可视化_可视化semantickitti .bin-CSDN博客 …

《人工智能怎么学》荣获2023年吴文俊人工智能科学技术奖及赠书活动

中国人工智能学会官网&#xff08;www.caai.cn&#xff09;近日正式公布了2023年吴文俊科学技术奖获奖名单&#xff0c;图书《人工智能怎么学》项目被授予2023年吴文俊人工智能科学技术奖科技进步奖&#xff08;科普项目&#xff09;。2023年吴文俊科学技术奖完整获奖名单见htt…

实现大华摄像头的抓图-使用HTTP方式

实现抓图&#xff0c;网上大部分都是使用SDK二次开发的&#xff0c;HTTP接口实现的基本没有介绍&#xff0c;好像官方叫CUI接口&#xff0c;但是找官方要文档&#xff0c;基本要不到&#xff0c;我自己下载了一份以前的文档&#xff0c;可以做大部分操作&#xff0c;这里免费分…

基于MPPT的太阳能光伏电池simulink性能仿真,对比扰动观察法,增量电导法,恒定电压法

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 扰动观察法 (Perturb and Observe Method) 4.2 增量电导法 (Incremental Conductance Method) 4.3 恒定电压法 (Constant Voltage Method) 5.完整工程文件 1.课题概述 在simulink中&#xff0c;实…

RNN实现退位减法

文章目录 前言RNNRNN架构图前向传播公式反向传播算法 用RNN实现退位减法代码变量的对应关系 总结 前言 最近深入学习了一下RNN&#xff0c;即循环神经网络。RNN是一类比较基础的神经网络&#xff0c;本文使用的是最基础、最简单的循环神经网络的形式。LSTM也是一种常见的循环神…

中大型工厂人员定位系统源码,实现人、车、物的实时位置监控

UWB高精度定位系统源码&#xff0c;中大型工厂人员定位系统&#xff0c;实现人、车、物的实时位置监控 UWB高精度定位系统源码&#xff0c;智慧工厂人员定位系统源码&#xff0c;基于VueSpring boot前后端分离架构开发的一套UWB高精度定位系统源码。有演示。 随着经济的高速发展…

Flink实时数仓同步:切片表实战详解

一、背景 在大数据领域&#xff0c;初始阶段业务数据通常被存储于关系型数据库&#xff0c;如MySQL。然而&#xff0c;为满足日常分析和报表等需求&#xff0c;大数据平台采用多种同步方式&#xff0c;以适应这些业务数据的不同存储需求。 一项常见需求是&#xff0c;业务使用…

潜水耳机哪个牌子好?认准这几个游泳耳机品牌就对了!

在科技日益发达的今天&#xff0c;人们对于运动设备的需求也在不断提升。作为一项独特的水上运动&#xff0c;潜水爱好者们对耳机的要求也越来越高。一款优秀的潜水耳机不仅能够提供卓越的防水性能和舒适度&#xff0c;还必须具备出色的音质。那么&#xff0c;在众多品牌中&…

C语言进阶—表达式求值

隐式类型转换&#xff1a; C 的整型算术运算总是至少以缺省(默认)整型类型的精度来进行的。 为了获得这个精度&#xff0c;表达式中的字符和短整型操作数在使用之前被转换为普通整型&#xff0c;这种转换称为整型提升。 #include <stdio.h>int main() {char c 1;printf(…

鸿蒙Harmony应用开发—ArkTS声明式开发(自定义手势判定)

为组件提供自定义手势判定能力。开发者可根据需要&#xff0c;在手势识别期间&#xff0c;决定是否响应手势。 说明&#xff1a; 从API Version 11开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 onGestureJudgeBegin onGestureJudgeBegi…

C#与python交互(flask发送Get/Post请求)

先运行python&#xff0c;再运行C# **ps: 注意修改端口号**python发送Get/Post请求 # -*- coding: utf-8 -*- # Time : 2024/1/25 15:52 # Author : YY # File : post_test.py # Content&#xff1a;提交数据给客户端 from flask import Flask, request, jsonify, redirect…

Vue系列-环境快速搭建

vue环境快速搭建 演示视频 快速搭建Vue开发环境pnpm和yarn 1. 基本信息 作者: GMCY系列: Vue仓库: GitHub | Gitee话题(GitHub): tools \ vue创建时间: 2024/03/02 2. 介绍 功能 批处理文件vue 环境的快速搭建nodejs, npm, pnpm, yarn 自动 下载安装npm, pnpm, yarn 自动 …

计网:HTTPS协议详解

1、HTTP 与 HTTPS 有哪些区别&#xff1f;​​​ HTTP以明文方式传输数据&#xff0c;不提供任何加密。如果攻击者截取了传输报文&#xff0c;就可以直接读取其中的信息。HTTPS利用SSL/TLS加密数据包&#xff0c;报文以密文方式传输。 HTTP 连接建立相对简单&#xff0c; TCP …

【办公类-22-08】周计划系列(3-3)“信息窗+主题知识(上传+打印)” (2024年调整版本)

作品展示 背景需求&#xff1a; 前文将信息窗主题知识的内容提取并优化结构 【办公类-22-07】周计划系列&#xff08;3-1&#xff09;“信息窗主题知识&#xff08;提取&#xff09;” &#xff08;2024年调整版本&#xff09;-CSDN博客文章浏览阅读803次&#xff0c;点赞7次…

新一代WLAN解决方案与WLAN的配置实现

案例背景为二层旁挂式组网&#xff0c;转发方式为直接转发&#xff0c;管理Vlan为100&#xff0c;业务Vlan为101。 基本配置&#xff1a; SW1&#xff1a; [SW1]VLAN batch 100 101 [SW1-GigabitEthernet0/0/1]port link-type trunk [SW1-GigabitEthernet0/0/1]port trunk a…

SQL 初级

SQL 初级 SQL 简介 SQL (Structured Query Language:结构化查询语言) 是用于管理关系数据库管理系统&#xff08;RDBMS&#xff09;。 SQL 的范围包括数据插入、查询、更新和删除&#xff0c;数据库模式创建和修改&#xff0c;以及数据访问控制。 SQL 是什么&#xff1f; SQL…

【Linux C | 网络编程】多播的概念、多播地址、UDP实现多播的C语言例子

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…