【C项目】顺序表

简介:本系列博客为C项目系列内容,通过代码来具体实现某个经典简单项目
适宜人群:已大体了解C语法同学
作者留言:本博客相关内容如需转载请注明出处,本人学疏才浅,难免存在些许错误,望留言指正
作者博客链接:睡觉待开机

下面是本项目的大体思路梳理:
在这里插入图片描述

引言:

一般来说,顺序表作为基本的数据结构类型是不需要我们进行实现的,因为一些高级语言比如C++或者java直接具备的这样的内置数据结构,但是为了深入了解顺序表的底层,这里也是建议自己动手用C写一下,一是便于复习C学到的知识,二是更加深入了解顺序表的实现底层逻辑。


1.顺序表思路

为了明晰顺序表的实现思路,我们首先来铺垫一下我到底要在怎么写一个顺序表。

首先啥是顺序表?
一种线性表,底层是数组,只不过这个顺序表所谓的数组不单单可以放各种类型的数据,还可以有各种接口,包括增删查改操作的接口等等。

注:线性表的概念:逻辑结构上是连续的,物理结构不一定连续的数据结构称为线性表。

顺序表的概念:逻辑结构上是连续的,物理结构上也是连续的,底层是以数组为实现,有着增删查改各种接口的基本数据组织结构。
在这里插入图片描述


那么我就可以大致明白了我要写一个顺序表,这个顺序表实现了一些功能。

首先我要写一个顺序表的话,要有一个顺序表的大体类型吧,所以我就写了一个动态顺序表的类型

typedef int SLDateType;typedef struct SeqList
{SLDateType* arr;int size;int capacity;
}SL;

在这里插入图片描述

然后我想要在这个顺序表中实现各种功能(接口),那这个顺序表首先得初始化吧,有初始化顺序表了那肯定对应着销毁这个接口,自然也需要顺序表销毁,然后还要有头插尾插任意插入这个”增“的功能,还有有头删尾删任意删的这个”删“的共能,然后还要有查找功能,还要修改功能,那么我针对该顺序表的每个接口专门搞一个函数

为了便于代码书写,我将各种接口以及顺序表类型本身定义在SeqList.h头文件中进行声明与定义:

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>typedef int SLDateType;typedef struct SeqList
{SLDateType* arr;int size;int capacity;
}SL;//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);//顺序表的头部输入/尾部输入
void SLPushBack(SL* ps,SLDateType x);
void SLPushFront(SL* ps, SLDateType x);//顺序表的头部删除/尾部删除
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);//指定位置放入/删除数据
void SLInsert(SL* ps, int pos, SLDateType x);
void SLErase(SL* ps, int pos);//查找数据
int SLFind(SL* ps, SLDateType x);//修改数据
void SLModify(SL* ps, int pos, SLDateType x);

2.具体实现各种接口

顺序表初始化接口:

void SLInit(SL* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->size = 0;
}

顺序表初始化插图:
在这里插入图片描述

顺序表销毁接口:

void SLDestroy(SL* ps)
{assert(ps);if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->capacity = ps->size = 0;
}

顺序表销毁插图:
在这里插入图片描述

顺序表扩容接口:

void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->capacity == ps->size){//小问题:刚开始的时候,sl->capacity是0值int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDateType* temp = realloc(ps->arr,sizeof(SLDateType)*newcapacity);if (!temp){perror("realloc fail!");return;}ps->arr = temp;ps->capacity = newcapacity;}
}

顺序表扩容插图:
在这里插入图片描述

顺序表插入接口

void SLPushBack(SL* ps,SLDateType x)
{assert(ps);//1.空间不足需要扩大容量//2.空间足够直接放入数据SLCheckCapacity(ps);ps->arr[ps->size] = x;ps->size++;
}void SLPushFront(SL* ps, SLDateType x)
{assert(ps);SLCheckCapacity(ps);//挪动数据int i = 0;for (i = ps->size - 1; i >= 0; i--){ps->arr[i+1] = ps->arr[i];}//放入数据*(ps->arr) = x;ps->size++;
}
void SLInsert(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);int i = 0;for (i = ps->size - 1; i >= pos; i--){ps->arr[i+1] = ps->arr[i];}ps->arr[pos] = x;ps->size++;
}

头插的插图:
在这里插入图片描述
尾插的插图:
在这里插入图片描述
任意插入的插图:
在这里插入图片描述

顺序表删除接口:

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);ps->size--;
}void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);int i = 0;for (i = 1; i < ps->size; i++){ps->arr[i-1] = ps->arr[i];}ps->size--;
}
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int i = 0;for (i = pos + 1; i < ps->size; i++){ps->arr[i-1] = ps->arr[i];}ps->size--;
}

头删插图:
在这里插入图片描述
尾删插图:
在这里插入图片描述
任意删插图:
在这里插入图片描述

顺序表查找接口:

int SLFind(SL* ps, SLDateType x)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){if (x == ps->arr[i]){printf("%d找到了:",x);return i;}}printf("没有找到\n");return -1;
}

在这里插入图片描述
顺序表修改接口:

void SLModify(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size - 1);ps->arr[pos] = x;printf("修改成功\n");
}

修改插图:
在这里插入图片描述

3.全部接口代码实现:

#include"SeqList.h"void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->capacity == ps->size){//小问题:刚开始的时候,sl->capacity是0值int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDateType* temp = realloc(ps->arr,sizeof(SLDateType)*newcapacity);if (!temp){perror("realloc fail!");return;}ps->arr = temp;ps->capacity = newcapacity;}
}void SLInit(SL* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->size = 0;
}void SLDestroy(SL* ps)
{assert(ps);if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->capacity = ps->size = 0;
}void SLPrint(SL* ps)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", *(ps->arr + i));//ps->arr[i];}printf("\n");
}void SLPushBack(SL* ps,SLDateType x)
{assert(ps);//1.空间不足需要扩大容量//2.空间足够直接放入数据SLCheckCapacity(ps);ps->arr[ps->size] = x;ps->size++;
}void SLPushFront(SL* ps, SLDateType x)
{assert(ps);SLCheckCapacity(ps);//挪动数据int i = 0;for (i = ps->size - 1; i >= 0; i--){ps->arr[i+1] = ps->arr[i];}//放入数据*(ps->arr) = x;ps->size++;
}void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);ps->size--;
}void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);int i = 0;for (i = 1; i < ps->size; i++){ps->arr[i-1] = ps->arr[i];}ps->size--;
}void SLInsert(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);int i = 0;for (i = ps->size - 1; i >= pos; i--){ps->arr[i+1] = ps->arr[i];}ps->arr[pos] = x;ps->size++;
}void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int i = 0;for (i = pos + 1; i < ps->size; i++){ps->arr[i-1] = ps->arr[i];}ps->size--;
}int SLFind(SL* ps, SLDateType x)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){if (x == ps->arr[i]){printf("%d找到了:",x);return i;}}printf("没有找到\n");return -1;
}void SLModify(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size - 1);ps->arr[pos] = x;printf("修改成功\n");
}

完。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java遍历二叉树,前序遍历、中序遍历、后序遍历

static class TreeNode{int val;TreeNode left;TreeNode right;int deep;}/*** 二叉树的前序遍历&#xff0c;RLR 根左右* param root* param res*/static void accessTree1(TreeNode root,List<Integer> res){if(root null){return;}res.add(root.val);accessTree1(roo…

LeetCode 835. 图像重叠

都知道是枚举行移动 枚举列移动 脑子不清楚 一开始写的很shit&#xff0c;后来动了一下脑子&#xff0c;发现你可以处理行移动&#xff0c;然后在行移动的基础上处理列移动&#xff0c;注意RE问题就行了 class Solution { public:int largestOverlap(vector<vector<int&g…

ElementUI安装与使用指南

Element官网-安装指南 提醒一下&#xff1a;下面实例讲解是在Mac系统演示的&#xff1b; 一、开发环境配置 电脑需要先安装好node.js和vue2或者vue3 安装Node.js Node.js 中文网 安装node.js命令&#xff1a;brew install node node.js安装完后&#xff0c;输入&#xff1…

【Linux C | 网络编程】getsockname 和 getpeername函数详解及C语言例子

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

Qt关于qss文件的添加使用

把ui设计得更加的养眼&#xff0c;肯定需要对控件的属性进行设置&#xff0c;qt中就是关于qss文件的使用。 那么如何创建和添加qss文件呢 1.新建一个文本文件的txt 2.将文本文件的后缀改为qss&#xff08;类比html&#xff09; 3.放置到项目的资源文件夹下 4.添加资源文件 5.在…

推荐系统|排序_MMOE

MMOE MMOE是指Multi-gate Mixture-of-Experts 注意看Expert后面加了s&#xff0c;说明了有多个专家。 而在MMOE中专家是指用来对输入特征计算的神经网络&#xff0c;每个神经网络根据输入计算出来的向量都会有所不同。 MMOE的低层 MMOE的上一层 通过MMOE的低层算出的向量和权…

【排序算法】C语言实现随机快排,巨详细讲解

文章目录 &#x1f680;前言&#x1f680;快排的核心过程partition&#xff08;划分过程&#xff09;&#x1f680;快排1.0&#x1f680;随机快速排序&#x1f680;稳定性 &#x1f680;前言 铁子们好啊&#xff01;继续我们排序算法今天要讲的是快排&#xff0c;通常大家所说…

nop-entropy可逆计算入门(1)

第1步&#xff1a;从大佬的gitee&#xff1a;https://gitee.com/canonical-entropy/nop-entropy下载源码&#xff0c;进行本地编译&#xff0c;具体编译看项目下的readme,想偷懒的可以下载我编译后的jar&#xff0c;放到自己的maven仓库 https://pan.baidu.com/s/15qANnrCh5RV…

C语言字符串操作函数详解①strlen函数的讲解与三种模拟实现方法(建议三连收藏)

目录 ​编辑 前言 1.strlen函数介绍 2.模拟实现strlen 2.1计数器做法 2.2不创建临时变量&#xff0c;通过递归的方法 2.3利用两个指针相减 3.结语 前言 C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量…

Linux文本三剑客-grep

1.grep简介&#xff1a; grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具&#xff0c;它能使用正则表达式搜索文本&#xff0c;并把匹配的行打印出来&#xff0c;都是按行处理的。 grep 最主要…

Linux内核源码

记得看目录哦&#xff01; 1. 为什么要阅读Linux内核2. Linux0.01内核源码3. 阅读linux内核源码技巧4. linux升级内核5. linux的备份和恢复5.1 安装dump和restore5.2 使用dump完成备份5.3 使用restore完成恢复 1. 为什么要阅读Linux内核 2. Linux0.01内核源码 3. 阅读linux内核…

基于Java SSM框架实现影院购票系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现影院购票系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#…