从C语言的使用转换到C++(下篇)——刷题、竞赛篇

简介: 我们上篇文章讲述了C++中的一些基础语法和常用函数(从C语言的使用转换到C++(上篇)——刷题、竞赛篇),我们本篇文章讲述C++STL的使用。

 我们上篇文章讲述了C++中的一些基础语法和常用函数(从C语言的使用转换到C++(上篇)——刷题、竞赛篇),我们本篇文章讲述C++STL的使用。


一、C++STL的简介


STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库(C++ Standard Library)中,是ANSI/ISO C++标准中最新的也是极具革命性的一部分。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。

 STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但这种分离确实使得STL变得非常通用。例如,由于STL的sort()函数是完全通用的,你可以用它来操作几乎任何数据集合,包括链表,容器和数组;

 STL另一个重要特性是它不是面向对象的。为了具有足够通用性,STL主要依赖于模板而不是封装,继承和虚函数(多态性)——OOP的三个要素。你在STL中找不到任何明显的类继承关系。这好像是一种倒退,但这正好是使得STL的组件具有广泛通用性的底层特征。另外,由于STL是基于模板,内联函数的使用使得生成的代码短小高效。


二、STL的使用详解

2、1 STL之动态数组vector的使用


 在c语言中我们学习了数组的使用,如:int arr[10]。我们在使用的过程中也发现其缺点,我们不能随意的改变数组的长度。在C++中我们可以使用动态数组vector来完全代替c语言中的数组。动态数组vector能够在运行阶段设置数组的长度、在末尾和中间插入数据、长度可以任意改变。相对c语言中的数组来说,动态数组vector很方便、很实用。


 动态数组vector在头文件vector中,也在命名空间std里面。所以使用动态数组vector时,我们要引入#include<vector>和using namespace std;


 vector、stack、queue、map、set 这些在C++中都叫做容器,这些容器的大小都可以用.size()获取到。我们快来看一下具体的使用方法:


#include<iostream>
#include<vector>
using namespace std;
int main()
{
  vector<int> v1;  //定义一个的整形动态数组vector v1,定义的时候并没有分配大小
  cout << v1.size() << endl;  //输出动态数组vector v1的大小
  return 0;
}


 在上面的代码中,我们简单的定义了动态数组vector,并且计算了其大小。注意:动态数组vector在C++中叫做容器,我们可以用.size()来计算出其大小。

 上述我们在定义的时候并没有分配大小,所以用.size()来计算出其大小时,结果为0



c512be4577714cbea651ea2ef084c012.png


我们接着看动态数组vector的其他用法:

#include<iostream>
#include<vector>
using namespace std;
int main()
{
  //vector<int> v1;  //定义一个的整形动态数组vector v1,定义的时候并没有分配大小
  //cout << v1.size() << endl;  //输出动态数组vector v1的大小
  vector<int> v(10);  //直接定义长度为10的int数组,默认每个元素的值为0
  vector<int> v1;
  v1.resize(8);  //先定义了一个vector v1的动态数组,然后再用resize设置长度为8
  vector<int> v2(100, 9);  //把长度为100的数组的所有值都初始化为9
  v[1] = 2;  //可以直接用下标来访问,也可用迭代器访问
  return 0;
}



 不管是vector 、 stack 、 queue 、 map还是set 都有很多好用的方法,这些方法都可以在www.cplusplus.com官方网站中直接查询官方文档,上面有方法的讲解和代码示例。比如进入官网搜索 vector ,就会出现 vector拥有的所有方法,点进去一个方法就能看到这个方法的详细解释和代码示例~当然我们平时写算法用不到那么多方法啦,只有几个是常用的。以下是一些常用的 vector方法:

#include<iostream>
#include<vector>
using namespace std;
int main()
{
  vector<int> a; //定义时不指定vector的大小
  cout << a.size() << endl; // a的大小为0
  for (int i = 0; i < 10; i++) 
  {
    a.push_back(i); // 向a中末尾插入0到9
  }
  cout << a.size() << endl; // a的大小为10;
  vector<int> b(15);  //定义时指定b的大小为15,各个元素默认值为0
  cout << b.size() << endl;  //b的大小为15
  for (int i = 0; i < b.size(); i++) 
  {
    b[i] = 15;  //给b中的每个元素赋值
  }
  for (int i = 0; i < b.size(); i++) 
  {
    cout << b[i] << " ";  //输出b中的元素
  }
  cout << endl;
  vector<int> c(20, 2);  //定义时指定c的大小为20,各个元素默认值为2
  for (int i = 0; i < c.size(); i++) 
  {
    cout << c[i] << " ";  //输出c中的元素
  }
  cout << endl;
  for (auto it = c.begin(); it != c.end(); it++)   //迭代器访问
  {
    cout << *it << " ";
  }
  return 0;
}


容器vector , set , map这些遍历的时候都是使用迭代器访问的,(c.begin()是一个指针,指向容器的第一个元素,c.end()指向容器的最后一个元素的后一个位置)。


 上述代码的运行结果如下图:

2、2 STL之集合set的使用


 set是集合,一个 set里面的各元素是各不相同的,而且 set 会按照元素进行从小到大排序。以下是set的常用用法:

#include <iostream>
#include <set>
using namespace std;
int main()
{
  set<int> s;  //定义一个集合
  s.insert(1);  //向集合里面插入一个1
  cout << *(s.begin()) << endl; // ᬌ输出集合中的第一个元素
  for (int i = 0; i < 10; i++) 
  {
    s.insert(i); // 向集合中插入十个元素
  }
  for (auto it = s.begin(); it != s.end(); it++) 
  {
      cout << *it << " ";
  }
  cout << endl << (s.find(2) != s.end()) << endl; //查找集合s中的值,如果结果等于s.end()表示未找到(因为s.end()表示s的最后一个元素的下一个元素所在的位置)
    cout << (s.find(10) != s.end()) << endl; // s.find(10) != s.end()
  s.erase(1); // s.erase( 1);//删除集合s中的1这个元素
  cout << (s.find(1) != s.end()) << endl; //这时候元素1就应该找不到了
  return 0;
}


上述代码的运行结果如下图:

2、3 STL之映射map的使用


 map是键值对,比如一个人名对应一个学号,就可以定义一个字符串string类型的人名为“键”,学号int类型为“值”,如map<string, int>m;当然键、值也可以是其它变量类型。map 会自动将所有的键值对按照键从小到大排序,map使用时的头文件 #include <map>以下是 map中常用的方法:

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
  map<string, int> m;  //定义一个空的map m,键是string类型的,值是int类型的
  m["hello"] = 2;   //将key为"hello", value为2的键值对(key-value)存入map中
  cout << m["hello"] << endl;  //访问map中key为"hello"的value,如果key不存在,则返回0
  cout << m["world"] << endl;  //返回0
  m["world"] = 3;  //将"world"键对应的值修改为3
  m[","] = 1;  //设立一组键值对,键为",”值为1
  for (auto it = m.begin(); it != m.end(); it++) 
  {
    //用迭代器遍历,输出map中所有的元素,键用it->first获取,值用it->second获取
    cout << it->first << " " << it->second << endl;  
  }
  //访问map的第一个元素,输出它的键和值
  cout << m.begin()->first << " " << m.begin()->second << endl;
  //访问map的最后一个元素,输出它的键和值
  cout << m.rbegin()->first << " " << m.rbegin()->second << endl;
  //输出map的元素个数
  cout << m.size() << endl;
  return 0;
}

 上述代码的运行结果如下图:

2、4 STL之栈stack的使用


 栈stack在头文件 #include <stack>中,是数据结构里面的栈。我们知道栈是先进后出的一个原则。以下是常用用法:  

#include <iostream>
#include <stack>
using namespace std;
int main() 
{
  stack<int> s;  //定义一个空栈s
  for (int i = 0; i < 6; i++) 
  {
    s.push(i);  //将元素i压入栈s中
  }
  cout << s.top() << endl;  //访问s的栈顶元素
  cout << s.size() << endl;  //输出s的元素个数
  s.pop(); //移除栈顶元素
  cout << s.size() << endl;  //输出s的元素个数
  cout << s.top() << endl;  //访问s的栈顶元素
  return 0;
}



 上面代码的运行结果如下图:

2、5 STL之队列queue的使用



队列queue 在头文件 #include<queue>中,是数据结构里面的队列。队列遵循先进先出的原则。以下是常用用法:

#include <iostream>
#include <queue>
using namespace std;
int main() 
{
  queue<int> q;  //定义一个空队列q
  for (int i = 0; i < 10; i++) 
  {
    q.push(i);  //将i的值依次压入队列q中
  }
  cout << q.front() << " " << q.back() << endl;  //访问队列的队首元素和队尾元素
  cout << q.size() << endl;  //输出队列的元素个数
  q.pop();  //移除队列的队首元素
  cout << q.front() << endl;
  cout << q.size() << endl;  //输出队列的元素个数
  return 0;
}



上述代码的运行结果如下图:

2、6 STL之unordered_map和unordered_set的使用


 unordered_map在头文件#include<unordered_map>中,unordered_set 在头文件#include<unordered_set>中。unordered_map和 map(或者unordered_set和 set )的区别是,map 会按照键值对的键 key进行排序(set里面会按照集合中的元素大小进行排序,从小到大顺序),而unordered_map(或者unordered_set)省去了这个排序的过程,如果偶尔刷题时候用map或者set 超时了,可以考虑用unordered_map(或者_unordered_set)缩短代码运行时间、提高代码效率。至于用法和map .set是一样的。


三、总结


 学到这里我们发现,用C++来刷题确实会方便很多。例如,STL中已有栈、队列等容器。而c语言却没有,有些题目做起来就麻烦了很多。


 STL的使用给我们带来了很大的便利,也是哦我们重点掌握的内容。学到这里基本上用C++写算法题没有问题。我们需要做的就是通过刷题,进而更加熟练的掌握。


 希望以上内容对你有所帮助,感谢阅读ovo~

相关文章
|
2月前
|
安全 编译器 C语言
C++入门1——从C语言到C++的过渡
C++入门1——从C语言到C++的过渡
65 2
|
10天前
|
算法 编译器 C语言
【C语言】C++ 和 C 的优缺点是什么?
C 和 C++ 是两种强大的编程语言,各有其优缺点。C 语言以其高效性、底层控制和简洁性广泛应用于系统编程和嵌入式系统。C++ 在 C 语言的基础上引入了面向对象编程、模板编程和丰富的标准库,使其适合开发大型、复杂的软件系统。 在选择使用 C 还是 C++ 时,开发者需要根据项目的需求、语言的特性以及团队的技术栈来做出决策。无论是 C 语言还是 C++,了解其优缺点和适用场景能够帮助开发者在实际开发中做出更明智的选择,从而更好地应对挑战,实现项目目标。
34 0
|
2月前
|
C语言 C++
C 语言的关键字 static 和 C++ 的关键字 static 有什么区别
在C语言中,`static`关键字主要用于变量声明,使得该变量的作用域被限制在其被声明的函数内部,且在整个程序运行期间保留其值。而在C++中,除了继承了C的特性外,`static`还可以用于类成员,使该成员被所有类实例共享,同时在类外进行初始化。这使得C++中的`static`具有更广泛的应用场景,不仅限于控制变量的作用域和生存期。
61 10
|
2月前
|
机器学习/深度学习 编译器 C语言
C语言刷题(中)(保姆式详解)
C语言刷题(中)(保姆式详解)
16 0
|
3月前
|
算法 机器人 C语言
ROS仿真支持C++和C语言
ROS仿真支持C++和C语言
86 1
|
2月前
|
C语言 C++
实现两个变量值的互换[C语言和C++的区别]
实现两个变量值的互换[C语言和C++的区别]
24 0
|
3月前
|
编译器 C语言 C++
从C语言到C++
本文档详细介绍了C++相较于C语言的一些改进和新特性,包括类型检查、逻辑类型 `bool`、枚举类型、可赋值的表达式等。同时,文档还讲解了C++中的标准输入输出流 `cin` 和 `cout` 的使用方法及格式化输出技巧。此外,还介绍了函数重载、运算符重载、默认参数等高级特性,并探讨了引用的概念及其应用,包括常引用和引用的本质分析。以下是简要概述: 本文档适合有一定C语言基础的学习者深入了解C++的新特性及其应用。
|
15天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
25 2
|
21天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
54 5
|
27天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
56 4