diff --git a/README.md b/README.md index f734c5a..15c4c43 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,5 @@ #### day7: 函数模板, 类模板, 类模板与友元一起使用的情况, 类型转换函数(static_cast, dynamic_cast, const_cast, reinterpret_cast) #### day8: 异常处理, STL(容器、算法、迭代器) + +#### day9: STL-> string, vector, deque, stack diff --git a/day10/readme.assets/image-20230804074147635.png b/day10/readme.assets/image-20230804074147635.png new file mode 100755 index 0000000..323bd41 Binary files /dev/null and b/day10/readme.assets/image-20230804074147635.png differ diff --git a/day10/readme.assets/image-20230804075335829.png b/day10/readme.assets/image-20230804075335829.png new file mode 100755 index 0000000..58d557c Binary files /dev/null and b/day10/readme.assets/image-20230804075335829.png differ diff --git a/day10/readme.assets/image-20230804083406386.png b/day10/readme.assets/image-20230804083406386.png new file mode 100755 index 0000000..76fab8f Binary files /dev/null and b/day10/readme.assets/image-20230804083406386.png differ diff --git a/day10/readme.assets/image-20230804083459911.png b/day10/readme.assets/image-20230804083459911.png new file mode 100755 index 0000000..d82b733 Binary files /dev/null and b/day10/readme.assets/image-20230804083459911.png differ diff --git a/day10/readme.assets/image-20230804083751044.png b/day10/readme.assets/image-20230804083751044.png new file mode 100755 index 0000000..71cb305 Binary files /dev/null and b/day10/readme.assets/image-20230804083751044.png differ diff --git a/day10/readme.md b/day10/readme.md new file mode 100755 index 0000000..5a74d48 --- /dev/null +++ b/day10/readme.md @@ -0,0 +1,289 @@ +## 二、STL容器II + +### 2.1 queue 容器 + +#### 2.1.1 queue概念 + +> Queue 是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口,queue +> 容器允许从一端新增元素,从另一端移除元素。 + +![image-20230804074147635](./readme.assets/image-20230804074147635.png) + +#### 2.1.2 queue 没有迭代器 + +Queue 所有元素的进出都必须符合”先进先出”的条件,只有 queue 的顶端元素,才 +有机会被外界取用。Queue 不提供遍历功能,也不提供迭代器。 + + + +#### 2.1.3 常用API + +##### 2.1.3.1 构造函数 + +```c++ +queue queT; //queue 采用模板类实现,queue 对象的默认构造形式: +queue(const queue &que);//拷贝构造函数 +``` + + + +##### 2.1.3.2 存取、插入和删除 + +```c++ +void push(elem); //往队尾添加元素 +void pop(); //从队头移除第一个元素 +T back(); //返回最后一个元素 +T front(); //返回第一个元素 +``` + + + +##### 2.1.3.3 赋值与大小 + +```c++ +queue& operator=(const queue &que);//重载等号操作符 + +empty();//判断队列是否为空 +size();//返回队列的大小 +``` + + + +### 2.2 list 容器 + +#### 2.2.1 list 概念 + +list(链表)是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 + +链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。 + +每个结点包括两个部分: + +``` +1)存储数据元素的数据域, +2)存储下一个结点地址的指针域 +``` + +list与vector的比较: + +``` +1) 相对于vector 的连续线性空间,list 就显得负责许多,每次插入或者删除一个元素,就是配置或者释放一个元素的空间。不浪费多余的空间,且插入与移除元素的操作是常数时间(稳定)。 +2)list和vector 是两个最常被使用的容器, 但list是由双向链表实现的。 +3)list插入操作和删除操作都不会造成原有 list 迭代器的失效。 【重要特性】 +``` + + + +list特点: + +``` +1)采用动态存储分配,不会造成内存浪费和溢出 +2)链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素 +3)链表灵活,但是空间和时间额外耗费较大 +``` + +#### 2.2.2 list 的迭代器 + +List 不能像 vector 一样以普通指针作为迭代器,因为其节点不能保证在同一块连续的内存空间上。。List 迭代器必须有能力指向 list 的节点,并有能力进行正确的递增、递减、取值、成员存取操作。**递增**时指向下一个节点,**递减**时指向上一个节点,**取值**时取的是节点的数据值,**成员取用**时取的是节点的成员。 + +另外,list 是一个双向链表,迭代器必须能够具备前移、后移的能力,所以 list 容器提供的是 Bidirectional Iterators.(双向的迭代器)。 + + List 有一个重要的性质,插入操作和删除操作都不会造成原有 list 迭代器的失效。 + +【注意】list的迭代器,不支持`+n`操作。 + +#### 2.2.3 list 数据结构 + +> list 容器不仅是一个双向链表,而且还是一个循环的双向链表。 + +#### 2.2.4 常用API + +##### 2.2.4.1 构造函数 + +```c++ +list lstT;//list 采用采用模板类实现,对象的默认构造形式: +list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。 +list(n,elem);//构造函数将 n 个 elem 拷贝给本身。 +list(const list &lst);//拷贝构造函数 +``` + + + +##### 2.2.4.2 插入和删除 + +```c++ +push_back(elem);//在容器尾部加入一个元素 +pop_back();//删除容器中最后一个元素 +push_front(elem);//在容器开头插入一个元素 +pop_front();//从容器开头移除第一个元素 +insert(pos,elem);//在 pos 位置插 elem 元素的拷贝,返回新数据的位置。 +insert(pos,n,elem);//在 pos 位置插入 n 个 elem 数据,无返回值。 +insert(pos,beg,end);//在 pos 位置插入[beg,end)区间的数据,无返回值。 +clear();//移除容器的所有数据 + +erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。 +erase(pos);//删除 pos 位置的数据,返回下一个数据的位置。 +remove(elem);//删除容器中所有与 elem 值匹配的元素 +``` + +##### 2.2.4.3 大小 + +```c++ +size();//返回容器中元素的个数 +empty();//判断容器是否为空 +resize(num);//重新指定容器的长度为 num, 若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除 +resize(num, elem); +``` + +##### 2.2.4.4 赋值 + +```c++ +assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。 +assign(n, elem); //将 n 个 elem 拷贝赋值给本身。 +list& operator=(const list &lst); //重载等号操作符 +swap(lst); //将 lst 与本身的元素互换。 +``` + +##### 2.2.4.5 读取 + +``` +front();//返回第一个元素。 +back();//返回最后一个元素 +``` + +##### 2.2.4.6 反转和排序 + +``` +reverse(); //反转链表 +sort(); //list 排序 +``` + + + +### 2.3 set/multiset 容器 + +#### 2.3.1 set概念 + +set 的特性是所有元素都会根据元素的键值自动被排序。 + +set 的元素即是键值又是实值, 不允许两个元素有相同的键值。 + +set 的 iterator 是一种 const_iterator, 不允许修改set的键值。 + +set 拥有和 list 某些相同的性质,当对容器中的元素进行插入操作或者删除操作的 +时候,操作之前的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器必然是一个例外。 + +#### 2.3.2 set数据结构 + +multiset 特性及用法和 set 完全相同,唯一的差别在于它允许键值重复。set 和multiset 的底层实现是红黑树,红黑树为平衡二叉树的一种。 + +二叉树就是任何节点最多只允许有两个字节点。分别是左子结点和右子节点: + + + +二叉搜索树,是指二叉树中的节点按照一定的规则进行排序,使得对二叉树中元素访问更加高效: + + + +二叉搜索树的放置规则是: + +任何节点的元素值一定大于其左子树中的每一个节点的元素值,并且小于其右子树的值。因此从根节点一直向左走,一直到无路可走,即得到最小值,一直向右走,直至无路可走,可得到最大值。那么在二叉搜索树中找到最大元素和最小元素是非常简单的事情。 + +如上图所示:那么当一个二叉搜索树的左子树和右子树不平衡的时候,那么搜索依据上图表示,搜索 9 所花费的时间要比搜索 17 所花费的时间要多,由于我们的输入或者经过我们插入或者删除操作,二叉树失去平衡,造成搜索效率降低。 + + + +#### 2.3.3 常用API + +##### 2.3.3.1 构造函数 + +```c++ +set st;//set 默认构造函数: +mulitset mst; //multiset 默认构造函数: +set(const set &st);//拷贝构造函数 +``` + +##### 2.3.3.2 赋值和大小 + +```c++ +set& operator=(const set &st);//重载等号操作符 +swap(st);//交换两个集合容器 + +size();//返回容器中元素的数目 +empty();//判断容器是否为空 +``` + + + +##### 2.3.3.3 插入和删除 + +``` +insert(elem); //在容器中插入元素。 +clear(); //清除所有元素 +erase(pos); //删除 pos 迭代器所指的元素,返回下一个元素的迭代器。 +erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。 +erase(elem); //删除容器中值为 elem 的元素。 +``` + +##### 2.3.3.4 查找 + +```c++ +find(key); //查找键 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返 +回 set.end(); +count(key);//查找键 key 的元素个数 +lower_bound(keyElem);//返回第一个 key>=keyElem 元素的迭代器。 +upper_bound(keyElem);//返回第一个 key>keyElem 元素的迭代器。 +equal_range(keyElem);//返回容器中 key 与 keyElem 相等的上下限的两个迭代器。 +``` + +##### 2.3.3.5 set 排序规则 + +> set自动排序, 但可以改变它的排序规则,默认从小到大。 + +自定义排序规则,可以使用struct或class, 声明 `bool operator(v1, v2)`仿函数重载。 + + + +#### 2.3.4 对组(pair) + +对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可 +以分别用 pair 的两个公有属性 first 和 second 访问。 + +``` +类模板:template struct pair +``` + +用法一: + +```c++ +pair pair1(string("name"), 20); +cout << pair1.first << endl; +cout << pair1.second << endl; +``` + +用法二: + +```c++ +pair pair2 = make_pair("name", 30); +cout << pair2.first << endl; +cout << pair2.second << endl; +``` + +用法三: + +```c++ +pair pair3 = pair2; +cout << pair3.first << endl; +cout << pair3.second << endl; +``` + + + +### 2.4 map/multimap 容器 + +Map 的特性是所有元素都会根据元素的键值自动排序。 + +Map 所有的元素都是pair,同时拥有实值和键值,pair 的第一元素被视为键值,第二元素被视为实值,map 不允许两个元素有相同的键值。 + +multimap 和 map 的操作类似,唯一区别 multimap 键值可重复。 +map 和 multimap 都是以红黑树为底层实现机制。 \ No newline at end of file diff --git a/day10/stl_algorithm_demo/d1.cpp b/day10/stl_algorithm_demo/d1.cpp new file mode 100644 index 0000000..07aaff6 --- /dev/null +++ b/day10/stl_algorithm_demo/d1.cpp @@ -0,0 +1,33 @@ +// 函数对象 +// 仿函数: 一元,二元仿函数 +#include + +using namespace std; + +// 一元仿函数 +class A +{ +public: + A(int n) : n(n) {} + int n; + // 重载 operator() 运算符,只要调用 A 对象的 (int x) ,就会给对象的对应成员对象加一个 x + A &operator()(int i) + { + this->n += i; + return *this; + } +}; + +void print(A a, int n) // A a = A(30) +{ + a(n); + cout << "a.n = " << a.n << endl; +} + +int main() +{ + // 打印 a 对象的值加额外的值的结果 + print(A(20), 3); // A(20) 会创建一个匿名对象 + + return 0; +} diff --git a/day10/stl_algorithm_demo/d2.cpp b/day10/stl_algorithm_demo/d2.cpp new file mode 100644 index 0000000..167550d --- /dev/null +++ b/day10/stl_algorithm_demo/d2.cpp @@ -0,0 +1,59 @@ +// 谓词 +// gt 大于, ge 大于等于 +// lt 小于, le 小于等于 +// eq 等于, ne 小于等于 +#include +#include +#include + +using namespace std; + +class GTFive // 一元谓词 +{ +public: + bool operator()(int n) + { + return n > 5; + } +}; + +class GT // 二元谓词 +{ +public: + bool operator()(const int &n1, const int &n2) + { + return n1 > n2; + } +}; + +void printGTF(GTFive gtf, int *p, int size) +{ + for (int i = 0; i < size; i++) + { + if (gtf(p[i])) + cout << p[i] << " "; + } + cout << endl; +} + +void print(int *p, int size, GT gt, int n) +{ + for (int i = 0; i < size; i++) + { + if (gt(p[i], n)) + cout << p[i] << " "; + } + cout << endl; +} + +int main() +{ + int ms[] = {1, 2, 4, 7, 9, 20}; + cout << "大于 5 的元素" << endl; + printGTF(GTFive(), ms, 6); + + cout << "大于 7 的元素" << endl; + print(ms, 6, GT(), 7); + + return 0; +} diff --git a/day10/stl_algorithm_demo/d3.cpp b/day10/stl_algorithm_demo/d3.cpp new file mode 100644 index 0000000..52f14b6 --- /dev/null +++ b/day10/stl_algorithm_demo/d3.cpp @@ -0,0 +1,39 @@ +// 算术类函数对象 +// 算术类函数对象 +#include +#include +#include + +using namespace std; + +// template +void print(typename set::const_iterator start, + typename set::const_iterator end, plus pl, int m) +{ + for (; start != end; start++) + { + cout << pl(*start, m) << " "; + } + cout << endl; +} + +void print(typename set::const_iterator start, + typename set::const_iterator end, multiplies mul, int m) +{ + for (; start != end; start++) + { + cout << mul(*start, m) << " "; + } + cout << endl; +} + +int main() +{ + int m[] = {1, 2, 3, 4, 8, 5, 1, 2}; + // set 会自动过滤重复,并排序 + set s(m, m + sizeof(m) / sizeof(m[0])); + print(s.begin(), s.end(), plus(), 1); + print(s.begin(), s.end(), multiplies(), 3); + + return 0; +} diff --git a/day10/stl_algorithm_demo/f1.cpp b/day10/stl_algorithm_demo/f1.cpp new file mode 100644 index 0000000..1087f63 --- /dev/null +++ b/day10/stl_algorithm_demo/f1.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +using namespace std; + +// template +void print(typename set::const_iterator start, + typename set::const_iterator end, plus pl, int m) +{ + for (; start != end; start++) + { + cout << pl(*start, m) << " "; + } + cout << endl; +} + +void print(typename set::const_iterator start, + typename set::const_iterator end, multiplies mul, int m) +{ + for (; start != end; start++) + { + cout << mul(*start, m) << " "; + } + cout << endl; +} + +void show(int n) +{ + cout << n << " "; +} + +// 二元仿函数 +class PrintPlus : public binary_function +{ +public: + void operator()(const int &n1, const int &n2) const + { + cout << n1 << "+" << n2 << " = " << n1 + n2 << endl; + } +}; + +int main() +{ + int m[] = {1, 2, 3, 4, 8, 5, 1, 2}; + // set 会自动过滤重复,并排序 + set s(m, m + sizeof(m) / sizeof(m[0])); + // print(s.begin(), s.end(), plus(), 1); + // print(s.begin(), s.end(), multiplies(), 3); + + // for_each(s.begin(), s.end(), show); + // cout << endl; + + // PrintPlus 测试 + // for (int i = 0; i < 6; i++) + for_each(s.begin(), s.end(), bind1st(PrintPlus(), i)); + + return 0; +} diff --git a/day10/stl_algorithm_demo/f2.cpp b/day10/stl_algorithm_demo/f2.cpp new file mode 100644 index 0000000..72a0f1c --- /dev/null +++ b/day10/stl_algorithm_demo/f2.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +using namespace std; + +class PrintGt5Adapter : public binary_function +{ +public: + void operator()(const int &n1, const int &n2) const + { + if (n1 > n2) + cout << n1 << " "; + } +}; + +int main() +{ + int m[] = {1, 2, 3, 4, 8, 5, 1, 2}; + set s(m, m + sizeof(m) / sizeof(m[0])); + + for_each(s.begin(), s.end(), bind2nd(PrintGt5Adapter(), 2)); + + return 0; +} diff --git a/day10/stl_algorithm_demo/f3.cpp b/day10/stl_algorithm_demo/f3.cpp new file mode 100644 index 0000000..c91dc0d --- /dev/null +++ b/day10/stl_algorithm_demo/f3.cpp @@ -0,0 +1,43 @@ +// 取反适配器 +#include +#include +#include + +using namespace std; +// 自定义一个适配器,只需要容器中元素即可。 +class GT5 : public unary_function +{ +public: + bool operator()(const int &n) const + { + return n > 5; + } +}; + +class GTN : public binary_function +{ +public: + bool operator()(const int &n1, const int &n2) const + { + return n1 > n2; + } +}; + +int main() +{ + int m[] = {1, 2, 2, 3, 5, 10}; + vector v; + v.assign(m, m + sizeof(m) / sizeof(m[0])); + + // find_if(start, end, _callback) 返回查找到的第一个迭代器的位置 + vector::iterator ret = find_if(v.begin(), v.end(), not1(bind2nd(greater(), 3))); + cout << *ret << endl; + + ret = find_if(v.begin(), v.end(), GT5()); + cout << *ret << endl; + + ret = find_if(v.begin(), v.end(), bind2nd(GTN(), 3)); + cout << *ret << endl; + + return 0; +} diff --git a/day10/stl_algorithm_demo/f4.cpp b/day10/stl_algorithm_demo/f4.cpp new file mode 100644 index 0000000..3119ecf --- /dev/null +++ b/day10/stl_algorithm_demo/f4.cpp @@ -0,0 +1,26 @@ +// 函数指针适配 +// 使用 ptr_fun<>() 适配函数指针 +// <> 中的第一个参数是函数指针的类型,第二个参数是函数指针的参数类型,第三个参数是函数指针的返回值类型 +// bind1st() 和 bind2nd() 适配函数对象 +#include +#include +#include + +using namespace std; + +bool gtn(int n1, int n2) +{ + return n1 > n2; +} + +int main() +{ + int m[] = {1, 2, 2, 3, 5, 10}; + vector v; + v.assign(m, m + sizeof(m) / sizeof(m[0])); + + vector::iterator ret = find_if(v.begin(), v.end(), bind2nd(ptr_fun(gtn), 3)); + cout << *ret << endl; + + return 0; +} diff --git a/day10/stl_algorithm_demo/f5.cpp b/day10/stl_algorithm_demo/f5.cpp new file mode 100644 index 0000000..1dc5dea --- /dev/null +++ b/day10/stl_algorithm_demo/f5.cpp @@ -0,0 +1,39 @@ +// mem_fn 有两个重载版本: +// 用法1:mem_fn(&MyClass::printMessage) 用于将成员函数转换为函数对象 +// 用法2:mem_fn(&MyClass::printMessage)(&obj, "hello world") 用于调用成员函数 +// mem_fn 是一个函数模板,它接受一个成员函数指针或成员函数引用,并返回一个函数对象,该对象可以调用相应的成员函数。 +#include +#include +#include + +using namespace std; + +class Stu +{ +private: + string name; + int age; + +public: + Stu(const string &name, int age) : name(name), age(age) {} + +public: + void show() + { + cout << "name is " << name << ", age is " << age << endl; + } +}; + +int main() +{ + vector vs; + vs.push_back(Stu("disen", 18)); + vs.push_back(Stu("lucy", 20)); + vs.push_back(Stu("jack", 15)); + vs.push_back(Stu("mack", 19)); + + // 遍历容器中所有成员,成员函数作为仿函数时,则通过容器成员调用它的仿函数 + for_each(vs.begin(), vs.end(), mem_fun_ref(&Stu::show)); + + return 0; +} diff --git a/day10/stl_algorithm_demo/f6.cpp b/day10/stl_algorithm_demo/f6.cpp new file mode 100644 index 0000000..8a4c351 --- /dev/null +++ b/day10/stl_algorithm_demo/f6.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +using namespace std; +using namespace std::placeholders; + +int main() +{ + int m[] = {1, 2, 2, 3, 5, 10}; + vector v; + v.assign(m, m + sizeof(m) / sizeof(m[0])); + + int target = 3; + + // 使用 std::bind 适配 std::equal_to + vector::iterator ret = adjacent_find(v.begin(), v.end(), bind(equal_to(), _1, 3)); + cout << *(++ret) << endl; + + if (ret != v.end()) + { + cout << "Found adjacent elements equal to " << target << "." << endl; + } + else + { + cout << "No adjacent elements equal to " << target << " found." << endl; + } + return 0; +} diff --git a/day10/stl_list_demo/d1.cpp b/day10/stl_list_demo/d1.cpp new file mode 100644 index 0000000..4c67098 --- /dev/null +++ b/day10/stl_list_demo/d1.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +using namespace std; + +template +void print(const list &lst) +{ + for (typename list::const_iterator it = lst.begin(); it != lst.end(); ++it) + cout << *it << ' '; + cout << endl; +} + +int main() +{ + list lst1(6, 5); // 6 个 5 + print(lst1); + + string s1 = "abcdefg"; + + // 将 string 字符串转换为 list + list lst2(s1.begin(), s1.end()); + print(lst2); + + return 0; +} diff --git a/day10/stl_list_demo/d2.cpp b/day10/stl_list_demo/d2.cpp new file mode 100644 index 0000000..2644474 --- /dev/null +++ b/day10/stl_list_demo/d2.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +using namespace std; + +template +void print(const list &lst) +{ + for (typename list::const_iterator it = lst.begin(); it != lst.end(); ++it) + cout << *it << ' '; + cout << endl; +} + +int main() +{ + string s = "abcdefg"; + + // 将 string 字符串转换为 list + list l(s.begin(), s.end()); + int size = l.size(); // 获取大小 + print(l); + + // list 手写逆序 + list::iterator it = l.begin(); // 迭代器指向第一个元素 + for (int i = 0; i < size; i++) // 逆序 size 次 + { + it = l.insert(it, l.back()); // 将最后一个元素插入到第一个元素之前 + it++; // 迭代器指向下一个元素 + l.pop_back(); // 删除最后一个元素 + } + + print(l); + + return 0; +} diff --git a/day10/stl_list_demo/d3.cpp b/day10/stl_list_demo/d3.cpp new file mode 100644 index 0000000..b9e8bef --- /dev/null +++ b/day10/stl_list_demo/d3.cpp @@ -0,0 +1,35 @@ +#include +#include +#include + +using namespace std; + +template +void print(const list &lst) +{ + for (typename list::const_iterator it = lst.begin(); it != lst.end(); ++it) + cout << *it << ' '; + cout << endl; +} + +int main() +{ + string s = "abcdefg"; + list l(s.begin(), s.end()); + + // 删除 cde + // list::iterator it = find(l.begin(), l.end(), 'c'); + // l.erase(it, find(l.begin(), l.end(), 'e')); + + list::iterator it = l.begin(); // 迭代器指向第一个元素 + for (int i = 0; i < 2; i++) // 迭代器指向第三个元素 + it++; + list::iterator it2 = it; // 迭代器指向第三个元素 + for (int i = 0; i < 3; i++) // 迭代器指向第六个元素 + it2++; + l.erase(it, it2); // 删除第三个到第五个元素 + + print(l); // a b f g + + return 0; +} diff --git a/day10/stl_list_demo/d4.cpp b/day10/stl_list_demo/d4.cpp new file mode 100644 index 0000000..5cd223d --- /dev/null +++ b/day10/stl_list_demo/d4.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +using namespace std; + +template +void print(const list &lst) +{ + for (typename list::const_iterator it = lst.begin(); it != lst.end(); ++it) + cout << *it << ' '; + cout << endl; +} + +int main() +{ + string s = "abcdefg"; + list l(s.begin(), s.end()); + print(l); + l.reverse(); // 逆序 + print(l); + + int m[] = {6, 4, 2, 0, 8, 6, 4}; + list l2(m, m + 7); + print(l2); + l2.sort(); // 排序 + print(l2); + l2.reverse(); // 逆序 + print(l2); + + return 0; +} diff --git a/day10/stl_map_demo/d1.cpp b/day10/stl_map_demo/d1.cpp new file mode 100644 index 0000000..efa8cc2 --- /dev/null +++ b/day10/stl_map_demo/d1.cpp @@ -0,0 +1,26 @@ +#include +#include + +using namespace std; + +int main() +{ + map ms; + + // 1. insert()函数 + // map 在插入时会自动根据 map 的键来排序 + ms.insert(pair(1, "张三")); // pair是map::value_type的类型 + ms.insert(pair(4, "李四")); + ms.insert(make_pair(3, "王五")); // make_pair()函数可以自动推导出类型 + ms.insert(map::value_type(2, "赵六")); // value_type是map的类型 + ms[5] = "田七"; // 通过下标的方式插入数据 + + map::iterator it = ms.begin(); + for (; it != ms.end(); it++) + { + // cout << "sid = " << it->first << ",name = " << it->second << endl; + cout << "sid = " << (*it).first << ",name = " << (*it).second << endl; + } + + return 0; +} diff --git a/day10/stl_map_demo/d2.cpp b/day10/stl_map_demo/d2.cpp new file mode 100644 index 0000000..27ef992 --- /dev/null +++ b/day10/stl_map_demo/d2.cpp @@ -0,0 +1,61 @@ +// 使用 map 来解决括号匹配 +#include +#include +#include +#include + +using namespace std; + +string left_c = "{[("; +map map1; + +bool valid(const char *p) +{ + stack stk; + int max_depth = 0; + + while (*p) + { + const char &cp = *p; + + // if (left_c.find(cp) != string::npos) // 如果当前拿到的是左括号 + if (left_c.find(cp) != -1) // 如果当前拿到的是左括号 + { + // 入栈 + stk.push(*p); + } + else // 如果当前拿到的是右括号 + { + // 弹栈 + if (stk.empty()) + return false; + + const char &top = stk.top(); + if (map1[cp] != top) + return false; + + // 当前左右匹配的后续操作 + // 求最大深度 + if (max_depth < stk.size()) + max_depth = stk.size(); + + // 弹栈前判断最大深度 + stk.pop(); + } + p++; + } + cout << "当前括号栈的最大深度为: " << max_depth << endl; + + return stk.empty(); +} + +int main() +{ + map1.insert(make_pair('}', '{')); + map1.insert(make_pair(']', '[')); + map1.insert(make_pair(')', '(')); + + cout << valid("{[()]}[[[[[()]]]]]") << endl; + cout << valid("{[())}") << endl; + return 0; +} diff --git a/day10/stl_map_demo/d3.cpp b/day10/stl_map_demo/d3.cpp new file mode 100644 index 0000000..c164679 --- /dev/null +++ b/day10/stl_map_demo/d3.cpp @@ -0,0 +1,15 @@ +#include +#include + +using namespace std; + +int main() +{ + map m; + m.insert(make_pair(1, "disen")); + m.insert(make_pair(2, "lucy")); + cout << m.size() << endl; + m.erase(1); // 删除键值为 1 的元素 + cout << m.size() << endl; + return 0; +} diff --git a/day10/stl_map_demo/d4.cpp b/day10/stl_map_demo/d4.cpp new file mode 100644 index 0000000..e7bd536 --- /dev/null +++ b/day10/stl_map_demo/d4.cpp @@ -0,0 +1,26 @@ +#include +#include + +using namespace std; + +int main() +{ + map m; + m.insert(make_pair(1, "disen")); + m.insert(make_pair(2, "lucy")); + m.insert(make_pair(3, "jack")); + + map::const_iterator it = m.find(3); + + if (it == m.end()) + { + cout << "未查找到" << endl; + } + else + { + const pair &p = *it; + cout << p.first << ", " << p.second << endl; + } + + return 0; +} diff --git a/day10/stl_queue_demo/d1.cpp b/day10/stl_queue_demo/d1.cpp new file mode 100644 index 0000000..e69de29 diff --git a/day10/stl_set_demo/d1.cpp b/day10/stl_set_demo/d1.cpp new file mode 100644 index 0000000..e13514b --- /dev/null +++ b/day10/stl_set_demo/d1.cpp @@ -0,0 +1,32 @@ +#include +#include + +using namespace std; + +template +void print(const set &s) +{ + for (typename set::const_iterator it = s.begin(); it != s.end(); ++it) + cout << *it << ' '; + cout << endl; +} + +template +void print(const multiset &s) +{ + for (typename multiset::const_iterator it = s.begin(); it != s.end(); ++it) + cout << *it << ' '; + cout << endl; +} + +int main() +{ + int m[] = {1, 2, 3, 2, 3, 4}; + set s(m, m + 6); + print(s); // set 会自动去重,输出 1 2 3 4 + + multiset ms(m, m + 6); + print(ms); // multiset 不会自动去重,输出 1 2 2 3 3 4 + + return 0; +} diff --git a/day10/stl_set_demo/d2.cpp b/day10/stl_set_demo/d2.cpp new file mode 100644 index 0000000..a62df95 --- /dev/null +++ b/day10/stl_set_demo/d2.cpp @@ -0,0 +1,50 @@ +#include +#include + +using namespace std; + +template +void print(const set &s) +{ + for (typename set::const_iterator it = s.begin(); it != s.end(); ++it) + cout << *it << ' '; + cout << endl; +} + +int main() +{ + int m[] = {5, 12, 16, 21, 22, 27, 29, 30}; + set s(m, m + 8); + print(s); // set 键值自动排序,且不重复 + + // 查看大于等于 22 值的所有元素 + cout << "查看大于等于 22 值的所有元素: " << endl; + set::iterator it = s.lower_bound(22); // 返回第一个大于等于 22 的元素的迭代器 + while (it != s.end()) + { + cout << *it << ' '; + ++it; + } + cout << endl; + + // 查找小于等于 22 值的所有元素 + cout << "查找小于等于 22 值的所有元素: " << endl; + // it = s.upper_bound(22); // 返回第一个大于 22 的元素的迭代器 + // for (; it != s.begin();) + // { + // --it; + // cout << *it << ' '; + // } + // cout << endl; + + // 查找小于等于 22 值的所有元素(另一种写法) + it = s.lower_bound(22); + while (it != s.begin()) + { + --it; + cout << *it << ' '; + } + cout << endl; + + return 0; +} diff --git a/day10/stl_set_demo/d3.cpp b/day10/stl_set_demo/d3.cpp new file mode 100644 index 0000000..d362ca9 --- /dev/null +++ b/day10/stl_set_demo/d3.cpp @@ -0,0 +1,36 @@ +// 自定义排序 +#include +#include + +using namespace std; + +// 自定义规则 +template +class MySort +{ +public: + bool operator()(const T &a, const T &b) + { + return a > b; // 从小到大排序 + } +}; + +int main() +{ + // 使用 set 时,添加自定义排序规则 + set > s1; + s1.insert(20); + s1.insert(30); + s1.insert(1); + s1.insert(8); + + set >::iterator it = s1.begin(); // > 可以省略 + while (it != s1.end()) + { + cout << *it << ' '; + ++it; + } + cout << endl; + + return 0; +} diff --git a/day10/stl_set_demo/d4.cpp b/day10/stl_set_demo/d4.cpp new file mode 100644 index 0000000..aaae4bd --- /dev/null +++ b/day10/stl_set_demo/d4.cpp @@ -0,0 +1,59 @@ +// 自定义排序 +#include +#include + +using namespace std; + +// 自定义规则 +template +class MySort +{ +public: + bool operator()(const T &a, const T &b) + { + return a > b; // 从小到大排序 + } +}; + +class Student +{ +public: + string name; + int age; + float score; + +public: + Student(const string &name, int age, float score) + { + this->name = name; + this->age = age; + this->score = score; + } +}; + +class MyStudentByAgeSort +{ +public: + bool operator()(const Student &s1, const Student &s2) + { + return s1.age > s2.age; + } +}; + +class MyStudentByScoreSort +{ +public: + bool operator()(const Student &s1, const Student &s2) + { + return s1.score > s2.score; + } +}; + +int main() +{ + Student[] *stus = new Student[3]{Student("张三", 18, 100), Student("李四", 20, 90), Student("王五", 19, 95)}; + set s2; + s2............................ + + return 0; +} diff --git a/day10/stl_set_demo/d5.cpp b/day10/stl_set_demo/d5.cpp new file mode 100644 index 0000000..660b461 --- /dev/null +++ b/day10/stl_set_demo/d5.cpp @@ -0,0 +1,12 @@ +#include +#include + +using namespace std; + +int main() +{ + // pair 是一个模板类,有两个模板参数, + // 用于存储两个数据,可以分别指定两个数据的类型 + pair p1(1, "张三"); + return 0; +} diff --git a/day10/stl_set_demo/h6.cpp b/day10/stl_set_demo/h6.cpp new file mode 100644 index 0000000..f1d8b41 --- /dev/null +++ b/day10/stl_set_demo/h6.cpp @@ -0,0 +1,40 @@ +// 对组(pair) +// 将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可 +// 以分别用 pair 的两个公有属性 first 和 second 访问。 + +// 类模板:template class pair + +// 用法一: + +// pair pair1(string("name"), 20); +// cout << pair1.first << endl; +// cout << pair1.second << endl; + +// 用法二: + +// pair pair2 = make_pair("name", 30); +// cout << pair2.first << endl; +// cout << pair2.second << endl; + +// 用法三: + +// pair pair3 = pair2; // 拷贝构造函数 +// cout << pair3.first << endl; +// cout << pair3.second << endl; + +// 如: +#include +#include +#include + +using namespace std; + +int main() +{ + pair p1(1, "disen"); + pair p2 = make_pair(2, "lucy"); + cout << "id = " << p1.first << ", name = " << p1.second << endl; + cout << "id = " << p2.first << ", name = " << p2.second << endl; + + return 0; +} \ No newline at end of file diff --git a/day5/d1.cpp b/day5/d1.cpp new file mode 100644 index 0000000..6531b08 --- /dev/null +++ b/day5/d1.cpp @@ -0,0 +1,55 @@ +// = 赋值重载 +// 注意 = 重载时,可能会调用类本身的拷贝构造函数。如果左值是没有创建的对象时, +// 会调用类的拷贝构造函数 +#include +#include +#include + +using namespace std; + +class A +{ +private: + int x; + +public: + A(int x) : x(x) + { + cout << "A(int x)" << endl; + } + A(const A &obj) + { + cout << "A(A &obj)" << endl; + this->x = obj.x; + } + A &operator=(const A &other) + { + cout << "A &operator=(A&other)" << endl; + this->x = other.x; + return *this; + } + +public: + void show() + { + cout << "x = " << x << endl; + } +}; + +int main() +{ + A a1(100), a2(200); + A a4 = 300; // A(300) + a4 = 400; // operator=() + + A a3 = a1; // A(a1) + a3.show(); + + a3 = a2; // operator=() 调用赋值重载函数 + a3.show(); + + a3 = a4; + a3.show(); + + return 0; +} diff --git a/day5/d2.cpp b/day5/d2.cpp new file mode 100644 index 0000000..22110f7 --- /dev/null +++ b/day5/d2.cpp @@ -0,0 +1,41 @@ +// () 函数调用重载 +// 当类对象作为函数调用时,会执行 operator()(参数列表) 函数 +// +#include +#include +#include + +using namespace std; + +class A +{ +private: + int x, y; + +public: + A(int x, int y) : x(x), y(y) {} + +public: + void operator()(int a, int b) + { + this->x += a; + this->y += b; + show(); + } + + void show() + { + cout << x << ", " << y << endl; + } +}; + +int main() +{ + A a1(10, 9); + a1.show(); + + a1(2, 3); // 类对象作为函数使用,实现 2+x,3+y + // a1.show(); + + return 0; +} diff --git a/day5/d3/Makefile b/day5/d3/Makefile new file mode 100644 index 0000000..a217e1c --- /dev/null +++ b/day5/d3/Makefile @@ -0,0 +1,39 @@ +# 定义路径变量 +SRC_DIR = ./ +OBJ_DIR = ./ +BIN_DIR = ./ + +# 定义编译器 +CC = g++ +STD = -std=c++11 +# 定义目标文件 +TARGET = $(BIN_DIR)/a.out +# 定义源文件 +SRCS = $(wildcard $(SRC_DIR)/*.cpp) +# OBJS = $(OBJ_DIR)/lrc.o $(OBJ_DIR)/console.o $(OBJ_DIR)/start_mplayer.o $(OBJ_DIR)/time_delay.o $(OBJ_DIR)/main.o +OBJS = $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRCS)) + +# 编译规则 +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp + $(CC) -c $< -o $@ $(STD) + +# 链接规则 +$(TARGET): $(OBJS) + $(CC) $^ -o $@ $(STD) + +# 默认构建目标 +all: $(TARGET) + +# 创建目录 +$(shell mkdir -p $(OBJ_DIR) $(BIN_DIR)) + +# 运行测试 +run: $(TARGET) + $(TARGET) + +# 清理规则 +clean: + rm -rf $(OBJ_DIR)/*.o $(TARGET) + +# 伪目标 +.PHONY: all clean \ No newline at end of file diff --git a/day5/d3/main.cpp b/day5/d3/main.cpp new file mode 100644 index 0000000..7ac40bb --- /dev/null +++ b/day5/d3/main.cpp @@ -0,0 +1,12 @@ +#include "mystring.h" +#include + +using namespace std; + +int main() +{ + MyString s1("disen"); + cout << s1 + ",lucy" << endl; + + return 0; +} \ No newline at end of file diff --git a/day5/d3/mystring.cpp b/day5/d3/mystring.cpp new file mode 100644 index 0000000..45d6384 --- /dev/null +++ b/day5/d3/mystring.cpp @@ -0,0 +1,96 @@ +#include "mystring.h" +using namespace std; + +ostream &operator<<(ostream &cout, const MyString &str) +{ + cout << str.mStr; // 输出字符串 mStr + return cout; // 返回 cout 输出流对象 +} +istream &operator<<(istream &cin, MyString &str) +{ + cin >> str.mStr; // 输入字符串 mStr + return cin; // 返回 cin 输入流对象 +} + +MyString::MyString(const char *str) +{ + mSize = strlen(str); // 计算字符串长度 + mStr = new char[mSize + 1]; // 为 '\0' 留一个位置 + strcpy(mStr, str); // 拷贝字符串 +} + +MyString::MyString(const MyString &str) +{ + mSize = str.mSize; // 拷贝字符串长度 + char *p = new char[mSize + 1]; // 为 '\0' 留一个位置 + strcpy(p, str.mStr); // 拷贝字符串 + delete[] this->mStr; // 删除之前的空间 + this->mStr = p; // 指向新的空间 +} + +MyString::~MyString() +{ + delete[] mStr; // 释放空间 +} + +// 字符串拼接 +MyString &MyString::operator+(MyString &other) +{ + mSize += other.mSize; // 计算新的字符串长度, 用原有长度加上 other 的长度 + char *p = new char[mSize + 1]; // 为 '\0' 留一个位置 + strcpy(p, mStr); // 拷贝 mStr + strcat(p, other.mStr); // 拼接 other.mStr + delete[] this->mStr; // 删除之前的空间 + this->mStr = p; // 指向新的空间 +} + +MyString &MyString::operator+(const char *other) +{ + mSize += strlen(other); // 计算新的字符串长度, 用原有长度加上 other 的长度 + char *p = new char[mSize + 1]; // 为 '\0' 留一个位置 + strcpy(p, mStr); // 拷贝 mStr + strcat(p, other); // 拼接 other + delete[] this->mStr; // 删除之前的空间 + this->mStr = p; // 指向新的空间 +} + +// 字符串赋值 +MyString &MyString::operator=(MyString &other) +{ + mSize = other.mSize; // 拷贝字符串长度 + char *p = new char[mSize + 1]; // 为 '\0' 留一个位置 + strcpy(p, other.mStr); // 拷贝字符串 + delete[] mStr; // 删除之前的空间 + mStr = p; // 指向新的空间 +} + +MyString &MyString::operator=(const char *other) +{ + mSize = strlen(other); // 拷贝字符串长度 + char *p = new char[mSize + 1]; // 为 '\0' 留一个位置 + strcpy(p, other); // 拷贝字符串 + delete[] mStr; // 删除之前的空间 + mStr = p; // 指向新的空间 +} + +// 字符串比较 +MyString &operator==(MyString &other) +{ + return strcmp(mStr, other.mStr) == 0; // 比较字符串 +} + +MyString &operator==(const char *other) +{ + return strcmp(mStr, other) == 0; // 比较字符串 +} + +// 读取字符串中 index 位置的字符 +char MyString::operator[](int index) +{ + cout << "长度: " << mSize << endl; + // index 支持负数, -1 表示倒数第一个字符 + // index 是负数,计算机存储是补码,如果直接位运算,以补码的方式 & 位运算符 + // 需要手动取反补码(~), 然后 +1 + int absIndex = (~index + 1) & 0x7fffffff; // 0x7fffffff 是有符号正整数 int 的最大值 + // 0x7fffffff = 0111 1111 1111 1111 1111 1111 1111 1111 +} diff --git a/day5/d3/mystring.h b/day5/d3/mystring.h new file mode 100644 index 0000000..e693ef5 --- /dev/null +++ b/day5/d3/mystring.h @@ -0,0 +1,42 @@ +#ifndef __MYSTRING_H__ +#define __MYSTRING_H__ + +#include +#include + +// 重载: 实现自定义字符串类 +class MyString +{ + friend ostream &operator<<(ostream &cout, const MyString &str) {} + friend istream &operator<<(istream &cout, MyString &str) {} + +public: + MyString(const char *str); // 有参构造函数 + MyString(const MyString &str); // 拷贝构造函数 + ~MyString(); // 析构函数 + +public: + // 字符串拼接 + MyString &operator+(MyString &other); // 重载 + 运算符 + MyString &operator+(const char *other); // 重载 + 运算符 + + // 字符串赋值 + MyString &operator=(MyString &other); // 重载 = 运算符 + MyString &operator=(const char *other); // 重载 = 运算符 + + // 字符串比较 + MyString &operator==(MyString &other); // 重载 == 运算符 + MyString &operator==(const char *other); // 重载 == 运算符 + + // 读取字符串中 index 位置的字符 + char operator[](int index); // 重载 [] 运算符 + +private: + char *mStr; // 字符串 + int mSize; // 字符串长度 +}; + +ostream &operator<<(ostream &cout, const MyString &str); +istream &operator<<(istream &cout, MyString &str); + +#endif \ No newline at end of file diff --git a/day5/d4.cpp b/day5/d4.cpp new file mode 100644 index 0000000..03cb52b --- /dev/null +++ b/day5/d4.cpp @@ -0,0 +1,51 @@ +// 构造函数 +#include +#include +#include + +using namespace std; + +class Person +{ +private: + string name; + int age; + +public: + Person(const string &name, int age) : name(name), age(age) {} + +public: + void hi() + { + cout << this->name << ", " << this->age << endl; + } +}; + +class Worker : public Person +{ +private: + int salary; // 工资 + int year; // 工作年限 + +public: + // 子类的构造函数定义时,可以调用父类的构造函数进行父类成员的初始化 + // 使用初始化列表实现(调用父类的构造函数,传入对应参数) + Worker(const string &name, int age, int salary, int year) : Person(name, age), salary(salary), year(year) + { + } + +public: + void hi() // 重写了父类的函数,覆盖了父类的 hi() + { + // 先调用父类的 hi() + Person::hi(); + cout << salary << ", " << year << endl; + } +}; + +int main() +{ + Worker w1 = Worker("liming", 18, 2100, 2); + w1.hi(); + return 0; +} diff --git a/day5/d5.cpp b/day5/d5.cpp new file mode 100644 index 0000000..a8d8c38 --- /dev/null +++ b/day5/d5.cpp @@ -0,0 +1,99 @@ +#include +#include +#include + +using namespace std; + +class A +{ +public: + int a; + +protected: + int b; + +private: + int c; + +public: + A(int a, int b, int c) : a(a), b(b), c(c) {} + +public: + void showA() + { + cout << "A: " << a << ", " << b << ", " << c << endl; + } +}; + +class B : public A +{ +public: + B() : A(1, 3, 2) {} + +public: + void showB() + { + showA(); + // B 类的成员函数内,可以访问父类的 public 、protected 成员 + // a, b 是父类的 public/protected 的成员变量 + cout << "B: " << a << ", " << b << endl; + } +}; + +class C : protected B +{ +public: + C() : B() {} + +public: + void showC() + { + showA(); + showB(); + cout << "C: " << a << ", " << b << endl; + } +}; + +class D : private C +{ +public: + D() : C() {} + +public: + void showD() + { + showA(); + cout << "D: " << a << ", " << b << endl; + } +}; + +class E : public D +{ +public: + E() : D() {} + +public: + void showE() + { + showA(); + // cout << "E: " << a << ", " << b << endl; + } +}; + +int main() +{ + // B b1; + // b1.showA(); + // b1.showB(); + + // C c1; + // c1.showC(); + + // D d1; + // d1.showD(); + + E e1; + e1.showD(); + + return 0; +} diff --git a/day5/d6.cpp b/day5/d6.cpp new file mode 100644 index 0000000..2a9ec1a --- /dev/null +++ b/day5/d6.cpp @@ -0,0 +1,54 @@ +#include +#include +#include + +using namespace std; + +class A +{ +public: + int x; + +private: + int y; + +public: + A(int x, int y) + // A() + { + cout << "A(int x,int y)" << endl; + // cout << "A()" << endl; + } + ~A() + { + cout << "~A()" << endl; + } +}; + +class B : public A +{ +private: + int y; + +public: + B() : A(1, 2) + { + cout << "B()" << endl; + } + ~B() + { + cout << "~B()" << endl; + } +}; + +int main() +{ + cout << "A size is " << sizeof(A) << endl; + cout << "B size is " << sizeof(B) << endl; + + B b1; // A() B() ~B() ~A() + + // A a; + + return 0; +} diff --git a/day5/d7.cpp b/day5/d7.cpp new file mode 100644 index 0000000..77fd000 --- /dev/null +++ b/day5/d7.cpp @@ -0,0 +1,46 @@ +// 继承中同名成员的处理方法 +#include +#include +#include + +using namespace std; + +class A +{ +public: + int x; + A(int x) : x(x) {} + void show() + { + cout << "x = " << x << endl; + } +}; + +class B : public A +{ +private: + int x; + +public: + // B(int x) : A(x) + // { + // // 就近原则: this->x 是 B 类的,不是父类 A 的 + // this->x = x + 20; + // } + B(int x) : A(x), x(x + 20) + { + } + + void showX() + { + cout << "x = " << x << endl; + } +}; + +int main() +{ + B b1(10); + b1.show(); // 从 A 类继承过来的方法,打印的是 A 类的 x + b1.showX(); // B 类自己的,打印自己的 a + return 0; +} diff --git a/day5/homework/h1.cpp b/day5/homework/h1.cpp new file mode 100644 index 0000000..2628646 --- /dev/null +++ b/day5/homework/h1.cpp @@ -0,0 +1,85 @@ +// 编写一个名为 String 的类,表示字符串。重载赋值运算符 = ,使其能够执行字符串的赋值操作。 +#include +#include +#include + +using namespace std; + +class String +{ +private: + char *str; + +public: + String(const char *s = NULL) // 构造函数: 默认参数为NULL,表示构造一个空字符串 + { + if (s == NULL) + str = NULL; + + else + { + str = new char[strlen(s) + 1]; + strcpy(str, s); + } + } + + String(const String &s) + { + if (s.str == NULL) + str = NULL; + + else + { + str = new char[strlen(s.str) + 1]; + strcpy(str, s.str); + } + } + + ~String() + { + if (str != NULL) // 如果str不为空,删除str + delete[] str; + } + +public: + String &operator=(const String &s) + { + if (str == s.str) + return *this; + + if (str != NULL) // 如果str不为空,则先删除str + delete[] str; // 删除的目的是为了防止内存泄漏 + + if (s.str == NULL) // 如果s.str为空,则str也为空 + str = NULL; + + else + str = new char[strlen(s.str) + 1]; // +1 是为了存放'\0' + strcpy(str, s.str); + + return *this; // 返回当前对象的引用 + } + + void print() + { + if (str != NULL) + cout << str << endl; + + else + cout << "NULL" << endl; + } +}; + +int main() +{ + String s1("hello"); + s1.print(); + String *s2 = new String("world"); + + s2->print(); + s1 = "xi'an"; + + s2 = &s1; + s2->print(); + return 0; +} \ No newline at end of file diff --git a/day5/homework/h2.cpp b/day5/homework/h2.cpp new file mode 100644 index 0000000..eefa866 --- /dev/null +++ b/day5/homework/h2.cpp @@ -0,0 +1,40 @@ +// 编写一个名为 Date 的类,表示日期。重载相等运算符 == ,使其能够比较两个日期是否相等。 +// 【提示】类中包含year, +// month, day三个变量。 +#include +#include +#include + +using namespace std; + +class Date +{ +private: + int year, month, day; + +public: + Date(int year, int month, int day) : year(year), month(month), day(day) {} + Date(const Date &d) : year(d.year), month(d.month), day(d.day) {} + ~Date() {} + +public: + bool operator==(const Date &d) + { + if (year == d.year && month == d.month && day == d.day) + { + return true; + } + return false; + } +}; + +int main() +{ + Date d1(2020, 10, 1); + Date d2(2020, 10, 1); + Date d3(2020, 10, 2); + cout << (d1 == d2) << endl; // 1 表示 true + cout << (d1 == d3) << endl; // 0 表示 false + + return 0; +} diff --git a/day5/homework/h3.cpp b/day5/homework/h3.cpp new file mode 100644 index 0000000..9b711c0 --- /dev/null +++ b/day5/homework/h3.cpp @@ -0,0 +1,62 @@ +// 编写一个名为 Matrix 的类,表示矩阵。重载乘法运算符 *,使其能够执行两个矩阵的乘法操作。 +#include +#include +#include + +using namespace std; + +class Matrix +{ +private: + int row, col; + int **matrix; + +public: + Matrix(int row, int col) : row(row), col(col) + { + matrix = new int *[row]; + for (int i = 0; i < row; i++) + matrix[i] = new int[col]; + } + + ~Matrix() + { + for (int i = 0; i < row; i++) + delete[] matrix[i]; + delete[] matrix; + } + +public: + Matrix operator*(const Matrix &m) + { + Matrix result(row, m.col); + for (int i = 0; i < row; i++) + for (int j = 0; j < m.col; j++) + for (int k = 0; k < col; k++) + result.matrix[i][j] += matrix[i][k] * m.matrix[k][j]; + return result; + } + + friend ostream &operator<<(ostream &out, const Matrix &m) + { + for (int i = 0; i < m.row; i++) + { + for (int j = 0; j < m.col; j++) + out << m.matrix[i][j] << " "; + out << endl; + } + return out; + } + + friend istream &operator>>(istream &in, Matrix &m) + { + for (int i = 0; i < m.row; i++) + for (int j = 0; j < m.col; j++) + in >> m.matrix[i][j]; + return in; + } +}; + +int main() +{ +} \ No newline at end of file diff --git a/day5/homework/h4.cpp b/day5/homework/h4.cpp new file mode 100644 index 0000000..08dfd70 --- /dev/null +++ b/day5/homework/h4.cpp @@ -0,0 +1,36 @@ +// 编写一个名为 Complex 的类,表示复数。重载加法运算符 + ,使其能够执行两个复数的加法操作。 +#include +#include +#include + +using namespace std; + +class Complex +{ +private: + double real, imag; // 实部和虚部 + +public: + Complex(double real, double imag) : real(real), imag(imag) {} + Complex(const Complex &other) : real(other.real), imag(other.imag) {} + ~Complex() {} + +public: + Complex operator+(const Complex &other) + { + return Complex(real + other.real, imag + other.imag); + } + void show() + { + cout << real << " + " << imag << "i" << endl; + } +}; + +int main() +{ + Complex c1(1, 2); + Complex c2(3, 4); + Complex c3 = c1 + c2; + c3.show(); // 4 + 6i + return 0; +} diff --git a/day5/homework/h5.cpp b/day5/homework/h5.cpp new file mode 100644 index 0000000..9735fff --- /dev/null +++ b/day5/homework/h5.cpp @@ -0,0 +1,42 @@ +// 假设有三个类,Animal(动物),Mammal(哺乳动物)和 Dog(狗)。Animal 类具有一个成员函数 eat() ,用于输出动物吃的食物。Mammal 类继承自 Animal 类,并添加了一个成员函数 giveBirth() ,用于输出哺乳动物的生育方式。Dog 类继承自 Mammal 类,并添加了一个成员函数 bark() ,用于输出狗的叫声。请在给定的类定义中完成代码,并实现相应的成员函数。 +#include +#include +#include + +using namespace std; + +class Animal +{ +public: + void eat() + { + cout << "Animal eat" << endl; + } +}; + +class Mammal : public Animal +{ +public: + void giveBirth() + { + cout << "Mammal give birth" << endl; + } +}; + +class Dog : public Mammal +{ +public: + void bark() + { + cout << "Dog bark" << endl; + } +}; + +int main() +{ + Dog dog; + dog.eat(); // Animal eat + dog.giveBirth(); // Mammal give birth + dog.bark(); // Dog bark + return 0; +} diff --git a/day5/homework/h6.cpp b/day5/homework/h6.cpp new file mode 100644 index 0000000..eb4c4c7 --- /dev/null +++ b/day5/homework/h6.cpp @@ -0,0 +1,20 @@ +// 编写一个名为 MatrixArray 的类,表示矩阵数组。重载乘法运算符 *,使其能够执行两个矩阵积操作。重载[] 运算符,实现返回某一个行的一维数组并对数组进行设置值或访问值。 +// 【提示】构造函数提供行数与列数的参数,初始值为0。 +#include +#include +#include + +using namespace std; + +class MatrixArray +{ +private: + int row, col; + int **matrix; +}; + +int main() +{ + + return 0; +} diff --git a/day5/homework/h7.cpp b/day5/homework/h7.cpp new file mode 100644 index 0000000..6992abd --- /dev/null +++ b/day5/homework/h7.cpp @@ -0,0 +1,42 @@ +// 假设有两个类,Shape(形状)和 Rectangle(矩形)。Shape 类具有一个成员函数 getArea() ,用于计算形状的面积。Rectangle 类继承自 Shape 类,并添加了两个成员变量 width(宽度)和 height(高度)。请在给定的类定义中完成代码,并实现 Rectangle 类的 getArea() 函数来计算矩形的面积。 +// 【提示】Shape的类设计如下,表示为抽象类(getArea() 是纯虚函数): +// class Shape +// { +// public: +// virtual double getArea() const = 0; +// }; + +#include +#include +#include + +using namespace std; + +class Shape +{ +public: + virtual double getArea() const = 0; +}; + +class Rectangle : public Shape +{ +private: + double width, height; + +public: + Rectangle(double width, double height) : width(width), height(height) {} + ~Rectangle() {} + +public: + double getArea() const // 重写父类的纯虚函数,const 可以保证不会修改成员变量的值 + { + return width * height; + } +}; + +int main() +{ + Shape *shape = new Rectangle(3, 4); + cout << shape->getArea() << endl; // 12 + return 0; +} diff --git a/day6/d1.cpp b/day6/d1.cpp new file mode 100644 index 0000000..8fe8944 --- /dev/null +++ b/day6/d1.cpp @@ -0,0 +1,44 @@ +// 多继承(同属一个超级父类)产生的问题 +#include +#include +#include + +using namespace std; + +class A +{ +public: + int x; +}; + +class B : virtual public A +{ +public: + B() + { + x = 50; + } +}; + +class C : virtual public A +{ +public: + C() + { + x = 100; + } +}; + +class D : public C, public B +{ +}; + +int main() +{ + D d1; + cout << d1.x << endl; + d1.x = 0; // x 是从 B 来的,还是从 C 来的? C ,使用就近原则 + cout << d1.x << endl; + + return 0; +} diff --git a/day6/d2.cpp b/day6/d2.cpp new file mode 100644 index 0000000..b2e9ac4 --- /dev/null +++ b/day6/d2.cpp @@ -0,0 +1,66 @@ +// 初尝多态 +#include +#include +#include + +using namespace std; + +// 抽象类: +// 至少有一个纯虚函数的类 +// 抽象类不能实现对象 +class AbstractCaculator // 定义计算器 +{ +protected: // 使用保护权限(目的是使子类可以访问,而其他类不可访问) + int a, b; + +public: + void setA(int a) { this->a = a; } + void setB(int b) { this->b = b; } + +public: + // 扩展功能,让子类去实现 + virtual int getResult() = 0; // 纯虚函数,声明函数并赋值为 0 +}; + +class AddCa : public AbstractCaculator +{ + // 必须要去实现纯虚函数 + int getResult() + { + return a + b; + } +}; + +class SubCa : public AbstractCaculator +{ + // 必须要去实现纯虚函数 + int getResult() + { + return a - b; + } +}; + +// 多态的体现: +// 1) 定义函数时,形参的类型为父类对象的指针 +// 2) 调用函数时,实参的类型为子类对象的指针 +int Result(AbstractCaculator *caculator, int a, int b) +{ + caculator->setA(a); + caculator->setB(b); + return caculator->getResult(); +} + +int main() +{ + // 抽象类型不能去定义对象 + // error: cannot declare variable ‘a1’ to be of abstract type ‘AbstractCaculator’ + // AbstractCaculator a1; + + AddCa *a2 = new AddCa; + cout << Result(a2, 10, 20) << endl; + cout << Result(new SubCa, 10, 20) << endl; // new SubCa 返回的是一个临时对象,不需要 delete + delete a2; + // delete new SubCa; // error: cannot delete expression of type ‘SubCa’ + + return 0; +} diff --git a/day6/d3.cpp b/day6/d3.cpp new file mode 100644 index 0000000..3471b6c --- /dev/null +++ b/day6/d3.cpp @@ -0,0 +1,41 @@ +// 向上类型转换 +#include +#include +#include + +using namespace std; + +class Printer +{ +public: + void open() + { + cout << "打印机正在开机..." << endl; + } +}; + +class DellPrinter : public Printer +{ + void open() + { + cout << "Dell打印机..." << endl; + } +}; + +class HuaweiPrinter : public Printer +{ + void open() + { + cout << "Huawei打印机..." << endl; + } +}; + +int main() +{ + DellPrinter dellprinter; + // 多态: 通过父类的引用或指针调用子类对象的成员 + // 子类对象自动向上转换位父类的类型 + Printer &printer = dellprinter; + printer.open(); // 输出: 打印机正在开机... + return 0; +} diff --git a/day6/d4.cpp b/day6/d4.cpp new file mode 100644 index 0000000..9df2e52 --- /dev/null +++ b/day6/d4.cpp @@ -0,0 +1,21 @@ +// 将父类的函数改为虚函数 +#include +#include +#include + +using namespace std; + +clacc Printer +{ +public: + virtual void open() + { + cout << "" + } +} + +int main() +{ + + return 0; +} diff --git a/day6/d5.cpp b/day6/d5.cpp new file mode 100644 index 0000000..433d960 --- /dev/null +++ b/day6/d5.cpp @@ -0,0 +1,88 @@ +#include +#include +#include + +using namespace std; + +class Animal +{ +protected: + string name; + float price; + +public: + Animal(const string &name, float price) + { + this->name = name; + this->price = price; + } + virtual void buy(); // 类内声明的虚函数 +}; + +// 类外实现类中的虚函数 +void Animal::buy() +{ + cout << "小宠物 " << name << " 卖了 " << price << endl; +} + +class Dog : public Animal +{ +private: + int age; + +public: + Dog(string name, float price, int age) : Animal(name, price), age(age) + { + } + virtual void buy() // 重写父类的虚函数 + { + cout << age << " 岁小狗 " << name << " 卖了 " << price << endl; + } + void eat() // 扩展的新功能 + { + cout << name << " 喝酒" << endl; + } +}; + +class Cat : public Animal +{ +private: + int age; + +public: + Cat(string name, float price) : Animal(name, price) + { + } + virtual void buy() // 重写父类的虚函数 + { + cout << "小猫 " << name << " 卖了 " << price << endl; + } + void eat() // 扩展的新功能 + { + cout << name << " 吃鱼" << endl; + } +}; + +class AnimalShop +{ +public: + // 多态应用之一 + void buy(Animal *animal) + { + cout << "-----动物之家正在出售小宠物-----" << endl; + animal->buy(); + cout << "-----出售结束-----" << endl; + + delete animal; // 释放堆区空间 + } +}; + +int main() +{ + AnimalShop shop; + Dog dog("旺财", 1000, 3); + // 多态的应用 + shop.buy(&dog); + shop.buy(new Cat("小花", 500)); + return 0; +} diff --git a/day6/template/t1.cpp b/day6/template/t1.cpp new file mode 100644 index 0000000..4cc64c9 --- /dev/null +++ b/day6/template/t1.cpp @@ -0,0 +1,49 @@ +// 函数模版 + +/* + template + 函数返回值 函数名(T &n1, T &n2) + { + // 函数体 + } +*/ +#include +#include +#include + +using namespace std; +namespace my +{ + // 推荐使用 typename 而不是 class,因为 typename 更通用 + template + void swap(T &a, T &b) + { + a ^= b; + b ^= a; + a ^= b; + } + + // 函数模版重载: 用于不同类型的参数 + template + void swap(T1 &a, T2 &b) + { + a ^= b; + b ^= a; + a ^= b; + } +} + +int main() +{ + int a = 2, b = 6; + cout << a << ", " << b << endl; + my::swap(a, b); // 自动推演类型: swap(a, b) + cout << a << ", " << b << endl; + + char c = 30; + cout << a << ", " << (int)c << endl; + my::swap(a, c); // 自动推演类型 + cout << a << ", " << (int)c << endl; + + return 0; +} diff --git a/day6/template/t2.cpp b/day6/template/t2.cpp new file mode 100644 index 0000000..fdc31ab --- /dev/null +++ b/day6/template/t2.cpp @@ -0,0 +1,55 @@ +// 使用函数模版实现对 char 和 int 数组的排序和打印 +#include +#include +#include + +using namespace std; + +template +void sort(T arr[], int size) +{ + for (int i = 0; i < size - 1; i++) + { + int min = i; + for (int j = i + 1; j < size; j++) + { + if (arr[min] > arr[j]) + { + min = j; + } + } + if (min != i) + { + arr[i] ^= arr[min]; + arr[min] ^= arr[i]; + arr[i] ^= arr[min]; + // T temp = arr[i]; + // arr[i] = arr[min]; + // arr[min] = temp; + } + } +} + +template +void printArr(T arr[], int size) +{ + for (int i = 0; i < size; i++) + cout << arr[i] << " "; + cout << endl; +} + +int main() +{ + int arr1[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0}; + char arr2[] = {'a', 'c', 'e', 'G', 'I', 'b', 'd', 'f', 'h', 'j'}; + int size1 = sizeof(arr1) / sizeof(arr1[0]); + int size2 = sizeof(arr2) / sizeof(arr2[0]); + + sort(arr1, size1); + sort(arr2, size2); + + printArr(arr1, size1); + printArr(arr2, size2); + + return 0; +} diff --git a/day6/test.cpp b/day6/test.cpp new file mode 100644 index 0000000..eab75b7 --- /dev/null +++ b/day6/test.cpp @@ -0,0 +1,37 @@ +// 多态本质: +// 父类引用或指针指向子类对象,通过父类指针或引用来(操作子类对象)调用子类中重写的成员函数 +#include +#include +#include + +using namespace std; + +class Animal +{ +public: + virtual void speak() + { + cout << "动物在唱歌..." << endl; + } +}; + +class Dog : public Animal +{ +public: + void speak() + { + cout << "狗在唱歌..." << endl; + } +}; + +void DoBusiness(Animal &animal) +{ + animal.speak(); +} + +int main() +{ + Dog dog; + DoBusiness(dog); + return 0; +} diff --git a/day7/homework/h7.cpp b/day7/homework/h7.cpp index 31fb929..36946ed 100644 --- a/day7/homework/h7.cpp +++ b/day7/homework/h7.cpp @@ -98,7 +98,7 @@ int main() else throw 1; } - catch (int &e) + catch (...) { cout << "dynamic_cast 将 Animal 转换为 Dog 失败" << endl; } @@ -107,12 +107,9 @@ int main() try { Animal *ap3 = dynamic_cast(cp2); // 将其转换为 Animal 类型的指针 - if (ap3) - cout << "dynamic_cast 将 Cat 转换为 Animal 成功" << endl; - else - throw 1; + cout << "dynamic_cast 将 Cat 转换为 Animal 成功" << endl; } - catch (int &e) + catch (...) { cout << "dynamic_cast 将 Cat 转换为 Animal 失败" << endl; } @@ -121,12 +118,9 @@ int main() try { Animal *ap4 = dynamic_cast(dp2); // 将其转换为 Animal 类型的指针 - if (ap4) - cout << "dynamic_cast 将 Dog 转换为 Animal 成功" << endl; - else - throw 1; + cout << "dynamic_cast 将 Dog 转换为 Animal 成功" << endl; } - catch (int &e) + catch (...) { cout << "dynamic_cast 将 Dog 转换为 Animal 失败" << endl; } diff --git a/day9/homework/h1.cpp b/day9/homework/h1.cpp new file mode 100644 index 0000000..537b760 --- /dev/null +++ b/day9/homework/h1.cpp @@ -0,0 +1,15 @@ +// 【场景】字符串反转 +// 编写一个函数 reverseString,接受一个字符串作为参数,并返回该字符串的反转版本。 +#include + +using namespace std; + +string reverseString(string &other) +{ +} + +int main() +{ + cout << "反转后的字符串 hello 为: " << reverseString("hello") << endl; + return 0; +} diff --git a/day9/homework/h2.cpp b/day9/homework/h2.cpp new file mode 100644 index 0000000..0b53269 --- /dev/null +++ b/day9/homework/h2.cpp @@ -0,0 +1,28 @@ +// 【场景】向量vector求和 +// 编写一个函数 sumVector,接受一个整数向量作为参数,并返回向量中所有元素的和。 + +#include +#include + +using namespace std; + +int sumVector(vector &vec) +{ + int sum = 0; + vector::iterator it = vec.begin(); + while (it != vec.end()) + { + sum += *it; + it++; + } + return sum; +} + +int main() +{ + vector v; + for (int i = 0; i < 10; i++) + v.push_back(i); + cout << "向量中所有元素的和为: " << sumVector(v) << endl; + return 0; +} \ No newline at end of file diff --git a/day9/homework/h3.cpp b/day9/homework/h3.cpp new file mode 100644 index 0000000..a7af34a --- /dev/null +++ b/day9/homework/h3.cpp @@ -0,0 +1,34 @@ +// 【场景】双端队列操作 +// 编写一个程序,演示双端队列(deque)的以下操作: 1)在队列的前面插入一个元素。 2)在队列的后面插入一个元素。 3)从队列的前面删除一个元素。 4)从队列的后面删除一个元素。 +#include +#include + +using namespace std; + +template +void print(deque &dq) +{ + // cout << "******************" << endl; + typename deque::iterator it = dq.begin(); + for (; it != dq.end(); it++) + { + cout << *it << endl; + } + cout << "------------------" << endl; +} + +int main() +{ + deque dq; + dq.push_front("push_front"); + dq.push_back("push_back"); + cout << "删除前: " << endl; + print(dq); + + dq.pop_front(); + dq.pop_back(); + cout << "删除后: " << endl; + print(dq); + + return 0; +} \ No newline at end of file diff --git a/day9/homework/h4.cpp b/day9/homework/h4.cpp new file mode 100644 index 0000000..7c4006f --- /dev/null +++ b/day9/homework/h4.cpp @@ -0,0 +1,43 @@ +// 【场景】栈操作 +// 编写一个程序,演示栈(stack)的以下操作: 1)将一个元素压入栈顶。 2)从栈顶弹出一个元素。 3)获取栈顶元素的值。 +#include +#include + +using namespace std; + +template +void print(stack &s) +{ + cout << "当前栈中元素(按出栈顺序)打印如下: " << endl; + // 先将栈转存到另一个临时栈中,临时栈的元素顺序和原栈相反 + // 临时栈用于打印,而不改变原栈的元素顺序 + stack tmp = s; // 拷贝原来的栈,避免改变原栈 + while (!tmp.empty()) + { + cout << tmp.top() << " "; + tmp.pop(); + } + cout << endl; + cout << "------------------" << endl; +} + +int main() +{ + stack stk; + stk.push(1); + stk.push(2); + stk.push(3); + stk.push(4); + stk.push(5); + + print(stk); + + cout << "从栈顶弹出一个元素: " << stk.top() << endl; + stk.pop(); + print(stk); + + cout << "获取栈顶元素的值: " << endl; + cout << stk.top() << endl; + + return 0; +} \ No newline at end of file diff --git a/day9/homework/h5.cpp b/day9/homework/h5.cpp new file mode 100644 index 0000000..eaff397 --- /dev/null +++ b/day9/homework/h5.cpp @@ -0,0 +1,21 @@ +// 【场景】字符串拼接 +// 编写一个函数 concatenateStrings,接受两个字符串作为参数,并返回它们的拼接结果。 +#include +#include + +using namespace std; + +string concatenateStrings(const string &str1, const string &str2) +{ + return str1 + str2; +} + +int main() +{ + string s1 = "hello"; + string s2 = "world"; + s1 = concatenateStrings(s1, " "); // 先拼接一个空格 + s1 = concatenateStrings(s1, s2); // 再拼接 s2 + cout << s1 << endl; + return 0; +} \ No newline at end of file diff --git a/day9/homework/h6.cpp b/day9/homework/h6.cpp new file mode 100644 index 0000000..05ec344 --- /dev/null +++ b/day9/homework/h6.cpp @@ -0,0 +1,45 @@ +// 【场景】向量vector查找 +// 编写一个函数 findElement,接受一个整数向量和一个目标值作为参数,并返回目标值在向量中的索引。 +// 如果目标值不存在于向量中,则返回 -1。 +#include +#include +#include + +using namespace std; + +int findElement(vector &v, const int &item) +{ + int index = 0; + vector::iterator it = v.begin(); + while (it != v.end()) + { + if (*it == item) // 如果找到了 + return index; // 返回索引 + index++; // 索引加一 + it++; // 迭代器指向下一个元素 + } + return -1; +} + +string print(int item) +{ + if (item == -1) + return "目标不存在"; + else + { + // to_string() 函数可以将整数转换为字符串 + // 需要 #include 头文件 + // 需要 c++11 标准,编译时加上 -std=c++11 + string s = to_string(item); + return s; + } +} + +int main() +{ + int arr[] = {1, 2, 3, 4, 5, 4, 6, 7, 8, 9, 10}; // 定义数组 + vector v1(arr, arr + sizeof(arr) / sizeof(arr[0])); // 将数组转换为向量 + cout << "5 在目标值向量中的索引为: " << print(findElement(v1, 5)) << endl; // 4 + cout << "11 在目标值向量中的索引为: " << print(findElement(v1, 11)) << endl; // -1 + return 0; +} diff --git a/day9/homework/h7.cpp b/day9/homework/h7.cpp new file mode 100644 index 0000000..67b72fe --- /dev/null +++ b/day9/homework/h7.cpp @@ -0,0 +1,3 @@ +// 【场景】双端队列排序 +// 编写一个程序,演示如何使用双端队列对一组整数进行排序。 +// 【提示】应用插入排序算法: 从第2个开始,确认当前位置数在前面有序(从小到大或从大到小)队列中的位置。 diff --git a/day9/homework/h8.cpp b/day9/homework/h8.cpp new file mode 100644 index 0000000..6165bdd --- /dev/null +++ b/day9/homework/h8.cpp @@ -0,0 +1,62 @@ +// 【场景】栈应用 +// 编写一个程序,判断给定的字符串是否是有效的括号序列。例如,对于字符串 "{[()]}",应返回 true;对于字符串 "{[(])}",应返回 false。 +// 【提示】华为OD的机试题 +#include +#include +#include + +using namespace std; + +bool judge(const string &str) +{ + stack stk; + int max_depth = 0; + + for (char c : str) // 增强型 for 循环,用于遍历字符串 + { + if (c == '(' || c == '[' || c == '{') + { + stk.push(c); // 当左括号出现时,入栈 + } + else if (c == ')' || c == ']' || c == '}') // 当碰到右括号时,开始匹配 + { + if (stk.empty()) // 如果栈已经为空,说明没有左括号与之匹配 + { + return false; // 返回无法匹配 + } + + char top = stk.top(); // 拿出栈顶元素 + + if (max_depth < stk.size()) + max_depth = stk.size(); + + stk.pop(); // 弹出栈顶元素 + + // 判断本次取出的字符与栈顶元素是否匹配,即左右括号是否匹配,不匹配则返回无效,匹配则继续进行下一轮遍历循环 + if ((c == ')' && top != '(') || (c == ']' && top != '[') || (c == '}' && top != '{')) + { + return false; // 括号不匹配 + } + } + } + + cout << "括号栈的最大深度为: " << max_depth << endl; + return stk.empty(); // 栈为空表示括号完全匹配 = 有效 = true = 1,反之,如果栈非空,说明还有未匹配的左括号,返回无效 = false = 0 +} + +string print(bool flag) +{ + if (flag) // flag 为 true = 1 + return "有效"; + else + return "无效"; +} + +int main() +{ + // string str1 = "{[(])}"; + // string str1 = "{(])}"; + string str1 = "{[(s[s])s]}[][[[[()]]]]"; + cout << "括号序列 " << str1 << " 是否有效: " << print(judge(str1)) << endl; // 1 + return 0; +} \ No newline at end of file