【数据结构】顺序表

  • 基本概念

线性表是 0 个或者多个数据元素的有序序列

-

特性

  1. 数据元素之间是有序的
  2. 数据元素个数是有限的
  3. 数据元素类型是相同的

  • 性质
  • a_{0} 为线性表的第一个元素,只有一个后继。
  • a_{n} 为线性表的最后一个元素,只有一个前驱。
  • 除 a_{0} 和 a_{n} 外的其他元素 a_{i} ,既有前驱,又有后继。
  • 线性表能够逐项访问和顺序存放。

  • 线性表存储的方式

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储数据元素


 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 、....)都尝试过,但都不行

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值