C语言实现顺序表(增,删,改,查)

news2024/11/16 8:25:02

目录

一.概念:

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

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

二.顺序表的实现:

1.顺序表增加元素

1.检查顺序表

2.头插

3.尾插

2.顺序表删除元素

1.头删

2.尾删

3.指定位置删

3.顺序表查找元素

4.顺序表修改元素

1.指定位置修改:

顺序表的问题:


数据结构和算法概述-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/lh11223326/article/details/136221673

一.概念:

顺序表在数据结构中是线性表的一种。

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

顺序表可以分为:

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

#include<stdio.h> 
#define N 7
 typedef int SLDataType;
 typedef struct SeqList
 {
    SLDataType array[N];//定长数组
    size_t size;//有效数据的个数
 }SeqList;

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

#include<stdio.h>
 typedef struct SeqList{//顺序表的动态存储
    SLDataType*array;//指向动态开辟的数组
    size_t size;//有效数据个数
    size_t capicity;//容量空间的大小
 }SeqList;

二.顺序表的实现:

一般来说我们写大型程序的时候会把声明跟引入文件放在一个头文件中如下,创建一个SeqList.h文件把下列代码放入:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//动态顺序表
typedef int SLDataType;

typedef struct SeqList {
	SLDataType* a;//去堆上动态开辟,用来指向动态开辟的数组
	int size;//存储的有效数据个数
	int capacity;//空间大小
}SL;

//对顺序表进行管理:增删查改
void SLInit(SL *ps);//顺序表初始化
void SLDestroy(SL *ps);//顺序表销毁
void SLPrint(SL* ps);
void SLCheckCapacity(SL* ps);

//头插头删,尾插尾删
void SLPushBack(SL* ps, SLDataType x);//后插
void SLPopBack(SL* ps);//后删
void SLPushFront(SL* ps, SLDataType x);//头插
void SLPopFront(SL* ps);//头删

//返回下标,没有找到返回-1
//找数据
int SLFind(SL* ps, SLDataType x);
//在指定位置插入x
void SLInsert(SL* ps,int pos,SLDataType x );
//删除指定位置的值
void SLErase(SL* ps, int pos);
//修改坐标处的元素
void SLModify(SL* ps, int pos, SLDataType x);

1.顺序表增加元素

在增加元素之前需要初始化顺序表,此时需要使用malloc创建一块空间,代码如下:

void SLInit(SL *ps) {//顺序表的初始化
	assert(ps);
	ps->a = (SLDataType*)malloc(sizeof(SLDataType)*4);
	if (ps->a==NULL) {

		perror("malloc failed");
		exit(-1);//终止程序
	}
	ps->size = 0;
	ps->capacity = 4;
}

1.检查顺序表

如果顺序表满了就需要扩容........................

void SLCheckCapacity(SL* ps) {
	assert(ps);

	//满了要扩容
	if (ps->size == ps->capacity) {
		SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));
		if (tmp == NULL) {
			perror("realloc failed");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
}

2.头插

在头部插入数据之前需要把全部数据都往后移动一位............

void SLPushFront(SL* ps, SLDataType x) {
	assert(ps);

	SLCheckCapacity(ps);

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

3.尾插

在末尾插入数据之前检查一下,如果有数据就是满了先扩容再插入......

void SLPushBack(SL* ps, SLDataType x) {
	assert(ps);

	SLCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}

2.顺序表删除元素

1.头删

void SLPopFront(SL* ps) {
	assert(ps);

	assert(ps->size > 0);
	
	int begin = 1;
	while (begin < ps->size) {
		ps->a[begin - 1] = ps->a[begin];
		++begin;
	}
	ps->size--;
}

2.尾删

直接把有效数据个数减一就行了...........

void SLPopBack(SL* ps) {
	assert(ps);

	assert(ps->size > 0);
	ps->size--;
}

3.指定位置删

把数据删除之后把数据都移前面补全.........

void SLErase(SL* ps, int pos) {
	assert(ps);

	assert(pos >= 0 && pos < ps->size);
	int begin = pos + 1;
	while (begin < ps->size) {
		ps->a[begin - 1] = ps->a[begin];
		++begin;
	}
	ps->size--;
}

3.顺序表查找元素

把每个数据都比对一遍然后返回下标.........

int SLFind(SL* ps, SLDataType x) {
	assert(ps);

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

4.顺序表修改元素

代码的位置是用户指定下标位置的修改:

void SLModify(SL* ps, int pos, SLDataType x) {
	assert(ps);

	assert(pos >= 0 && pos < ps->size);
	ps->a[pos] = x;
}

1.指定位置修改:

从指定位置的最后面把每个数据都后移一位,不要从前面往后面移,要从后往后,移动完数据之后就可以在指定位置添加了......

void SLInsert(SL* ps, int pos, SLDataType x) {
	assert(ps);

	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);

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

如下是SeqList.c中全部实现函数代码:

#include"SeqList.h"
void SLInit(SL *ps) {//顺序表的初始化
	assert(ps);
	ps->a = (SLDataType*)malloc(sizeof(SLDataType)*4);
	if (ps->a==NULL) {

		perror("malloc failed");
		exit(-1);//终止程序
	}
	ps->size = 0;
	ps->capacity = 4;
}
void SLDestroy(SL *ps)//顺序表的销毁
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

void SLPrint(SL* ps) {
	assert(ps);

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

void SLCheckCapacity(SL* ps) {
	assert(ps);

	//满了要扩容
	if (ps->size == ps->capacity) {
		SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));
		if (tmp == NULL) {
			perror("realloc failed");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
}


void SLPushBack(SL* ps, SLDataType x) {
	assert(ps);

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

void SLPopBack(SL* ps) {//
	assert(ps);

	//直接报错 暴力检查
	assert(ps->size > 0);
	ps->size--;

	//就是无效删除退出 检查
	/*if (ps->size == 0) {
		return;
	}*/
}
void SLPushFront(SL* ps, SLDataType x) {
	assert(ps);

	SLInsert(ps, 0, x);
}
void SLPopFront(SL* ps) {
	assert(ps);

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

int SLFind(SL* ps, SLDataType x) {
	assert(ps);

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


//在指定位置插入x
void SLInsert(SL* ps, int pos, SLDataType x) {
	assert(ps);

	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);

	int end = ps->size - 1;
	while (end>=pos) {
		ps->a[end + 1] = ps->a[end];
		--end;
	}
	ps->a[pos] = x;
	ps->size++;
}
//删除指定位置的值
void SLErase(SL* ps, int pos) {
	assert(ps);

	assert(pos >= 0 && pos < ps->size);
	int begin = pos + 1;
	while (begin < ps->size) {
		ps->a[begin - 1] = ps->a[begin];
		++begin;
	}
	ps->size--;
}

void SLModify(SL* ps, int pos, SLDataType x) {
	assert(ps);

	assert(pos >= 0 && pos < ps->size);
	ps->a[pos] = x;
}

最后可以自行设计一个界面:

顺序表的问题:

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

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

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

相关文章

就业班 第二阶段 2401--3.25 day5 mycat读写分离

[TOC] 启动并更改临时密码 [rootmysql1~]# systemctl start mysqld && passwdgrep password /var/log/mysqld.log | awk END{ print $NF} && mysqladmin -p"$passwd" password Qwer123..; MyCAT读写分离 Mycat 是一个开源的数据库系统&#xff0c;但…

线程安全集合类原理

一、ConcurrentHashMap (一)、HashMap 1、JDK7 并发死链 采用头插法 扩容源码(扩容时并没有创建新的节点&#xff0c;只是将引用挂在不同的地方) void transfer(Entry[] newTable, boolean rehash) {int newCapacity newTable.length;for (Entry<K,V> e : table) {…

俚语加密漫谈

俚语加密是一种古老而有效的通信方式&#xff0c;将特定词语或短语在群体内赋予特殊含义&#xff0c;从而隐藏真实信息。类似于方言&#xff0c;它在历史上的应用不可忽视。随着计算机时代的到来&#xff0c;现代密码学通过数学运算编织密语&#xff0c;使得加密变得更加高深莫…

大数据开发(离线实时音乐数仓)

大数据开发&#xff08;离线实时音乐数仓&#xff09; 一、数据库与ER建模1、数据库三范式2、ER实体关系模型 二、数据仓库与维度建模1、数据仓库&#xff08;Data Warehouse、DW、DWH&#xff09;1、关系型数据库很难将这些数据转换成企业真正需要的决策信息&#xff0c;原因如…

【Java多线程】1——多线程知识回顾

1 多线程知识回顾 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记仓库&#x1f449;https://github.com/A-BigTree/tree-learning-notes 个人主页&#x1f449;https://www.abigtree.top ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star…

web 技术中前端和后端交互过程

1、客户端服务器交互过程 客户端:上网过程中,负责浏览资源的电脑,叫客户端服务器:在因特网中,负责存放和对外提供资源的电脑叫服务器 服务器的本质: 就是一台电脑,只不过相比个人电脑它的性能高很多,个人电脑中可以通过安装浏览器的形式,访问服务器对外提供的各种资源。 个人…

【每日一题】2580. 统计将重叠区间合并成组的方案数-2024.3.27

题目&#xff1a; 2580. 统计将重叠区间合并成组的方案数 给你一个二维整数数组 ranges &#xff0c;其中 ranges[i] [starti, endi] 表示 starti 到 endi 之间&#xff08;包括二者&#xff09;的所有整数都包含在第 i 个区间中。 你需要将 ranges 分成 两个 组&#xff0…

【数据结构】 HashMap源码分析(常量+构造方法+方法)

文章目录 HashMap源码分析一、成员常量二、构造方法三、方法1.此时假定为进行了无参构造&#xff0c;没有分配内存2.当发生有参构造时&#xff0c;完成对容量的大小判断后&#xff0c;将容量大小&#xff0c;传进tableSizeFor方法中&#xff1a; HashMap源码分析 一、成员常量…

【物联网开源平台】tingsboard安装与编译

别看这篇了&#xff0c;这篇就当我的一个记录&#xff0c;我有空我再写过一篇&#xff0c;编译的时候出现了一个错误&#xff0c;然后我针对那一个错误执行了一个命令&#xff0c;出现了绿色的succes,我就以为整个tingsboard项目编译成功了&#xff0c;后面发现的时候&#xff…

如何本地部署开源AI知识库 FastGPT(新手教程)

环境: Win10 WSL2 ubuntu22.04 问题描述: 如何本地部署开源AI知识库 FastGPT 解决方案: 一、安装docker和docker-compose 安装docker 1.apt install docker.io2.apt install docker-compose3.docker --version4.docker compose version

[操作系统课设]GeeKOS操作系统的研究与实现

一.GeekOS操作系统概论 1.1教学操作系统 &#xff08;1&#xff09;针对RISC结构MIPS处理器 操作系统&#xff1a;Nachos、OS/161 &#xff08;2&#xff09;针对CISC结构Intel IA-32 (or x86)通用处理 操作系统&#xff1a;MINIX、GeekOS 我们用到的是&#xff1a;GeekOS 1&…

Java八股文(SpringCloud Alibaba)

Java八股文のSpringCloud Alibaba SpringCloud Alibaba SpringCloud Alibaba Spring Cloud Alibaba与Spring Cloud有什么区别&#xff1f; Spring Cloud Alibaba是Spring Cloud的衍生版本&#xff0c;它是由Alibaba开发和维护的&#xff0c;相比于Spring Cloud&#xff0c;它在…

C++初学者:像C#一样优雅写程序

C语言的强大&#xff0c;在于自由自在&#xff0c;你可以随便怎么写程序&#xff0c;不讲格式&#xff0c;可以很整齐&#xff0c;也可以鬼画符&#xff0c;只要能运行就可以了&#xff0c;程序员可以自由发挥。 如图&#xff1a; 国际C语言大赛中的代码 图2 C的语言更强大&…

关于振弦式渗压计的基本知识详解

振弦式渗透压力计的组成主要包括振弦、高灵敏度金属薄膜、渗透石以及激励和接收线圈等。其运作机制是&#xff1a;水压力施加在金属薄膜上导致其形变&#xff0c;进而影响连接的钢弦的拉力。由于钢弦振动频率与其拉力密切相关&#xff0c;通过测量钢弦的频率变化即可计算出渗透…

大白话扩散模型(无公式版)

背景 传统的图像生成模型有GAN&#xff0c;VAE等&#xff0c;但是存在模式坍缩&#xff0c;即生成图片缺乏多样性&#xff0c;这是因为模型本身结构导致的。而扩散模型拥有训练稳定&#xff0c;保持图像多样性等特点&#xff0c;逐渐成为现在AIGC领域的主流。 扩散模型 正如…

LVGL线条和画布功能

线条部件 线条部件由多个点连接而成&#xff0c;它可用于修饰界面或者展示数据。 要注意这里的描述&#xff0c;线条是由多个点连接而成的。 线条部件只有一个组成部分&#xff1a;主体 LV_PART_MAIN 线条是由多个点连接而成的对象&#xff0c;用户可以使用 lv_point_t 类型的…

C++电子宠物商店

一、功能描述 店内有不同类型的电子宠物 1.每种电子宠物能通过显示出来的文本提出需要或表示情绪如&#xff1a;饿、渴、饱涨、困、不舒服、高兴、生气、伤心、绝望、无聊等。 2.店员用户通过键盘操作“饲养”电子宠物&#xff0c;给它实施喂饭、喂水、带它上厕所、陪它玩耍、…

OpenCV4.9在iOS中安装

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;使用CUDA 为Tegra构建OpenCV-CSDN博客 下一篇&#xff1a; 警告&#xff01; 本教程可以包含过时的信息。 所需软件包 CMake 2.8.8 或更高版本Xcode 4.2 或更高版本 从 G…

【QT入门】 Qt代码创建布局之多重布局变换与布局删除技巧

往期回顾&#xff1a; 【QT入门】 Qt代码创建布局之栅格布局详解-CSDN博客 【QT入门】 Qt代码创建布局之分裂器布局详解-CSDN博客 【QT入门】 Qt代码创建布局之setLayout使用-CSDN博客 【QT入门】 Qt代码创建布局之多重布局变换与布局删除技巧 一、最终效果 我们先看最终要实…

【前端学习——css篇】1.css的盒模型

https://github.com/febobo/web-interview 1.css的盒模型 html中的所有元素都是一个盒子&#xff0c;组成包括&#xff1a;内容content、内边距padding、边框border、外边距margin content&#xff0c;即实际内容&#xff0c;显示文本和图像 boreder&#xff0c;即边框&#…