当前位置: 首页 > news >正文

[数据结构总结篇]--线性表

函数返回类型return 语句的规则示例
int必须写 return,且后面必须跟一个 int 类型的值return i;return 0;
void可以不写 return;若写 return,后面不能跟值return;(正确)、return 1;(错误)

存储结构一:顺序存储---顺序表

一.插入

1.1尾插  O(1)--一个元素动

n为元素个数  ++n就是最后一个元素了 让最后一个元素变成x

实现:

void push_back(int x){a[++n]=x;}

测试:

int main( ){push_back(2);print();push_back(5);print();return 0;}

1.2头插 O(n)--从后往前右移  

[1,n]后移一位--第一个元素是x---元素个数++  

实现:

void push_front(int x){for(int i=n;i>=1;i--){a[i+1]=a[i];}a[1]=x;n++;}

测试:

int main( ){push_front(2);print();push_front(5);print();return 0;}


for(int i=1;i<=n;i++){  // 错误!会导致元素覆盖,数据丢失
a[i+1]=a[i];
}
错误原因:从 i=1 开始后移,会先把 a[2] 覆盖成 a[1],再把 a[3] 覆盖成 a[2](也就是原来的 a[1]),最终所有元素都会变成初始 a[1] 的值(比如原数组 [ ,10,20],循环后会变成 [ ,10,10])。
正确循环:必须从 最后一个元素 开始往后移,避免覆盖,循环条件应为 i从n开始,到1结束:


1.3p位置插入  O(n)--[p,n]元素从后往前右移

!!!传入位置p啊啊啊

void insert(int p,int x){for(int i=n;i>=p;i--){a[i+1]=a[i];}a[p]=x;n++;}

二.删除

2.1尾删  O(1)

把n从4变成3


void pop_back(){if(n == 0) return;  // 空表不操作n--;
}或
void pop_back(){n--;
}

2.2头删   O(n)  从前往后左移

从[2,n]数据全部后移  ---元素个数-1---后一个=前一个值

void pop_front(){   //不用传参了for(int i=2;i<=n;i++){   //写错过a[i-1]=a[i];}n--;}

正确的 "删除首元素" 逻辑应该是:  

从前往后统一向左移动  所以从i=2

删除首元素(a[1])后,需要把后面的元素依次向前移动(覆盖前面的位置),最终元素个数减 1。
例如,原数组是 [ ,10,20,30,40]n=4),删除首元素后应该变成 [ ,20,30,40, ]n=3)。

移动过程是:
a[1] = a[2](用 20 覆盖 10)
a[2] = a[3](用 30 覆盖 20)
a[3] = a[4](用 40 覆盖 30)

删除首元素需要 "后面的元素往前补",所以是 a[i-1] = a[i];如果是插入首元素(push_front),才需要 "前面的元素往后移",用 a[i+1] = a[i]

2.3p位置删除   O(n)  [p+1,n]从前往后左移 

void erase(int p){//i从[p+1,n]统一左移一位 for(int i=p+1;i<=n;i++){a[i-1]=a[i];}n--;
}

一、先明确 “正确的任意位置删除逻辑”

假设数组是 [ ,10,20,30,40]n=4),要删除第 p=2 个元素(值为 20),最终结果应该是 [ ,10,30,40, ]n=3)。

关键步骤是:只需要移动 p 后面的元素(即从 p+1 到 n 的元素),让它们向左 “补位”:

  • a[2] = a[3](用 30 覆盖被删除的 20)
  • a[3] = a[4](用 40 覆盖原来的 30)
    这里的移动范围是 i从p+1开始,到n结束,赋值逻辑是 a[i-1] = a[i](左移 1 位)。

二、为什么第一个 erase(int p) 是对的?

第一个函数的循环是:

for(int i = p+1; i <= n; i++){  // 循环范围:p+1 到 na[i-1] = a[i];              // 左移:i-1(前一个位置) = i(当前位置)
}
  • 循环只处理 p 后面的元素(p+1 到 n),不碰 p 前面的元素(避免无效操作);
  • 赋值 a[i-1] = a[i] 正好让每个元素向左移 1 位,完美覆盖被删除的 p 位置。

用上面的例子(删 p=2)验证:

  • i 从 3p+1=2+1)开始,到 4n=4)结束:
    • i=3a[2] = a[3] → 20 变成 30;
    • i=4a[3] = a[4] → 30 变成 40;
  • 最终数组正确,n-- 后元素个数从 4 变 3,完全正确。

三、为什么第二个 erase(int p,int x) 是错的?

这个函数有 两个致命问题,直接破坏了删除逻辑:

问题 1:多传了无用参数 int x

“任意位置删除” 只需要知道 要删除的位置 p 即可(比如删第 2 个、第 3 个),根本不需要传入 xx 在这里没有任何用途,反而会导致调用时必须多传一个无关的值,比如 erase(2, 0),完全多余且不规范)。

问题 2:循环范围错误,导致删除位置偏移

第二个函数的循环是:

for(int i = p; i <= n; i++){  // 循环范围:p 到 n(错误!)a[i-1] = a[i];
}

循环从 p 开始,而不是 p+1,会导致 把 p 位置本身也卷进移动,最终删除的是 p-1 位置的元素,而非目标 p 位置。

还是用 “删 p=2(20)” 的例子验证:

  • i 从 2p=2)开始,到 4n=4)结束:
    • i=2a[1] = a[2] → 10 变成 20(原本要保留的 10 被覆盖了!);
    • i=3a[2] = a[3] → 20 变成 30;
    • i=4a[3] = a[4] → 30 变成 40;
  • 最终数组变成 [ ,20,30,40, ]n=3),相当于删除了 p=1 位置的 10,而不是目标 p=2 位置的 20,完全不符合预期!

四、总结:两个 erase 的核心区别

函数循环范围是否多传参数最终效果
erase(int p)p+1 ~ n正确删除第 p 个元素
erase(int p,int x)p ~ n是(多传 x)错误删除第 p-1 个元素

简单记:删除第 p 个元素,只需要移动 p 后面的元素(p+1 到 n,第一个函数做到了,第二个函数因为循环范围错了(从 p 开始),所以删错了位置,再加上多余的 x 参数,自然就是错的~

三.查找

3.1按值查找 O(n)

int find(int x){for(int i=1;i<=n;i++){if(a[i]==x) return i;}     //==  i返回下标return 0;}

3.2按位查找  O(1)

int at(int p){return a[p];}

int at(int p) {if (p < 1 || p > n) {  // 检查p是否在有效范围内return -1;  // 或其他错误标识(根据你的需求定义)}return a[p];
}

四.修改  O(1)

void change(int p,int x){a[p]=x;}

五.清空

void clear(){n=0;}
要注意,我们⾃⼰实现的简单形式是 O(1)
但是,严谨的⽅式应该是 O(N)

文章转载自:

http://dhLixS8Z.wftrs.cn
http://o6zPzBNH.wftrs.cn
http://GbBjTCAK.wftrs.cn
http://ofWIN0Tb.wftrs.cn
http://mx7K80zl.wftrs.cn
http://TnsWBuPQ.wftrs.cn
http://PuEPfQpx.wftrs.cn
http://9euW3LP1.wftrs.cn
http://fixPazSC.wftrs.cn
http://GZPPNxnD.wftrs.cn
http://2ODLdMYK.wftrs.cn
http://KMSMUmur.wftrs.cn
http://slYTnVX3.wftrs.cn
http://30oA89uQ.wftrs.cn
http://1qQ3kAOy.wftrs.cn
http://MOTRzytt.wftrs.cn
http://CTotWo53.wftrs.cn
http://E7gN2v3D.wftrs.cn
http://6XNPki4i.wftrs.cn
http://bkMIIO6Q.wftrs.cn
http://G9nZRaog.wftrs.cn
http://kqBkukDs.wftrs.cn
http://r92nfhEA.wftrs.cn
http://L7P5aH4g.wftrs.cn
http://ABuGCvSD.wftrs.cn
http://wUxz0Cbk.wftrs.cn
http://5HKTuDdZ.wftrs.cn
http://iCjQ14H8.wftrs.cn
http://kaJXsDLt.wftrs.cn
http://VnCgJJXA.wftrs.cn
http://www.dtcms.com/a/383354.html

相关文章:

  • 【Javaweb学习|实训总结|Week2】个人疑问记录、大模型API接入
  • srm招标采购询价供应商管理系统源码(java源码➕vue前端➕数据库操作文档➕软件文档)
  • 蚂蚁S19 Pro Hyd 184T矿机参数分析及其特点
  • Coze源码分析-资源库-创建知识库-基础设施/存储/安全
  • 国家标准项目管理专业人员五级划分解析
  • c++---map和set
  • Python可微分编程革命:JAX与PyTorch2.0的梯度计算架构剖析
  • 【Linux】人事档案——用户及组管理
  • JavaScript对象创建方式完全指南:从原始到现代的演进之路
  • 深入探讨 HarmonyOS 新一代声明式 UI:从 ArkTS 与 ArkUI 到高级应用实践
  • React组件通信的6种艺术:从单向传值到全局共享
  • Go 消息队列学习指南
  • 导购类电商平台的服务容错机制:Sentinel在微服务稳定性保障中的应用
  • 基于HTML2WEB和DEEPSEEK实现web设计
  • 网络系统设计方案: eNSP、华为、网络架构设计、小型局域网、DHCP\MSTP\VRRP\VLAN\RIP
  • 视觉 AI 如何优化产品图片分类?
  • Linux《线程(上)》
  • LeetCode 2565.最少得分子序列
  • Petalinux相关配置——ZYNQ通过eMMC启动
  • 2024版 IDEA 用 Maven 创建 java 项目(+Maven 安装和配置)
  • Qt程序单独运行报错问题
  • Qt读写ini文件的方式对比和Demo示例
  • xtuoj 连分式
  • 使用B210在Linux下实时处理ETC专用短程通信数据(5)-业余软件无线电户外经验
  • 机器人逆运动学进阶:李代数、矩阵指数与旋转流形计算
  • XLua教程之C#调用Lua
  • IDEA版本控制管理之使用Gitee
  • 贪心算法应用:航班起降问题详解
  • 【Linux】CentOS7安装教程
  • Java面试问题记录(四)