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

数据结构——线性表(核心操作,附代码)

文章目录

  • 一、顺序表的核心操作
    • 1.1定义及初始化
    • 1.2遍历
    • 1.3查(按值&按索引)
    • 1.4增(指定索引)
    • 1.5删(指定索引)
    • 1.6改(指定索引)
  • 二、链表的核心操作
    • 2.1定义及初始化
    • 2.2遍历
    • 2.3查(按索引&按值)
    • 2.4增
    • 2.5删(按索引)
    • 2.6改

一、顺序表的核心操作

顺序表是用一段地址连续的存储单元依次存储线性表中的元素,元素的逻辑顺序与物理存储顺序完全一致。
底层依赖数组实现。特点是能通过数组下标直接访问元素。

1.1定义及初始化

  • max_size表示顺序表的最大容量,即有有多少个元素。
  • length表示当前元素的个数,其范围为【0,max_size】
  • index表示数组的有效索引,其范围为【0,length-1】
#define MAX_SIZE 100 struct SeqList {int data [MAX_SIZE]; int length; 
};

简单操作包括:初始化链表,判空,判满,获取长度。

// 初始化顺序表
void initList (SeqList& list) {list.length = 0; // 初始为空表
}
// 判断顺序表是否为空
bool isEmpty (const SeqList& list) {return list.length == 0;
}
// 判断顺序表是否已满
bool isFull (const SeqList& list) {return list.length == MAX_SIZE;
}
// 获取顺序表长度
int getLength (const SeqList& list) {return list.length;
}

1.2遍历

遍历即通过数组下标从 0 到 length-1 依次访问元素。

// 打印顺序表元素
void printList (const SeqList& list) {if (isEmpty (list)) return ;for (int i = 0; i <= list.length-1; ++i) {cout << list.data [i] << " ";}
}

1.3查(按值&按索引)

按索引查找非常快,无需遍历,直接通过数组下标(索引)进行访问。注意索引范围。时间复杂度O(1)。

  • length的范围为【0,max_size】
  • 数组的有效索引的范围为【0,length-1】

按值查找需要遍历整个顺序表,逐个比较当前元素值与目标值,找到匹配项后,返回数组下标。时间复杂度O(n)。

// 按索引查找元素
int getElement(const SeqList& list, int index) {if (index < 0 || index >= list.length)   throw out_of_range("索引越界");return list.data[index];  // 直接访问数组对应下标
}
// 按值查找元素,返回第一个匹配元素的索引,未找到返回 - 1
int findElement(const SeqList& list, int value) {for (int i = 0; i < list.length; ++i) {  // 遍历所有元素if (list.data[i] == value) {return i;  // 找到后返回索引}}return -1;  // 遍历结束未找到
}

1.4增(指定索引)

在指定索引 index 处插入一个新元素,后续元素依次后移。在这里插入图片描述

void insertElement(SeqList& list, int index, int value) {if (isFull(list)) throw runtime_error("表满");  // 检查容量if (index < 0 || index > list.length) throw out_of_range("位置无效");// 从最后一个元素开始,依次后移一位(避免覆盖)for (int i = list.length-1; i >= index; --i) {list.data[i+1] = list.data[i];}list.data[index] = value;  // 插入新元素list.length++;  // 长度+1
}

1.5删(指定索引)

删除指定索引 index 处的元素,后续元素依次前移。
在这里插入图片描述

void deleteElement(SeqList& list, int index) {if (isEmpty(list)) throw runtime_error("表空");  // 检查空表if (index < 0 || index >= list.length) throw out_of_range("位置无效");// 从删除位置的下一个元素开始,依次前移一位(覆盖被删除元素)for (int i = index+1; i <= list.length-1; ++i) {list.data[i-1] = list.data[i];}list.length--;  // 长度-1
}

1.6改(指定索引)

将指定索引 index 处的元素值修改为 newValue。【直接覆盖】

void updateElement(SeqList& list, int index, int newValue) {if (index < 0 || index >= list.length)  throw out_of_range("修改位置无效");list.data[index] = newValue;  // 直接覆盖旧值
}

二、链表的核心操作

2.1定义及初始化

  • ListNode结构体定义:值val和指向下一个节点的指针next
  • dummy:虚拟头结点,指向开始节点简化边界情况
  • dummy->next:开始节点,第一个存储有效数据的节点
  • length:记录链表长度
// 链表节点结构体
struct ListNode {int val;ListNode* next;// 构造函数ListNode() : val(0), next(nullptr) {}ListNode(int x) : val(x), next(nullptr) {}ListNode(int x, ListNode* n) : val(x), next(n) {}
};
ListNode* dummy;  // 虚拟头节点(所有操作的统一起点)
int length;       // 链表长度
// 初始化链表
LinkedList() {dummy = new ListNode(0);  // 虚拟头节点,值无实际意义length = 0;
}

2.2遍历

void printList() {ListNode* h = dummy->next;//h指向开始节点if (h == nullptr) return ;while (h != nullptr) {cout << h->val << " -> ";h = h->next;}
}

2.3查(按索引&按值)

// 按索引获取元素
int get(int index) {// 索引无效检查if (index < 0 || index >= length)  throw out_of_range("索引越界:无效的查询索引");ListNode* cur = dummy;//h指向头结点// 从头结点出发,移动index+1次到达目标节点for (int i = 0; i <= index; ++i) {cur = cur->next;}//执行完后,cur 指向的是 index 对应的节点return cur->val;
}
// 按值查找,返回第一个匹配元素的索引,未找到返回-1
int find(int value) {ListNode* cur = dummy->next;  // 从真实头节点开始遍历for (int i = 0; i < length; ++i) {if (cur->val == value)  return i; cur = cur->next;}return -1; 
}

2.4增

插入的核心操作:
在这里插入图片描述

// 在指定索引处插入元素
void addAtIndex(int index, int val) {// 索引无效检查(允许index=length,即尾部插入)if (index < 0 || index > length) throw out_of_range("插入位置无效");ListNode* cur = dummy;// 从dummy出发,移动到达插入位置的前一个节点index-1for (int i = 0; i <= index-1; ++i) {cur = cur->next;}// 创建新节点并插入ListNode* newNode = new ListNode(val);newNode->next = cur->next;  cur->next = newNode;        length++;
}
  • 头部插入等价于在索引 0 处插入
  • 尾部插入等价于在索引 length 处插入

2.5删(按索引)

删除的核心操作
在这里插入图片描述

// 删除指定索引处的元素
void deleteAtIndex(int index) {if (index < 0 || index >= length)  throw out_of_range("删除位置无效");ListNode* cur = dummy;// 从dummy出发,移动到达删除位置的前一个节点for (int i = 0; i <= index-1; ++i) {cur = cur->next;}// 保存待删除节点,修改指针,释放内存ListNode* temp = cur->next;cur->next = cur->next->next;  // 跳过待删除节点delete temp;                  // 释放内存,避免泄漏length--;
}

2.6改

// 修改指定索引处的元素值
void updateAtIndex(int index, int newValue) {if (index < 0 || index >= length)  throw out_of_range("修改位置无效");ListNode* cur = dummy;// 从dummy出发,移动到达目标节点index处for (int i = 0; i <= index; ++i) {cur = cur->next;}cur->val = newValue;  // 修改值
}

设计链表
https://leetcode.cn/problems/design-linked-list/?envType=problem-list-v2&envId=linked-list

http://www.dtcms.com/a/327387.html

相关文章:

  • vue项目封装axios请求,支持判断当前环境及判断token是否过期等等(详细教程,可复制粘贴代码)
  • cuda排序算法--双调排序(Bitonic_Sort)
  • 【数据库】 MySQL 表的操作详解
  • 蓝桥杯手算题和杂题简易做法
  • 《Auracast广播音频技术解析及未来路线图》 —蓝牙技术联盟 市场拓展经理 吴志豪 技术与市场经理 鲁公羽
  • 基于 DiT 大模型与字体级分割的视频字幕无痕擦除方案,助力短剧出海
  • 深度学习与遥感入门(六)|轻量化 MobileNetV2 高光谱分类
  • 4.7 GB 视频导致浏览器内存溢出(OOM)的解决方案
  • 从零部署Nacos:替代Eureka的服务注册与服务发现基础教程
  • 视频输入输出模块介绍和示例
  • Dubbo 3.x源码(33)—Dubbo Consumer接收服务调用响应
  • Python day42
  • tensorrt-llm0.20.0离线部署DeepSeek-R1-Distill-Qwen-32B
  • 第六十三章:AI模型的“跨界之旅”:不同硬件架构下的兼容性方案
  • Linux NAPI 实现机制深度解析
  • 【CDA 新一级】学习笔记第1篇:数据分析的时代背景
  • 【前端八股文面试题】【JavaScript篇7】什么是JavaScript的原型、原型链? 有什么特点
  • 【设计模式精解】Java实现责任链模式(职责链模式)优雅处理多级请求(概述,使用场景,优缺点,代码示例)
  • Rust:构造函数 new() 如何进行错误处理?
  • 信号(Signal)** 是一种进程间异步通信机制,用于通知进程发生发生了某种事件(如错误、用户中断等)
  • 疯狂星期四文案网第37天运营日记
  • Apache POI中通过WorkBook写入图片后出现导出PDF文件时在不同页重复写入该图片问题,如何在通过sheet获取绘图对象清除该图片
  • 通过限制对象的内存分配位置来实现特定的设计目标
  • 【数据结构入门】堆
  • powerbi本地报表发布到web,以得到分享链接
  • C99中的变长数组(VLA)
  • 什么是 Spring MVC?
  • 中扬立库与西门子深化技术协同 共绘智能仓储创新蓝图
  • clean install 和 clean package 的区别
  • JVM学习笔记-----图解方法执行流程