理解数据结构中的线性表:从抽象数据结构到具体实现
引言
在计算机科学中,线性数据结构是最基础且广泛使用的数据结构之一。在这篇博客中,我们将重点探讨两种基于数组实现的线性数据结构。通过定义、特性以及实际代码示例,阐述它们之间的关系和各自的优势。
注意⚠️:
运行环境:“intelliSenseMode”: “macos-clang-x64”
C++ 版本: “cppStandard”: “c++17”
编译器:clang-x64
1. 线性表
LinearList(线性表) 是一种基本的数据结构,它是由若干个相同类型元素构成的有限序列,其中的元素按照一定的顺序依次排列。在抽象层面,线性表提供了如插入、删除、查找等基本操作接口,但不具体指定实现方式,它可以是基于链表或数组实现的。
需要的头文件如下所示
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
为了体现数据结构的核心思想,即抽象数据类型(ADT)的设计理念,我们应该首先关注于描述线性表这一数据结构的行为和特性,而不是具体的实现细节。通过 ADT,我们可以跨越特定编程语言的限制,以一种通用的方式来定义线性表应当提供的接口和功能。
抽象数据类型 LinearList
{
实例
有限个元素的有序集合
操作
empty():若表空,则返回true,否则返回false
size():返回线性表的大小(表的元素个数)
get(index):返回线性表中索引为 index 的元素
indexOf(x):返回线性表中第一次出现的 x 的索引。若 x 不存在,则返回 -1
erase(index):删除索引为 index 的元素,索引大于 index 的元素其索引减 1
insert(index,x):把 x 插入线性表中索引为 index 的位置上,索引大于等于 index 的元素其索引加 1
clear(): 清空列表
print():从左到右输出表元素
}
在遵循抽象数据类型(ADT)的设计原则下,使用 C++ 纯虚类来实现线性表。如下所示的代码片段展示了如何定义一个基类LinearList,并提供了一个clear 方法的实现。⚠️ 这里的 clear 方法仅负责将所有元素设置为初始状态或删除其内容,但并不释放底层存储元素的内存空间。
template <class T>
class LinearList
{
public:
// 析构函数
virtual ~LinearList() = default;
// 返回 true,表示列表为空
virtual bool empty() const = 0;
// 返回列表中元素的个数
virtual int size() const = 0;
// 返回第 index 个元素
virtual T &get(int index) = 0;
// 返回元素 elem 列表中第一次出现的下标
virtual int indexOf(T const &elem) = 0;
// 在列表中插入元素 elem
virtual void insert(int index, T const &elem) = 0;
// 在列表中删除第 index 个元素
virtual void erase(int index) = 0;
// 清空列表
virtual void clear() = 0;
// 打印列表
virtual void print() = 0;
};
2. ArrayList:基于数组的 LinearList 实现
ArrayList(动态数组) 是线性表的一种高效实现方式,它使用连续的内存空间存储元素,并能根据需要动态调整容量。ArrayList 继承自 LinearList,并实现了其所有抽象方法:
template <