顺序表漫谈

目录

​编辑

1.线性表

2.顺序表

2.1概念及结构

2.2接口实现

1.顺序表的动态存储

2.顺序表初始化

3.顺序表销毁

4.顺序表增容

5.顺序表头插

6.顺序表尾插

7.顺序表头删

8.顺序表尾删

9.顺序表打印

10.顺序表在任意下标位置插入数据

11.顺序表删除任意下标位置的值

12.顺序表查找

2.3菜单

3.源码


1.线性表

  • 线性表(linear list)是n个具有相同特性的数据元素的有限序列。
  • 线性表是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表、链表、栈、队列、字符串...
  • 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。


 

2.顺序表

2.1概念及结构

顺序表是一种线性表的实现方式,它通过一段物理地址连续的存储单元依次存储数据元素,数据元素之间的逻辑关系通过元素在内存中的相对位置来表示,一般情况下采用数组存储。在数组上完成数据的增删查改。

顺序表简单来说就是一个数组,它和数组的唯一区别就是里边的数据只能从头开始连续存储

🌵顺序表一般可以分为:

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

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

2.2接口实现

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

1.顺序表的动态存储

要实现动态的顺序表,我们首先得有一个指向数组的指针,因为内存是malloc或者realloc出来的。还得有一个size,知道到底存了多少个数据,以及得有一个capacity,用来记录空间容量。

typedef int SLDataType;typedef struct SeqList
{assert(psl);SLDataType* arr; //指向动态开辟的数组int size;        //有效数据个数,看作下标时,它指向最后一个数据的下一个位置int capacity;    //空间容量
}SeqList;

2.顺序表初始化

因为形参是实参的一份临时拷贝,改变形参的值不会影响实参,所以传值的时候要传地址,形参用指针接收。

//顺序表初始化
void SeqListInit(SeqList* psl)
{assert(psl);psl->arr = NULL;psl->size = 0;psl->capacity = 0;
}

3.顺序表销毁

//顺序表销毁
void SeqListDestory(SeqList* psl)
{assert(psl);if (psl->arr != NULL){free(psl->arr);psl->arr = NULL;psl->size = 0;psl->capacity = 0;}
}

4.顺序表增容

即检查空间,如果满了,就进行增容。因为头插和尾插都需要增容,所以我们把它成一个公共的函数,方便管理。 关于动态内存开辟有不清楚的铁子们可以看这篇博客:动态内存管理详解

//增容
void SeqListCheckCapacity(SeqList* psl)
{assert(psl);if (psl->size == psl->capacity){int newCapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;//防止扩容失败将原来的空间给覆盖掉,所以用一个临时变量来接收SLDataType* tmp = (SLDataType*)realloc(psl->arr, sizeof(SLDataType) * newCapacity);if (tmp == NULL){perror("realloc");return;}psl->arr = tmp;psl->capacity = newCapacity;}
}

5.顺序表头插

要想在头部插入数据,必须将所有的数据先向后挪动一个位置,然后将要插入的数据放在第一个位置。我们可以先定义一个变量end,让它等于最后一个数据,然后利用while循环将所有的数据向后挪动一个位置,再将数据插入头部,然后让数据个数size+1。

//头插
void SeqListPushFront(SeqList* psl, SLDataType x)
{assert(psl);SeqListCheckCapacity(psl);//挪动数据int end = psl->size - 1;while (end >= 0){psl->arr[end + 1] = psl->arr[end];end--;}psl->arr[0] = x;psl->size++;
}

6.顺序表尾插

尾插相对来说比较简单,如果空间不够,增容之后直接将要插入的数据放在尾部即可,然后将数据个数size+1。

//尾插
void SeqListPushBack(SeqList* psl, SLDataType x)
{assert(psl);//增容SeqListCheckCapacity(psl);psl->arr[psl->size] = x;psl->size++;
}

7.顺序表头删

头删时我们采用的方法还是挪动数据,但是要从前面开始挪动,因为如果从后往前挪的话会将前面的数据给覆盖掉。先定义一个变量begin,让它等于1,然后利用while循环将所有的数据向前挪动一个位置(让后一个数据将前一个数据覆盖掉),直到begin小于size就跳出循环,然后让数据个数size-1。

//头删
void SeqListPopFront(SeqList* psl)
{assert(psl);//暴力检查assert(psl->size);int begin = 1;while (begin < psl->size){psl->arr[begin - 1] = psl->arr[begin];begin++;}psl->size--;
}

8.顺序表尾删

尾删时我们只需让有效数据 size-- 就行,但是必须进行检查看顺序表是否为空,因为如果为空,后面我们在头插时就会出现问题。

//尾删
void SeqListPopBack(SeqList* psl)
{assert(psl);//若顺序表为空,则进行检查//温柔的检查/*if (psl->size == 0){return;}*///暴力检查assert(psl->size > 0);psl->size--;
}

9.顺序表打印

//顺序表打印
void SeqListPrint(SeqList* psl)
{assert(psl);for (int i = 0; i < psl->size; i++){printf("%d ", psl->arr[i]);}printf("\n");
}

10.顺序表在任意下标位置插入数据

首先要保证指针不为空以及pos位置的合法性。然后定义变量end,让它指向最后一个数据的位置,通过while循环将 pos到end 位置的值向后挪动一个位置,将要插入的数据放入pos位置,再将size+1。

//顺序表在任意下标位置插入数据
void SeqListInsert(SeqList* psl, int pos, SLDataType x)
{assert(psl);assert(pos >= 0 && pos <= psl->size);int end = psl->size - 1;while (end >= pos){psl->arr[end + 1] = psl->arr[end];end--;}psl->arr[pos] = x;psl->size++;
}

11.顺序表删除任意下标位置的值

//顺序表删除任意下标位置的值
void SeqListErase(SeqList* psl, int pos)
{assert(psl);assert(pos >= 0 && pos < psl->size);//挪动数据int begin = pos + 1;while (begin < psl->size){psl->arr[begin - 1] = psl->arr[begin];begin++;}psl->size--;
}

12.顺序表查找

在顺序表中查找数据,如果找到了,就返回下标;如果没有找到,则返回-1。

//顺序表查找
int SeqListFind(SeqList* psl, SLDataType x)
{assert(psl);for (int i = 0; i < psl->size; i++){if (psl->arr[i] == x){return i;break;}}return -1;
}

2.3菜单

void menu()
{printf("*************************************\n");printf("***   1.头插数据    2.尾插数据    ***\n");printf("***   3.头删数据    4.尾删数据    ***\n");printf("***   5.查找数据    6.打印顺序表  ***\n");printf("***   7.在任意下标位置插入数据    ***\n");printf("***   8.删除任意下标位置的数据    ***\n");printf("***   0.退出系统                  ***\n");printf("*************************************\n");
}void Test()
{SeqList sl;SeqListInit(&sl);//初始化int x = 0, pos = 0;int input = 0;do{printf("欢迎来到顺序表系统!\n");menu();printf("请输入你的选择:>");scanf("%d", &input);switch (input){case 1:printf("请输入你要头插的数据:\n");scanf("%d", &x);SeqListPushFront(&sl, x);printf("头插成功!\n");break;case 2:printf("请输入你要尾插的数据:\n");scanf("%d", &x);SeqListPushBack(&sl, x);printf("尾插成功!\n");break;case 3:SeqListPopFront(&sl);printf("头删成功!\n");break;case 4:SeqListPopBack(&sl);printf("尾删成功!\n");break;case 5:printf("请输入你要查找的数据(查找成功则返回下标, 负责返回-1):\n");scanf("%d", &x);int pos = SeqListFind(&sl, x);printf("%d\n", pos);break;case 6:printf("顺序表目前的数据为:\n");SeqListPrint(&sl);break;case 7:printf("请输入你要插入的数据:");scanf("%d", &x);printf("请输入你要插入数据的下标(下标从0开始):");scanf("%d", &pos);SeqListInsert(&sl, pos, x);printf("插入数据成功!\n");break;case 8:printf("请输入你要删除数据的下标:");scanf("%d", &pos);SeqListErase(&sl, pos);printf("删除成功!\n");break;case 0:printf("退出系统!\n");break;default:printf("选择错误,请重新选择!\n");break;}} while (input);SeqListDestory(&sl);//销毁
}

3.源码

🌻test.c

#include "SeqList.h"void menu()
{printf("*************************************\n");printf("***   1.头插数据    2.尾插数据    ***\n");printf("***   3.头删数据    4.尾删数据    ***\n");printf("***   5.查找数据    6.打印顺序表  ***\n");printf("***   7.在任意下标位置插入数据    ***\n");printf("***   8.删除任意下标位置的数据    ***\n");printf("***   0.退出系统                  ***\n");printf("*************************************\n");
}void Test()
{SeqList sl;SeqListInit(&sl);int x = 0, pos = 0;int input = 0;do{printf("欢迎来到顺序表系统!\n");menu();printf("请输入你的选择:>");scanf("%d", &input);switch (input){case 1:printf("请输入你要头插的数据:\n");scanf("%d", &x);SeqListPushFront(&sl, x);printf("头插成功!\n");break;case 2:printf("请输入你要尾插的数据:\n");scanf("%d", &x);SeqListPushBack(&sl, x);printf("尾插成功!\n");break;case 3:SeqListPopFront(&sl);printf("头删成功!\n");break;case 4:SeqListPopBack(&sl);printf("尾删成功!\n");break;case 5:printf("请输入你要查找的数据(查找成功则返回下标, 负责返回-1):\n");scanf("%d", &x);int pos = SeqListFind(&sl, x);printf("%d\n", pos);break;case 6:printf("顺序表目前的数据为:\n");SeqListPrint(&sl);break;case 7:printf("请输入你要插入的数据:");scanf("%d", &x);printf("请输入你要插入数据的下标(下标从0开始):");scanf("%d", &pos);SeqListInsert(&sl, pos, x);printf("插入数据成功!\n");break;case 8:printf("请输入你要删除数据的下标:");scanf("%d", &pos);SeqListErase(&sl, pos);printf("删除成功!\n");break;case 0:printf("退出系统!\n");break;default:printf("选择错误,请重新选择!\n");break;}} while (input);SeqListDestory(&sl);
}int main()
{Test();return 0;
}

🌻SeqList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLDataType;typedef struct SeqList
{SLDataType* arr;//指向动态开辟的数组int size;     //有效数据int capacity; //空间容量
}SeqList;//顺序表初始化
void SeqListInit(SeqList* psl);
//顺序表销毁
void SeqListDestory(SeqList* psl);
//顺序表打印
void SeqListPrint(SeqList* psl);
//增容
void SeqListCheckCapacity(SeqList* psl);//头插
void SeqListPushFront(SeqList* psl, SLDataType x);
//尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
//头删
void SeqListPopFront(SeqList* psl);
//尾删
void SeqListPopBack(SeqList* psl);//顺序表在任意位置插入数据
void SeqListInsert(SeqList* psl, int pos, SLDataType x);
//顺序表删除任意位置的值
void SeqListErase(SeqList* psl, int pos);//顺序表查找
int SeqListFind(SeqList* psl, SLDataType x);

🌻SeqList.c

#include "SeqList.h"//顺序表初始化
void SeqListInit(SeqList* psl)
{assert(psl);psl->arr = NULL;psl->size = 0;psl->capacity = 0;
}//顺序表销毁
void SeqListDestory(SeqList* psl)
{assert(psl);if (psl->arr != NULL){free(psl->arr);psl->arr = NULL;psl->size = 0;psl->capacity = 0;}
}//顺序表打印
void SeqListPrint(SeqList* psl)
{assert(psl);for (int i = 0; i < psl->size; i++){printf("%d ", psl->arr[i]);}printf("\n");
}//增容
void SeqListCheckCapacity(SeqList* psl)
{assert(psl);if (psl->size == psl->capacity){int newCapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;//防止扩容失败将原来的空间给覆盖掉,所以用一个临时变量来接收SLDataType* tmp = (SLDataType*)realloc(psl->arr, sizeof(SLDataType) * newCapacity);if (tmp == NULL){perror("realloc");return;}psl->arr = tmp;psl->capacity = newCapacity;}
}//头插
void SeqListPushFront(SeqList* psl, SLDataType x)
{assert(psl);SeqListCheckCapacity(psl);//挪动数据int end = psl->size - 1;while (end >= 0){psl->arr[end + 1] = psl->arr[end];end--;}psl->arr[0] = x;psl->size++;
}//尾插
void SeqListPushBack(SeqList* psl, SLDataType x)
{assert(psl);//增容SeqListCheckCapacity(psl);psl->arr[psl->size] = x;psl->size++;
}
//头删
void SeqListPopFront(SeqList* psl)
{assert(psl);//暴力检查assert(psl->size);int begin = 1;while (begin < psl->size){psl->arr[begin - 1] = psl->arr[begin];begin++;}psl->size--;
}//尾删
void SeqListPopBack(SeqList* psl)
{assert(psl);//若顺序表为空,则进行检查//温柔的检查/*if (psl->size == 0){return;}*///暴力检查assert(psl->size);psl->size--;
}//顺序表在任意下标位置插入数据
void SeqListInsert(SeqList* psl, int pos, SLDataType x)
{assert(psl);assert(pos >= 0 && pos <= psl->size);int end = psl->size - 1;while (end >= pos){psl->arr[end + 1] = psl->arr[end];end--;}psl->arr[pos] = x;psl->size++;
}//顺序表删除任意下标位置的值
void SeqListErase(SeqList* psl, int pos)
{assert(psl);assert(pos >= 0 && pos < psl->size);int begin = pos + 1;while (begin < psl->size){psl->arr[begin - 1] = psl->arr[begin];begin++;}psl->size--;
}//顺序表查找
int SeqListFind(SeqList* psl, SLDataType x)
{assert(psl);for (int i = 0; i < psl->size; i++){if (psl->arr[i] == x){return i;break;}}return -1;
}

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

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

相关文章

C++11多线程: mutex(互斥元)

文章目录 mutex(互斥元)案例 1案例2 lock_guard()案例2的优化 由C标准提供的保护共享数据的最基本机制是&#xff1a;互斥元 (mutex 全称为: mutual exclusive&#xff09; 在访问共享数据前&#xff0c; 锁定&#xff08; lock&#xff09;与该数据相关的互斥元&#xff0c…

Aspose.Words For JAVA 动态制作多维度表格(涵2024最新无水印包)

全网最全Aspose.Words For JAVA 高级使用教程: CSDNhttps://blog.csdn.net/LiHaoHang6/article/details/133989664?spm1001.2014.3001.5501 运行截图&#xff1a; 所谓多维度表格通常包含多个维度, 每个维度都代表一种数据属性,多维度表格可以用于数据分析&#xff0c;通过不…

【洛谷 P8780】[蓝桥杯 2022 省 B] 刷题统计 题解(贪心算法+模拟+四则运算)

[蓝桥杯 2022 省 B] 刷题统计 题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a a a 道题目&#xff0c;周六和周日每天做 b b b 道题目。请你帮小明计算&#xff0c;按照计划他将在第几天实现做题数大于等于 n n n 题? 输入格式 输入一…

【AIGC】OpenAI推出王炸级模型sora,颠覆AI视频行业

文章目录 强烈推荐前言什么是OpenAI Sora&#xff1f;工作原理&#xff1a;算法原理&#xff1a;应用场景展望与其他视频生成模型相比有哪些优势和不足&#xff1f;优点缺点 总结强烈推荐专栏集锦写在最后 强烈推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易…

数据仓库概念梳理

数据仓库&#xff08;英语&#xff1a;Data Warehouse&#xff0c;简称数仓、DW&#xff09;,是一个用于存储、分析、报告的数据系统。数据仓库的目的是构建面向分析的集成化数据环境&#xff0c;为企业提供决策支持&#xff08;Decision Support&#xff09;。 数据仓库是分析…

初入职场的你,为何频繁跳槽?

大数据统计&#xff0c;初入职场的人跳槽频率相当高&#xff0c;而对于工作了2~3年的来说&#xff0c;跳槽频率也就没有那么频繁了&#xff0c;是什么原因导致了频繁跳槽&#xff1f;如何避免频繁跳槽呢&#xff1f; 是什么原因导致了跳槽&#xff1f; 不适应 从学校毕业&…

【算法与数据结构】200、695、LeetCode岛屿数量(深搜+广搜) 岛屿的最大面积

文章目录 一、200、岛屿数量1.1 深度优先搜索DFS1.2 广度优先搜索BFS 二、695、岛屿的最大面积2.1 深度优先搜索DFS2.2 广度优先搜索BFS 三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、200、岛屿数量 1.1 深度优先搜…

Redis篇----第十一篇

系列文章目录 文章目录 系列文章目录前言一、Redis 如何做内存优化?二、Redis 回收进程如何工作的?三、都有哪些办法可以降低 Redis 的内存使用情况呢?四、Redis 的内存用完了会发生什么?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下…

【前端素材】推荐优质后台管理系统Symox模板(适用电商,附带源码)

一、需求分析 后台管理系统是一种用于管理网站、应用程序或系统的工具&#xff0c;它通常作为一个独立的后台界面存在&#xff0c;供管理员或特定用户使用。下面详细分析后台管理系统的定义和功能&#xff1a; 1. 定义 后台管理系统是一个用于管理和控制网站、应用程序或系统…

【算法与数据结构】1020、LeetCode飞地的数量

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;   程序如下&#xff1a; 复杂度分析&#xff1a; 时间复杂度&#xff1a; O ( ) O() O()。空间复杂…

快速清理_卸载docker_找到不用的进程_centos磁盘爆满_清理磁盘---Linux工作笔记071

查看大文件,并且按照大小排名 cd / | du -h |sort -hr|head -30 可以看到根据不用的结果进行删除 可以看到在/data/dict目录很大,里面的都可以删除 然后再去卸载docker,要不然,没有磁盘是卸载不了的 systemctl stop docker systemctl stop docker.socket yum remove docker-…

【2024上半年数学建模推荐】2024年第九届数维杯大学生数学建模挑战赛报名通知

2024上半年数模人必打的数学建模竞赛&#xff1a;数维杯全国大学生数学建模挑战赛已经开始报名。 赛题难度&#xff1a;四颗星 含金量&#xff1a;国家级二类 参赛对象&#xff1a;在校专科、本科、研究生 推荐理由&#xff1a;获奖率高&#xff0c;赛题难度比国赛略微简单…

Qt _day1

1.思维导图 2.设计一个简单登录界面 #include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {this->setWindowTitle("原神启动"); // this->setStyleSheet("background-color:rgb(255,184,64)");this->setStyl…

XSS攻击原理与解决方法

参考&#xff1a; web安全之XSS攻击原理及防范_xss攻击原理与解决方法-CSDN博客 跨站脚本攻击&#xff08;XSS)分类介绍及解决办法_反射型跨站脚本解决方案-CSDN博客 一、概述 XSS攻击是Web攻击中最常见的攻击方法之一&#xff0c;它是通过对网页注入可执行代码且成功地被浏…

【竞技宝】DOTA2-喀山:莫言帕克毁天灭地 IG让一追二力克Neon

北京时间2024年2月21日,喀山未来运动会DOTA2项目在昨天迎来第二个比赛日。本日第二轮第二场比赛由IG对阵Neon。本场比赛两队在前两局各取一胜,决胜局IG的防守反击多次击溃Neon,最终IG让一追二击败Neon。以下是本场比赛的详细战报。 第一局: 首局比赛,IG在天辉方,Neon在夜魇方。…

算法项目(2)—— LSTM、RNN、GRU(SE注意力)、卡尔曼轨迹预测

本文包含什么? 项目运行的方式(包教会)项目代码LSTM、RNN、GRU(SE注意力)、卡尔曼四种算法进行轨迹预测.各种效果图运行有问题? csdn上后台随时售后.项目说明 本文实现了三种深度学习算法加传统算法卡尔曼滤波进行轨迹预测, 预测效果图 首先看下不同模型的指标: 模型RM…

unity学习(33)——角色选取界面(原版)

10ARPG网络游戏编程实践&#xff08;十&#xff09;&#xff1a;角色选择UI及创建面板制作&#xff08;一&#xff09;&#xff08;流畅&#xff09;_哔哩哔哩_bilibili 角色选择界面教程中是这样的&#xff01;&#xff08;这个美工肯定是不能拿出去卖的&#xff0c;但是是有…

IP协议及相关技术协议

一、IP基本认识 1. IP的作用 IP在TCP/IP模型中处于网络层&#xff0c;网络层的主要作用是实现主机与主机之间的通信&#xff0c;而IP的作用是在复杂的网络环境中将数据包发送给最终目的主机。 2. IP与MAC的关系 简单而言&#xff0c;MAC的作用是实现“直连”的两个设备之通信…

77、Spring、Spring Boot和Spring Cloud的关系

77、Spring、Spring Boot和Spring Cloud的关系 随着 Spring、Spring Boot 和 Spring Cloud 的不断发展&#xff0c;越来越多的开发者加入 Spring 的大军中。对于初学者而言&#xff0c;可能不太了解 Spring、Spring Boot 和 Spring Cloud 这些概念以及它们之间的关系&#xff…

10个行锁、死锁案例⭐️24张加锁分析图彻底搞懂Innodb行锁加锁规则!

10个行锁、死锁案例⭐️24张加锁分析图&#x1f680;彻底搞懂Innodb行锁加锁规则&#xff01; 上篇文章 我们描述原子性与隔离性的实现&#xff0c;其中描述读操作解决隔离性问题的方案时还遗留了一个问题&#xff1a;写操作是如何解决不同的隔离性问题&#xff1f; 本篇文章…