首页 > 技术文章 > C++常用操作

summer-L 2022-03-22 16:54 原文

数组定义

点击查看代码
//一维数组定义
int num[10];
vector<int> num(10, 0)//定义一个包含十个int的数组,初始值为0
//二维数组定义
int array[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
vector<vector<int> > array(rows,vector<int>(columns, 0));//定义二维数组,值初始化为0

栈队列字典堆等

stack

点击查看代码
#include<stack>

stack<int> sta;//定义一个栈sta
int x;

sta.empty(); //堆栈为空则返回真
sta.pop(); //移除栈顶元素
sta.push(x); //在栈顶增加元素
s.size(); //返回栈中元素数目
s.top(); //返回栈顶元素

queue

队列

点击查看代码
#include<queue>
queue<int> que; //定义一个queue的变量
int x;
que.empty;		//查看是否为空  是的话返回1,不是返回0
que.push(x);       //从已有元素后面增加元素
que.size();        //输出现有元素的个数
que.front();     //显示队列第一个元素
que.back();    //显示队列最后一个元素
que.pop();    //删除队列第一个元素

set && unordered_set

集合set就是集合,STL的set用二叉树实现,集合中的每个元素只出现一次(参照数学中集合的互斥性),并且是排好序的(默认按键值升序排列)

set具有迭代器set<int>::iterator i 定义一个迭代器,名为i 可以把迭代器理解为C语言的指针

C++ STL中set与unordered_set区别和map与unordered_map区别类似:

  • set基于红黑树实现,红黑树具有自动排序功能,因此set内部所有数据任何时候都是有序的
  • unordered_set基于哈希表实现,数据插入和查找的时间复杂度很低,几乎是常数时间,代价是消耗更多的内存,没有自动排序功能
点击查看代码
#include<set>
set<int> q;     //以int型为例 默认按键值升序
set<int,greater<int>> p;  //降序排列
int x;
q.insert(x);	//将x插入q中
q.erase(x);		//删除q中的x元素,返回0或1,0表示set中不存在x
q.clear();		//清空q
q.empty();		//判断q是否为空,若是返回1,否则返回0
q.size();		//返回q中元素的个数
q.find(x);		//在q中查找x,返回x的迭代器,若x不存在,则返回指向q尾部的迭代器即 q.end()
q.lower_bound(x); //返回一个迭代器,指向第一个键值不小于x的元素
q.upper_bound(x); //返回一个迭代器,指向第一个键值大于x的元素

q.rend();		  //返回第一个元素的的前一个元素迭代器
q.begin();		  //返回指向q中第一个元素的迭代器

q.end();		 //返回指向q最后一个元素下一个位置的迭代器
q.rbegin();		 //返回最后一个元素

map && unordered_map

  • map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
  • unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
  • map和unordered_map的使用unordered_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。其底层实现是完全不同的,上方已经解释了,但是就外部使用来说却是一致的。
点击查看代码
#include <iostream>
#include <unordered_map>
#include <map>
#include <string>
using namespace std;
int main()
{
	//注意:C++11才开始支持括号初始化
    unordered_map<int, string> myMap={{ 5, "张大" },{ 6, "李五" }};//使用{}赋值
    myMap[2] = "李四";  //使用[ ]进行单个插入,若已存在键值2,则赋值修改,若无则插入。
    myMap.insert(pair<int, string>(3, "陈二"));//使用insert和pair插入

	//遍历输出+迭代器的使用
    auto iter = myMap.begin();//auto自动识别为迭代器类型unordered_map<int,string>::iterator
    while (iter!= myMap.end())
    {
        cout << iter->first << "," << iter->second << endl;
        ++iter;
    }

	//查找元素并输出+迭代器的使用
    auto iterator = myMap.find(2);//find()返回一个指向2的迭代器
    if (iterator != myMap.end())
	    cout << endl<< iterator->first << "," << iterator->second << endl;
    system("pause");
    return 0;
}


优先队列

优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的

定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆

点击查看代码
#include<iostream>
#include<queue>

using namespace std;

int main(){

    //升序队列,小顶堆
    priority_queue<int, vector<int>, greater<int>> up_q;

    //降序队列,大顶堆
    priority_queue<int, vector<int>, less<int>> down_q;
    //对于基础类型,默认是大顶堆
    priority_queue<int> default_q;
    //等同于priority_queue<int, vector<int>, less<int>> down_q

    //greater 和 less 是std实现的两个仿函数

    //和队列的操作基本相同
    up_q.top();       //访问队头元素
    up_q.empty();     //队列是否为空
    up_q.size();      //返回队列内元素个数
    up_q.push();      //插入元素到队尾 (并排序)
    up_q.emplace();   //原地构造一个元素并插入队列
    up_q.pop();       //弹出队头元素
    up_q.swap(value, value);      //交换内容
}

自定义数据类型

点击查看代码
#include<iostream>
#include<queue>

using namespace std;

    struct student{
        int score;
        string name;
        int student_number;

        //重载<运算符,用于优先级比较,以成绩排名
        bool operator<(const student& stu) const {
            return this->score < stu.score;//大顶堆
        }

        //构造函数
        student(int sco, string na, int sn):score(sco), name(na), student_number(sn){}
    };

    //自定义比较函数
    struct student_compare_score_greater{
        bool operator() (const student& stu_a, const student& stu_b){
            return stu_a.score > stu_b.score;//小顶堆
        }
    };

int main(){

    student s1(89, "wang", 1001001);
	student s2(76, "Li", 1001721);
	student s3(100, "Zhao", 1001321);

	priority_queue<student> p5;
	p5.push(s1);
	p5.push(s2);
	p5.push(s3);

	cout << "p5 list 大顶堆(student): " << endl << endl;
	while (p5.size())
	{
		cout << p5.top().name << " " << p5.top().score << " " << p5.top().student_number << endl;;
		p5.pop();
	}
	cout << endl;

	// 改为成绩由低到高
	priority_queue<student, vector<student>, student_compare_score_greater> p6;
	p6.push(s1);
	p6.push(s2);
	p6.push(s3);

	cout << "p6 list 小顶堆(student): " << endl;
	while (p6.size())
	{
		cout << p6.top().name << "  " << p6.top().score << "  " << p6.top().student_number << endl;;
		p6.pop();
	}
	cout << endl;
}

运行结果:
image

sort

字符串string

c_str()

字符串分割

strtok()

原型:char* strtok(char *str, const char *delim);
功能:分解字符串为一段字符串
参数:str为要分解的字符串,delim为分割字符串.str必须为一个char型数组,不能定义成指针形式
返回值:从str开头的一个被分割的串,当没有被分割的串则返回NULL
其他:strtok函数线程不安全,可以使用strtok_r替代

对于string str类型的字符串,要先进行转换

string str;
int len = str.size();
char char_ptr[len + 1];
//或者 char* char_ptr = new char[len + 1];
strcpy(char_ptr, str);

strtok使用实例:

点击查看代码
#include<iostream>
#include<cstring>
using namespace std;
int main(){
    //char str = "This is a sentence with 7 tokens";
    string str = "This is a sentence with 7 tokens";

    char *char_ptr = new char[str.size() + 1];
    strcpy(char_ptr, str.c_str());

    char *tokenPtr;
    tokenPtr = strtok(char_ptr, " "); //char_ptr必须是一个char数组,不能定义成指针形式
    while (tokenPtr != NULL)
    {
        cout << tokenPtr << "\n";
        tokenPtr = strtok(NULL, " ");
    }
    //cout << "After strtok, sentence = \n" << tokenPtr << endl;
    return 0;
}

strtok_r()

二叉树节点定义

推荐阅读