- 基本概念
线性表是 0 个或者多个数据元素的有序序列。
-
特性:
- 数据元素之间是有序的
- 数据元素个数是有限的
- 数据元素类型是相同的
- 性质
为线性表的第一个元素,只有一个后继。
为线性表的最后一个元素,只有一个前驱。
- 除
和
外的其他元素
,既有前驱,又有后继。
- 线性表能够逐项访问和顺序存放。
- 线性表存储的方式
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储数据元素
C 语 言 实 现 单 链 表
- 结构体框架
typedef struct {
int* pArr; // 存放数据地址
int size; // 长度,当前元素个数
int capacity; // 容量,当前最大能容纳元素
}Dynamic_Array;
- 操作函数声明
// 初始化
Dynamic_Array* Init_Array();
// 插入
void Push_back_Array(Dynamic_Array* arr,int val);
// 根据 位置 删除
void RemoveByPos_Array(Dynamic_Array* arr, int pos);
// 根据 数据 删除
void RemoveByValue_Array(Dynamic_Array* arr, int val);
// 查找
int Find_Array(Dynamic_Array* arr, int val);
// 打印
void Print_Array(Dynamic_Array* arr);
// 释放动态数组内存
void FreeSpace_Array(Dynamic_Array* arr, int pos);
// 清空数组
void Clear_Array(Dynamic_Array* arr);
// 获取容量
int Capactiy_Array(Dynamic_Array* arr);
// 获取长度
int Size_Array(Dynamic_Array* arr);
// 根据 位置 获取元素
int At_Array(Dynamic_Array* arr, int pos);
- 操作函数实现
// 初始化
Dynamic_Array* Init_Array() {
// 申请空间
Dynamic_Array* myArray = (Dynamic_Array*)malloc(sizeof(Dynamic_Array));
// 初始化
myArray->size = 0;
myArray->capacity = 20;
myArray->pArr = (int*)malloc(sizeof(int) * myArray->capacity);
return myArray;
}
// 插入
void Push_back_Array(Dynamic_Array* arr, int val) {
if (arr == NULL) return;
// 判断容量是否足够
if (arr->size >= arr->capacity) {
// 申请更大空间 默认两倍
int* NewSpace = (int*)malloc(sizeof(int) * arr->capacity * 2);
// 拷贝数据到新空间
if (NewSpace != NULL) {
memcpy(NewSpace, arr->pArr, arr->capacity * sizeof(int));
}
// 释放旧空间内存
free(arr->pArr);
// 更新容量
arr->capacity = arr->capacity * 2;
// 更新指针指向
arr->pArr = NewSpace;
}
// 尾插 插入 新元素
arr->pArr[arr->size] = val;
// 更新长度
arr->size++;
}
// 根据位置删除
void RemoveByPos_Array(Dynamic_Array* arr, int pos) {
if (arr == NULL) return;
// 判断 位置 是否有效
if (pos < 0 || pos >= (arr->size)) return;
// 删除
for (int i = pos; i < arr->size - 1; i++) {
arr->pArr[i] = arr->pArr[i + 1];
}
// 更新长度
arr->size--;
}
// 根据值删除
void RemoveByValue_Array(Dynamic_Array* arr, int val) {
if (arr == NULL) return;
int pos = Find_Array(arr, val);
// 调用 按位置 删除
RemoveByPos_Array(arr, pos);
}
// 查找
int Find_Array(Dynamic_Array* arr, int val) {
int pos = -1;
if (arr == NULL) return pos;
for (int i = 0; i < arr->size; i++) {
if (arr->pArr[i] == val) {
pos = i;
break;
}
}
return pos;
}
// 打印
void Print_Array(Dynamic_Array* arr) {
if (arr == NULL) return;
for (int i = 0; i < arr->size; i++)
printf("%d ", arr->pArr[i]);
printf("\n");
}
// 释放动态数组内存
void FreeSpace_Array(Dynamic_Array* arr) {
if (arr == NULL) return;
if (arr->pArr != NULL) free(arr->pArr);
free(arr);
}
// 清空数组
void Clear_Array(Dynamic_Array* arr) {
if (arr == NULL) return;
arr->size = 0;
}
// 获取容量
int Capactiy_Array(Dynamic_Array* arr) {
if (arr == NULL) return 0;
return arr->capacity;
}
// 获取长度
int Size_Array(Dynamic_Array* arr) {
if (arr == NULL) return 0;
return arr->size;
}
// 根据位置获取元素
int At_Array(Dynamic_Array* arr, int pos) {
if (arr == NULL) return -1;
return arr->pArr[pos];
}
CPP 实 现 单 链 表
- DynamicArray类声明
class DynamicArray {
public:
// 构造
DynamicArray();
// 插入
void Pushback_Array(const Person& p);
// 根据 下标 删除
void RemoveByPos_Array(const int& pos);
// 根据 数据 删除
void RemoveByVal_Array(const Person& p);
// 根据 下标 修改
void ModifyByPos_Array(const int& pos);
// 根据 数据 修改
void ModifyByVal_Array(const Person& p);
// 根据 下标 查找
Person& FindByPos_Array(const int& pos);
// 根据 数据 查找
int FindByVal_Array(const Person& p);
// 打印
void Print_Array();
// 清空
void Clear_Array();
// 获取长度
int Get_Size_Array();
// 获取容量
int Get_Capactiy_Array();
// 析构
~DynamicArray();
DynamicArray& operator=(const DynamicArray& da);
public:
Person* m_Parr;
int m_Size;
int m_Capactiy;
};
- Person类声明
class Person {
friend std::ostream& operator<<(std::ostream& cout, const Person& p);
public:
Person(std::string name, std::string sex, int age);
Person();
void Set_Name(std::string name);
void Set_Sex(std::string sex);
void Set_Age(int age);
std::string Get_Name();
std::string Get_Sex();
int Get_Age();
Person& operator=(const Person& p);
bool operator==(const Person& p);
private:
std::string m_Name;
std::string m_Sex;
int m_Age;
};
std::ostream& operator<<(std::ostream& cout, const Person& p);
- DynamicArray类方法实现
// 构造
DynamicArray::DynamicArray() {
this->m_Capactiy = 20;
this->m_Parr = new Person[this->m_Capactiy];
this->m_Size = 0;
}
// 尾插
void DynamicArray::Pushback_Array(const Person& p) {
// 空间不足
if (this->m_Size >= this->m_Capactiy) {
// 创建一个新空间
Person* NewSpace = new Person[this->m_Capactiy * 2];
// 旧数据放到新空间
for (int i = 0; i < this->m_Capactiy; i++) {
NewSpace[i].Set_Name(this->m_Parr[i].Get_Name());
NewSpace[i].Set_Sex(this->m_Parr[i].Get_Sex());
NewSpace[i].Set_Age(this->m_Parr[i].Get_Age());
//NewSpace[i] = this->m_Parr[i];
}
// 释放原有空间
delete[] this->m_Parr;
// 更改指针指向
this->m_Parr = NewSpace;
// 更新容量
this->m_Capactiy = this->m_Capactiy * 2;
}
// 插入元素
this->m_Parr[this->m_Size] = p;
// 更新长度
this->m_Size++;
}
// 根据 下标 删除
void DynamicArray::RemoveByPos_Array(const int& pos) {
if (pos < 0 || pos >= this->m_Size) {
return;
}
// pos 位置之后开始往前移动
for (int i = pos; i < this->m_Size - 1; i++) {
this->m_Parr[i] = this->m_Parr[i + 1];
}
// 更新长度
this->m_Size--;
}
// 根据 数据 删除
void DynamicArray::RemoveByVal_Array(const Person& p) {
// 通过值查找
int pos = FindByVal_Array(p);
// 通过下标删除
RemoveByPos_Array(pos);
}
// 根据 下标 查找
Person& DynamicArray::FindByPos_Array(const int& pos) {
return this->m_Parr[pos];
}
// 根据 数据 查找
int DynamicArray::FindByVal_Array(const Person& p) {
int pos = -1;
for (int i = 0; i < this->m_Size; i++) {
if (this->m_Parr[i] == p) {
pos = i;
break;
}
}
return pos;
}
// 打印
void DynamicArray::Print_Array() {
for (int i = 0; i < this->m_Size; i++) {
std::cout << this->m_Parr[i].Get_Name() << " "
<< this->m_Parr[i].Get_Sex() << " "
<< this->m_Parr[i].Get_Age()
<< std::endl;
}
std::cout << std::endl;
}
// 清空
void DynamicArray::Clear_Array() {
this->m_Size = 0;
delete[] this->m_Parr;
this->m_Parr = NULL;
}
// 获取长度
int DynamicArray::Get_Size_Array() {
return this->m_Size;
}
// 获取容量
int DynamicArray::Get_Capactiy_Array() {
return this->m_Capactiy;
}
// 析构
DynamicArray::~DynamicArray() {
if (this->m_Parr != NULL) {
delete[] this->m_Parr;
this->m_Parr = NULL;
}
}
// 重载 =
DynamicArray& DynamicArray::operator=(const DynamicArray& da) {
// 容量复制
this->m_Capactiy = da.m_Capactiy;
// 长度复制
this->m_Size = da.m_Size;
// 内容复制
for (int i = 0; i < this->m_Size; i++) {
this->m_Parr[i].Set_Name(da.m_Parr[i].Get_Name());
this->m_Parr[i].Set_Sex(da.m_Parr[i].Get_Sex());
this->m_Parr[i].Set_Age(da.m_Parr[i].Get_Age());
}
return *this;
}
- Person类实现
Person::Person(std::string name, std::string sex, int age){
this->m_Name = name;
//if (sex != "男" || sex != "女") {
// throw sex;
//}
this->m_Sex = sex;
this->m_Age = age;
}
Person::Person(){}
void Person::Set_Name(std::string name){
this->m_Name = name;
}
void Person::Set_Sex(std::string sex){
this->m_Sex = sex;
}
void Person::Set_Age(int age){
this->m_Age = age;
}
std::string Person::Get_Name(){
return this->m_Name;
}
std::string Person::Get_Sex(){
return this->m_Sex;
}
int Person::Get_Age(){
return this->m_Age;
}
Person& Person::operator=(const Person& p){
this->m_Age = p.m_Age;
this->m_Name = p.m_Name;
this->m_Sex = p.m_Sex;
return *this;
}
bool Person::operator==(const Person& p) {
if (this->m_Name == p.m_Name && this->Get_Age() == p.m_Age && this->Get_Sex() == p.m_Sex) {
return true;
}
else false;
}
std::ostream& operator<<(std::ostream& cout, const Person& p) {
std::cout << p.m_Name << " " << p.m_Sex << " " << p.m_Age << std::endl;
return std::cout;
}
在写 cpp 线性表的时候出现很奇怪的bug,平时一般都是头文件(.h)写声明,源文件(.cpp)写实现,两个文件名写成相同的,但是总是出现 LNK2019 的错误链接器工具错误 LNK2019 | Microsoft Docs
文档看了半天也没看出来哪里有问题,最后把写实现的(.cpp)文件改了名字(不和 .h 头文件一样)结果就好了
期间试了很多方法,说把头文件后缀改为 (.hpp、.H 、....)都尝试过,但都不行