C++ 中常用的一些东西, 通过使用动态数组来实现顺序表,
掌握了一下知识点:
1. 预处理有三中方法
宏定义, 文件包含, 条件编译
2. 使用同名的变量时, 可以在外层使用命名空间 类解决变量名重定义的错误
3. 类中三个访问权限,
public : 公有访问权限, 主要写一些函数接口
protected: 保护访问
private 私有访问权限 封装性,
4. 构造函数 \ 析构函数
5. 重载运算符
sub.h 文件
- /*
- 实现一个顺序表
- 1. 创建类. 成员包含. 指向顺序表的指针, 顺序表的长度, 顺序表的元素个数
- 2. 实现功能: 添加, 删除, 修改, 查看
- */
- // 用头文件进行声明的时候, 可以使用 ifnedf endif
- #ifndef __SUB_H__
- /*
- #ifndef 是 if not define 的简写
- 它是预处理功能三种 (宏定义, 文件包含, 条件编译) 的条件编译
- 再 C++ 中使用可以避免出现 "变量重复定义的错误"
- */
- #define __SUB_H__
- #include <iostream>
- using namespace std;
- // 使用作用域, 保证函数名不会出错
- namespace data
- {
- // 创建 vector 类
- class vector
- {
- // 定义私有成员, 包括指向空间的指针, 空间大小, 空间元素个数
- private:
- int *element = nullptr;
- size_t count = 0; //size_t 是地址线宽度 int 是数据线宽度,
- size_t length = 0;
- // 定义保护成员 新空间不足需要生成新空间
- protected:
- bool re_new(int size);
- // 定义公有成员函数包括: 构造函数, 析构函数, 成员其它函数
- public:
- // 可以统一使用返回值为 bool 的来确定函数的使用情况
- // 析构函数 进行初始化的作用
- // 这里首先, 初始化一下, 默认参数 在这里声明 定义不用
- vector(int count=10);
- // 析构函数 进行指针等的释放工作
- ~vector();
- // 顺序表添加 使用 bool 为返回值, 方便检测是否函数运行成功
- // 插入需要两个参数: 分别是插入的位置, 插入的内容
- bool insert(int index, int elem);
- // 顺序表删除 只需要插入删除的位置即可
- bool erase(int index);
- // 重载[] 进行内容的查找及修改
- int & operator[](int index);
- // 查看元素个数
- int Ssize()const { return length; }
- // 运算符重载, 方便输出
- // 使用友元函数重载 cout 运算符
- friend ostream & operator<<(ostream & o, const vector & vec);
- };
- }
- #endif // !__SUB_H__
sub.cpp 文件
- #include "sub.h"
- using namespace std;
- // 前边类定义了作用域, 这里需要使用才能访问
- namespace data
- {
- // 构造函数 需要作用域来明确函数属于哪里
- vector::vector(int count ) // 参数已经为 10, 在声明中
- {
- // 初始化基本成员变量
- // 因为要使用类内的 count 来赋值, 碰到相同变量名,
- // 使用 this 指针来区分. 有 this 指针的是属于类的变量
- this->count = count;
- length = 0; // 元素个数, 初始为 0
- // 初始化指向顺序表空间的指针
- // 在堆内申请空间, 空间大小为 count
- element = new int[count]; // = {0}; 初始化繁琐
- // 申请完空间需要对空间进行初始化 \
使用 memset(指针变量, 初始值, 空间大小 )
- memset(element ,0,sizeof(int)*count);
- }
- // 析构函数 析构没参数, 构造有参数, 参数可变
- // 析构函数 用来释放对象占用的空间
- vector::~vector()
- {
- // 首先释放指向空间的指针
- // 判断指针现在是否为空
- if (element!=nullptr)
- {
- // 使用 new 申请, delete 进行释放,
- // 这里使用方括号是因为 申请时, 类型是 int[]
- delete[] element;
- }
- // 初始化元素个数
- length = 0;
- }
- // 顺序表插入 \ 添加
- /*
- 需要考虑:
- 1. 插入的位置是否合适, 有可能插入的是 - 1 的位置, 数组下标最小为 0,-1 就会出现错误
- 2. 判断空间大小, 因为空间大小是初始设定的, 在添加数据时有可能数据超出
- 3. 添加元素的位置, 需要讲后边的所有元素向后移动一位, 才能空出来
- 4. 将空出来的位置赋值需要的元素
- 5. 将元素个数 +1
- 6. 返回成功
- */
- //index 为插入的位置, elem 为插入的元素内容
- // 不要忘记类的作用域
- bool vector::insert(int index ,int elem)
- {
- //1. 判断位置
- if (index<0 || index>length)
- {
- // 因为不合适, 所以需要退出程序
- return false;
- }
- //2. 判断空间大小 看元素个数是否和空间大小相等, 相等说明空间不足
- if (length == count)
- {
- // 相等说明空间不足, 需要开辟新内存
- // 这里直接使用 类的成员函数, 如果开辟空间失败需要提示一下
- if (!re_new(count+10))
- {
- printf("空间申请失败!");
- // 使用 system 让用户看到提示
- system("pause");
- //exit 为 C++ 的退出函数, exit(0)正常退出, 非 0 非正常退出
- exit(-1);
- }
- }
- //3. 插入位置移动 通过循环遍历, 位置, 将位置后移
- // 这里的 i 需要等于元素的个数, 因为总长度才能找到对应 存在的位置
- // 当 i 到需要插入的位置时, 在向后移动一次, 就可以空出这个位置了
- for (int i=length-1; i>=index; --i )
- {
- // 将当前位置元素移动到下一个位置,
- element[i + 1] = element[i];
- }
- // 将插入位置 赋值内容
- element[index] = elem;
- // 因为插入了一个内容所以需要将元素个数 +1
- ++length;
- // 返回成功
- return true;
- }
- // 删除元素
- /*
- 需要考虑:
- 1. 判断位置是否有效
- 2. 删除的位置, 后边的依次向前移动一位
- 这里需要注意, 最后一位的问题. 因为是依次向前移动, 所以需要将最后一位赋值为 0 ,
- 就是说: 最后一个元素的下一位也要向前移动, 覆盖原来的元素
- 3. 将元素个数 -1
- 4. 返回成功
- */
- // 只需要删除的位置即可
- bool vector::erase(int index)
- {
- //1. 判断位置 因为 length 表示多少个元素, 所以 length -1 是下标的位置
- if (index <0 || index>length-1)
- {
- return true;
- }
- //2. 删除元素
- for (int i =index;i<=length-1;i++ )
- {
- element[i] = element[i + 1];
- }
- //3. 元素个数 -1
- --length;
- //4. 返回成功
- return true;
- }
- // 重载[] 方便存取元素
- int & vector::operator[](int index)
- {
- // 重载运算符, 不能改变运算符的性质,
- //[]就是一个下标值, 所以这里可以进行, 查询和修改
- return element[index];
- }
- // 开辟新空间 调用此函数说明空间不足, 需要重新分配
- bool vector::re_new(int size)
- {
- // 申请堆空间, 大小为 size 是实参传进来比原空间大 10 的数,
- // 如果向让程序更优, 这里需要设置成原数的 2 倍, 避免多次分配空间
- int* new_element = new int[size];
- // 申请堆空间后, 需要初始化 使用 memset
- memset(new_element , 0 , sizeof(int)*size);
- // 这里还要检测一下空间是否申请成功
- if (!new_element) // 申请成功返回的是 1, 取反, 就是 0 , 不进入判断
- {
- return false;
- }
- // 将原空间的内容拷贝到新空间 使用 memcpy 函数
- memcpy(new_element,element,this->count*sizeof(int));
- // 释放原来空间
- delete[] element;
- // 将指针指向新空间
- element = new_element;
- // 这里不要忘记, 原来空间替换成新空间大
- this->count = size;
- // 返回成功
- return true;
- }
- // 因为这里是友元函数, 所以属于一个全局函数, 不需要类名作用域
- ostream& operator<<(ostream & o,const vector & vec)
- {
- for (int i=0;i<vec.Ssize();i++)
- {
- //endls 是 输出一个空格
- o << vec.element[i] << ends;
- }
- return o;
- }
- }
main.cpp 文件
- #include "sub.h"
- int main()
- {
- // 这里需要作用于来定义类的对象
- // 当创建对象以后, 构造函数就执行
- data::vector vec(10);
- // 写入元素
- for (int i =0;i<30;i+=2)
- {
- vec.insert(0, i + 1);
- }
- // 经过运算符重载, vec 可以直接输出
- cout << vec << endl;
- // 查询第几个位置, 第几个值
- cout << vec.operator[](5) << endl;
- // 将第几个值, 修改成多少
- vec.operator[](5) = 555;
- cout << vec << endl;
- return 0;
- }
来源: https://www.cnblogs.com/0x0000/p/10456792.html