顺序表的增删查改

article/2025/8/22 5:20:46

数据结构

是数据存储的方式,对于不同的数据我们要采用不同的数据结构。就像交通运输,选用什么交通工具取决于你要运输的是人还是货物,以及它们的数量。

顺序存储结构

包括顺序表、链表、栈和队列等。

例如腾讯QQ中的好友列表,在之前添加好友信息后,好友信息这种类型会存储在内存中,当我们翻动好友列表时,会看到不同好友的ID,点开ID又会看到具体的信息,信息利用顺序表或链表进行存储,翻动的过程也就是遍历。

增加好友、删除好友、查找好友信息、更改好友信息等,对应着数据结构最主要的功能,增删查改

这些功能都是在腾讯的服务器上实现的。同时好友列表或群聊有上限,达到上限后可以增容,但增容往往需要充值会员。

静态顺序表

在创建顺序表时,就确定了要存储元素的个数为N,与静态通讯录相同,可能导致内存不够用,或是内存浪费,因此我们需要能够动态调整内存的能力。

动态顺序表 


//#定义的宏和常量  全大写typedef int SLDataType;
#define INITCAPACITY 5//假设初始容量为5typedef struct SeqList
{SLDataType* a;int sz;int capacity;
}SL;

 这里我们将数据类型暂时定为int类型,typedef为SLDataType,便于我们后续对顺序表数据类型的修改。定义属性表为SL*的指针a,数据个数sz,现有容量sz。

1、接口函数


//顺序表初始化
void SLInit(SL* ps);
//打印
void SLPrint(SL* ps);
//尾插
void SLPushBack(SL* ps, SLDataType x);
//尾删
void SLPopBack(SL* ps);
//头删
void SLPopFront(SL* ps);
//头插
void SLPushFront(SL* ps, SLDataType x);
//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);
//指定位置删除
void SLErase(SL* ps, int pos);

插入的过程都需要判断增容,可将其封装为增容函数,在头插、尾插中运用。

2、顺序表的初始化

SL a;Init_SeqList(&a);
//顺序表初始化
void Init_SeqList(SL* pa)
{pa->capacity = INITCAPACITY;pa->sz = 0;SLDataType* tmp = (SLDataType*)malloc((pa->capacity) * sizeof(SLDataType));if (NULL == tmp){perror("malloc fail");return;}pa->a = tmp;tmp = NULL;
}

这里必须使用传址调用,对sz和capacity初始化后,malloc 容量大小的空间给中间变量tmp,不为NULL后赋给a,这样a就指向了一块初始空间。

 3、顺序表的打印(int类型为例)

//打印
void SLPrint(SL* pa)
{//利用现有个数sz进行遍历打印for (int i = 0; i < pa->sz; i++){printf("%d ", pa->a[i]);}printf("\n");
}

4、增容函数

//判断是否需要增容,如需要,则增容
void SLCapacityAdd(SL* pa)
{if (pa->capacity == pa->sz){//增容倍数随意,一般来说2倍比较适合SLDataType* tmp = (SLDataType*)realloc(pa->a, 2 * (pa->capacity) * sizeof(SLDataType));if (NULL == tmp){perror("realloc fail");return;}pa->a = tmp;tmp = NULL;pa->capacity *= 2;}
}

增容后capacity的值变为2倍

5、尾插

//顺序表尾插
void SLPushBack(SL* pa, SLDataType x)
{SLCapacityAdd(pa);//尾插的过程,即在下标为size的位置插入pa->a[pa->sz++] = x;}

尾插前先调用SLCapacityAdd判断是否增容。

6、尾删

//顺序表尾删
void SLPopback(SL* pa)
{assert(pa->sz > 0);pa->sz--;
}

由于打印等显示过程中,我们用sz来遍历顺序表,因此在尾删时,仅需要将sz--,使遍历范围不包含最后一个元素,可以等效为将其删除。

在删除前可以利用assert进行断言,防止顺序表中没有数据,仍然进行删除操作。

换句话说,如果没有数据继续删除,sz会变成负数,当之后再添加元素时,sz为负数,遍历时会产生越界现象。

7、头删

//头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->sz > 0);//删除的过程int begin = 1;while (begin < ps->sz){ps->a[begin - 1] = ps->a[begin];begin++;}ps->sz--;
}

删除时同样判断sz是否大于0,删除过程为下标为1的元素起,依次向前覆盖,最后sz也要-1。

注意:覆盖的时候,从前面的元素覆盖,参考memmove和memcpy内存函数,对于重叠空间拷贝的不同。

8、头插


//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);CheckCapacity(ps);int end = ps->sz - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];end--;}ps->a[0] = x;ps->sz++;
}

先检查是否需要增容,然后从sz-1开始向右覆盖,最后在a[0]处添加x,然后sz++

 9、 指定位置插入

//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->sz);//锁定插入的范围为  0-szCheckCapacity(ps);int end = ps->sz - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->sz++;
}

先断言pos插入的位置正确,然后从sz-1开始向右覆盖,直到pos位置现有的元素也覆盖过去,然后将x插入到pos的位置上。

 10、指定位置删除

//指定位置删除
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->sz);//锁定插入的范围为  0-sz//assert(ps->sz > 0);  上面pos已经排除了sz<=0的可能,可以不用再写int begin = pos;while (begin < ps->sz - 1){ps->a[begin] = ps->a[begin + 1];begin++;}ps->sz--;}

判断pos范围的同时,确定了sz>0成立。从pos开始,到sz-2,从右向左覆盖,然后sz-1。

 11、升级头尾/插删

由于我们指定位置插入删除的功能已经实现,可以将头删、头插、尾插、尾删升级。

在头尾/插删的函数实现中调用Insert和Erase

注意:尾插位置是sz,尾删是sz-1

头插头删都是0 

 12、注意点

增加元素时先确保是否需要增容,删除时先确保是否还有元素,sz是否为0。

指定位置可以代替头尾插入删除,当然也可以写一些中间位置的。

同时还有查改功能

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;
}

查的过程遍历即可,根据SL数据类型直接判断是否相等,结构体等自定义类型也可以。

更改是先查找,根据查找内容返回的下标pos或i,就可以利用指针进行修改。


http://chatgpt.dhexx.cn/article/uNn6vD1K.shtml

相关文章

顺序表初始化

文章目录 1. 顺序表2. 顺序表的初始化 1. 顺序表 顺序表(顺序存储结构) 存储数据时&#xff0c;会提前申请一整块足够大小的物理空间&#xff0c;然后将数据依次存储到一整块连续的存储空间内&#xff0c;存储时做到数据元素之间不留一丝缝隙。 使用顺序表存储集合 {1,2,3,4,…

顺序表的创建

三个朋友今天全部上岸大厂&#xff0c;祝贺。&#xff08;太羡慕了&#xff09; 静态分配创建一个顺序表&#xff1b; 1.顺序表的定义&#xff1a; #define MaxSize 10 typedef struct {ElemType data[MaxSize];int length; }SqlList;这里我们用结构体的方式定义以一个顺序表…

顺序表的详解

线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串.... 即顺序表为线性表的一种&#xff0c; 顺序表是一种物理地址连续的存储单元依次存储数据元素的线性结构&#…

什么是顺序表

顺序表 在程序中&#xff0c;经常需要将一组&#xff08;通常是同为某个类型的&#xff09;数据元素作为整体管理和使用&#xff0c;需要创建这种元素组&#xff0c;用变量记录它们&#xff0c;传进传出函数等。一组数据中包含的元素个数可能发生变化&#xff08;可以增加或删…

数据结构——顺序表

目录 一. 什么是顺序表&#xff1f; 1&#xff0c;静态顺序表 2&#xff0c;动态顺序表 ①动态顺序表的实现及其初始化 ②空间的创建 ③顺序表的打印和销毁 ④顺序表的尾部插入和删除 ⑤顺序表的头部插入和删除 ⑥顺序表pos位置的插入和删除 ⑦顺序表指定元素的删除 二&am…

【数据结构】——顺序表介绍(独家介绍,小白必看!!)

重点和易错点都用彩笔标记出来了&#xff0c;放心食用&#xff01;&#xff01; 数据结构分为线性表和非线性表&#xff0c;今天我们要学习的顺序表就是线性表中的一个小类。那么&#xff0c;何为线性表&#xff0c;线性表是指n个具有相同性质的数据元素的有限序列&#xff0c…

顺序表详解

目录 一、线性表的概念 二、顺序表 1、顺序表的概念 1&#xff09;. 静态顺序表&#xff1a;使用定长数组存储元素。 2&#xff09;. 动态顺序表&#xff1a;使用动态开辟的数组存储。 三、接口实现 1、创建 2、初始化 3、扩容 4、尾插 5、打印 6、销毁 7、尾删 越界&…

php的strstr是什么意思,php strstr函数怎么用

strstr()函数是PHP中的一个内置函数&#xff0c;语法为strstr(string,search,before_search) &#xff0c;用于搜索字符串在另一字符串中是否存在&#xff0c;如果是&#xff0c;返回该字符串及剩余部分&#xff0c;否则返回 FALSE。此函数区分大小写。 php strstr()函数怎么用…

【数据结构】--- kmp算法和strstr函数

kmp算法和strstr函数 引言一、概念分析分析原理分析 KMP算法原理基本操作图解KMP原理 三、复杂度分析四、KMP算法代码 引言 现实生活中&#xff0c;字符串匹配在很多的应用场景里都有着极其重要的作用&#xff0c;包括生物信息学、信息检索、拼写检查、语言翻译、数据压缩、网…

实现strstr函数

strstr函数的作用是寻找子字符串在目标字符串中第一次出现的位置。 #include <stdio.h> #include<stdlib.h> #include<assert.h> const char * Strstr(const char * str1, const char * str2) {assert(str1 ! NULL);assert(str2 ! NULL);char* cur str1;ch…

字符串函数剖析(3)---strstr函数

1.strstr函数的巧妙 – 查找子字符串 1.1模拟实现strstr函数 strstr函数&#xff1a;在一个字符串中查找子串 学习新函数时&#xff0c;先去c库查找该函数的相关资料&#xff0c;更加助于你的学习 const char * strstr ( const char * str1, const char * str2 );先看函数…

C语言strstr()函数用法-字符串查找

1.函数定义 strstr()函数是一个参数为两个字符指针类型&#xff0c;返回值是char*类型的函数。 用于找到子串&#xff08;str2&#xff09;在一个字符串&#xff08;str1&#xff09;中第一次出现的位置&#xff08;不包括str2的串结束符&#xff09;&#xff0c;并返回该位置…

ConcurrentHashMap 实现原理

一. ConcurrentHashMap 是什么 在并发编程中&#xff0c;ConcurrentHashMap 是一个经常被使用的数据结构&#xff0c;相比于 Hashtable 以及Collections.synchronizedMap() 来说&#xff0c;ConcurrentHashMap 在线程安全的基础上提供了更好的写并发能力&#xff0c;同时还降低…

ConcurrentHashMap 详解

前言 ConcurrentHashMap。 以下的技术点都基于JDK1.8~ 基础回顾 我们都知道&#xff0c;从JDK1.8起&#xff0c;ConcurrentHashMap底层的数据结构就已经从原来的Segment分段锁变为了数组 链表 红黑树的形态。 它是一款并发容器&#xff0c;一款装数据的容器在并发环境下铁…

ConcurrentHashMap介绍

引言 学习ConcurrentHashMap&#xff0c;合理的问题顺序应该如下&#xff1a; ConcurrentHashMap是什么&#xff08;WHAT&#xff09;为什么要有ConcurrentHashMap&#xff08;WHY&#xff09;ConcurrentHashMap的实现原理&#xff08;HOW&#xff09;ConcurrentHashMap如何使…

一文彻底弄懂ConcurrentHashMap

一文彻底弄懂ConcurrentHashMap 导读前言锁synchronizedvolatile&#xff08;非锁&#xff09;自旋锁分段锁ReentrantLockCAS ConcurrentHashMap 实现原理JDK1.7 中的 ConcurrentHashMapSegmentConcurrentHashMap 并发读写的几种情况get 方法put 方法 JDK1.8 中的 ConcurrentHa…

ConcurrentHashMap杂谈

为什么使用ConcurrentHashMap 在并发编程中使用HashMap可能导致程序死循环&#xff0c;而使用线程安全的HashTable效率又非常低下 线程不安全的HashMap 在多线程环境下&#xff0c;使用HashMap进行put操作会引起死循环&#xff0c;导致CPU利用率接近100% 死循环案例&#xf…

图解ConcurrentHashMap

曾经研究过jkd1.5新特性&#xff0c;其中ConcurrentHashMap就是其中之一&#xff0c;其特点&#xff1a;效率比Hashtable高&#xff0c;并发性比hashmap好。结合了两者的特点。 集合是编程中最常用的数据结构。而谈到并发&#xff0c;几乎总是离不开集合这类高级数据结构的支…

Java集合:ConcurrentHashMap

本篇内容包括&#xff1a;ConcurrentHashMap 概述、ConcurrentHashMap 底层数据结构、ConcurrentHashMap 的使用以及相关知识点。 一、ConcurrentHashMap 概述 ConcurrentHashMap 是 HashMap 的线程安全版本&#xff0c;其内部和 HashMap 一样&#xff0c;也是采用了数组 链表…

Hashtable与ConcurrentHashMap区别

ConcurrentHashMap融合了hashtable和hashmap二者的优势。 hashtable是做了同步的&#xff0c;hashmap未考虑同步。所以hashmap在单线程情况下效率较高。hashtable在的多线程情况下&#xff0c;同步操作能保证程序执行的正确性。 但是hashtable每次同步执行的时候都要锁住整个结…