再也不用c刷題了!!——c++刷題必備

致讀者: 部落客是一名數據科學與大數據專業大二的學生,真正的一個互聯網萌新,寫部落格一方面是為了記錄自己的學習歷程,一方面是希望能夠幫助到很多和自己一樣處於困惑的讀者。由於水平有限,部落格中難免會有一些錯誤,有紕漏之處懇請各位大佬不吝賜教!之後會寫大數據專業的文章哦。儘管當前水平可能不及各位大佬,但我會盡我自己所能,做到最好☺。——天地有正氣,雜然賦流形。下則為河嶽,上則為日星。

第一發布 csdn 部落格鏈接

還記得大一上學期含淚用c刷題,那感覺簡直爽的不行,後來結識c++發現我錯過了一個億,所以分享一下用c++刷題所用到的基礎知識。

結識演算法和OJ就是在大學階段,當時老師提到OJ,我也是一臉懵,啥是OJ?

後來慢慢開始入門,從校賽第三名,到後來的ACM培訓,經歷了很多,也學習了很多東西。刷題大約有1000多道了,以後刷題應該暫時不會了,大二就要學習我們大數據專業知識啦。

從c->c++

C語言作為初學者的一門語言,為什麼從大一就要開始學吶?

  • 相較於其它程式語言(python),C語言是一個比較低級的語言,這樣低級的語言,往往能夠讓我們更加了解電腦。
  • 因為比較底層,C語言的執行效率比較高,同樣的程式執行效果,肯定C語言執行速度快。
  • C語言作為編程界歷史最悠久的語言之一,而且至今仍然流行。
  • 如果學習過C語言,就能發現學習後面再學習任何高級程式語言都變得輕而易舉。

同時,正因為C語言什麼都沒有,排序,字元串,棧,隊列等等,如果刷題的時候,都要自己去實現的話,未免有點浪費時間(前提是你已經很熟悉了,比較基礎才是重中之重,知其然,更要知其所以然),所以使用c++刷題,能夠提升效率一大截。

  • c++能夠完全支援c,打開一個c++文件,用c語言的知識寫,完全能夠運行(關鍵字不衝突情況下)。
  • c++STL模板庫,刷題必備啊!!!棧和隊列,集合,向量。用過的都說好。
  • 字元串處理更加方便,字元數組的方式,每次都不太方便,還有注意\0 結束符的問題。

學會了這些,走向人生……

C++頭文件

如果就是為了刷題,那其實就很簡單了。

C語言我們知道頭文件是以 #include<stdio.h> 導入頭文件,而C++則是用 #include<iostream> 導入頭文件。

如果我們想調用C語言頭文件怎麼辦,那就是就是去掉 .h 然後前面加上 c

例如,在c++裡面引入c語言輸入輸出的頭文件。

#include<cstdio> 這樣就能夠成功導入了。

#include <cstdio> // 相當於C語⾔⾥⾯的#include <stdio.h>
#include <cstdlib> // 相當於C語⾔⾥⾯的#include <stdib.h>
#include <cctype> // 相當於C語⾔⾥⾯的#include <ctype.h>
#include <cstring> // 相當於C語⾔⾥⾯的#include <string.h>

命名空間

刷題時候都是為了方便,所以才使用 using namespace std; 這樣想使用什麼直接寫就行了。

如果不這樣引入,你寫的演算法可能是這樣的 std:: 佔據注意地方,而且會影響比賽,刷題速度。

std::cout << "hello world" << std::endl;

引入之後:

cout << "hello world" << endl;

看著美觀多了。

輸入輸出

標準輸入流(cin

預定義的對象 ciniostream 類的一個實例。cin 對象附屬到標準輸入設備,通常是鍵盤。cin 是與流提取運算符 >> 結合使用的

#include <iostream>
using namespace std;
int main( )
{
    int n;
    cin>>n;
}

標準輸出流(cout

預定義的對象 coutiostream 類的一個實例。cout 對象”連接”到標準輸出設備,通常是顯示器。cout 是與流插入運算符 << 結合使用的,

#include <iostream>
using namespace std;
int main( )
{
   char str[] = "Hello C++";
   cout << "Value of str is : " << str << endl;
}

流插入運算符 << 在一個語句中可以多次使用,如上面實例中所示,endl 用於在行末添加一個換行符。

cincout ⽐較⽅便,不⽤像C語⾔⾥的scanfprintf那樣寫得那樣繁瑣,cin >> n;scanf("%d", &n);⼀樣(⽽且⽤cin再也不⽤擔⼼像scanf⼀樣忘記寫取地址符&了)
同樣,cout << n;printf("%d", n);此時cout是向左的兩個箭頭,注意和cin區分開來。⽽且不管ndouble還是int或者是char類型,只⽤寫cin >> n;cout << n;這樣簡單的語句就好,不⽤像C語⾔中需要根據n的類型對應地寫%lf、%d、%c這樣麻煩。

字元串

c++用到最多的就是字元串了,跟之前的字元數組類似,但是字元數組,操作起來相當麻煩,顯然使用c++的字元串會方便的多。

定義一個字元串,導入庫 <string>

string s = "hello world";//賦值
cout<<s<<endl;
s = "world";
cout<<s<<endl;

輸出為

hello world
world

字元串拼接(可以直接相加)

string s1 = "hello";
string s2 = " world";
string s = s1 + s2;//拼接直接使用 + 號

讀入字元串

string s; // 定義⼀個空字元串s
cin>>s;//不包括空格
getline(cin, s); // 讀取⼀整⾏的字元串,包括空格

字元串長度(兩種方法等價)

int len = s.size();//字元串s的⻓度
int len = s.length();//字元串s的⻓度

查找字元串t是否是s的子串

如果t是s的子串則返回首次匹配的位置,否則返回 string::npos 或 -1

s.find(t);

beginend 方法

begin()函數返回一個迭代器,指向字元串的第一個元素.返回值是字元串的首地址,取值為*

end()函數返回一個迭代器,指向字元串的最後一個元素.返回值是字元串的首地址,取值為*

string s1 = "hello";
string s2 = " world";
s1.append(s2);
cout<<*s1.begin()<<endl;
cout<<*s1.end()<<endl;

反轉字元串

string s = "hello world";
reverse(s.begin(), s.end());
cout<<s<<endl;
//結果
dlrow olleh

截取某個字元串中的⼦串 substr 這個函數在處理字元串的題目很常用,當然,用這個方法很多時候會 TLE

string s = "hello world";
string s1 = s.substr(6);//下標6開始到結束
string s2 = s.substr(011);//下標0開始,截取11個字元
cout<<s1<<endl;
cout<<s2<<endl;
//結果
world
hello world

使用標準庫的棧和隊列時,先包含相關的頭文件

stack<int> s;
s.empty()               如果棧為空返回true,否則返回false
s.size()                返回棧中元素的個數
s.pop()                 刪除棧頂元素但不返回其值
s.top()                 返回棧頂的元素,但不刪除該元素
s.push()                在棧頂壓入新元素
#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(); // 移除棧頂元素
    return 0;
}

隊列

q.push(x):將x元素接到隊列的末端;
q.pop() 彈出隊列的第一個元素,並不會返回元素的值;
q.front()訪問隊首元
q.back()訪問隊尾元素
q.size()訪問隊中的元素個數

優先隊列

優先隊列電腦科學中的一類抽象數據類型。優先隊列中的每個元素都有各自的優先順序,優先順序最高的元素最先得到服務;優先順序相同的元素按照其在優先隊列中的順序得到服務。優先隊列往往用來實現。

詳情請看我另一個部落格

priority_queue<node> q;
q.empty()          如果隊列為空,則返回true,否則返回false 
q.size()           返回隊列中元素的個數
q.pop()            刪除隊首元素,但不返回其值
q.top()            返回具有最高優先順序的元素值,但不刪除該元素
q.push()       在基於優先順序的適當位置插入新元素

集合

set是集合,⼀個set⾥⾯的各元素是各不相同的,⽽且set會按照元素進⾏從⼩到⼤排序以下是set的常⽤⽤法:

#include <iostream>
#include <set>
using namespace std;
int main() {
    set<int> s;
    s.insert(2);//向集合添加元素
    s.insert(3);//向集合添加元素
    cout << *(s.begin()) << endl//輸出第一個元素
    for (int i = 0; i < 10; i++) {//插入0 - 9
        s.insert(i);
    }
    for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";//集合的遍歷,it是一個迭代的指針
    }
    cout << endl << (s.find(2) != s.end()) << endl;//查找,元素
    s.erase(3);//刪除元素
    cout << (s.find(3) != s.end()) << endl;
    return 0;
}

map/字典/映射

map是鍵值對,⽐如⼀個⼈身份證對應⼀個人的資訊,就可以定義⼀個字元串類型的身份證字元串為「鍵」,個人資訊為「值」,如map<string, int=”” style=”font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;”> m;map會⾃動將所有的鍵值對按照鍵從⼩到⼤排序。

類似於python的字典,鍵值唯一。

map使⽤時的頭⽂件#include

以下是map中常⽤的⽅法:

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    map<stringstring> m;
    m["hello"] = "world"// 存儲鍵為 "hello" 值為 "world"的鍵值對
    cout << m["hello"] << endl// 訪問map中key為"hello"的value,
    cout << m["world"] << endl;// 如果key不存在,則返回0或空
    m["world"] = "test"// 將"world"鍵對應的值修改為3
    m["key"] = "value"// 設置鍵為 "key" 值為"value" 的鍵值對
    //迭代器遍歷,輸出map中所有的元素,鍵it->first獲取,值it->second獲取
    for (map<stringstring>::iterator it = m.begin(); it != m.end(); it++) {
        cout << it->first << " " << it->second << endl;
    }

    cout << m.begin()->first << " " << m.begin()->second << endl;
    // 訪問map的第一個元素,輸出它的鍵和值

    cout << m.rbegin()->first << " " << m.rbegin()->second << endl;
    // 訪問map的最後一個元素,輸出它的鍵和值

    cout << m.size() << endl;
    // 輸出map的元素個數
    return 0;
}

向量

在c++中,vector是一個十分有用的*容器*

作用:它能夠像容器一樣存放各種類型的對象,簡單地說,vector是一個能夠存放任意類型的動態數組,能夠增加和壓縮數據。

新建一個向量存儲int類型

vector<int>test; // 定義的時候不指定vector的⼤⼩
vector<int>test2(6); // 定義的時候指定vector的⼤⼩,默認test2⾥⾯元素都是0
vector<int>test3(63); // 定義的時候指定vector的⼤⼩,默認test3⾥⾯元素都是3

尾部添加兩個元素,0的位置存儲5, 1 的位置存儲8

test.push_back(5);
test.push_back(8);

插入元素 insert

test.insert(test.begin()+i,value);//在第i+1個元素前面插入value;

刪除元素

test.erase(test.begin() + 5);//刪除第6個元素

清空向量

test.clear();//clear

獲取向量的大小

test.size();

獲取起始地址或結束地址

test.begin();//起始地址
test.end();//結束地址

遍歷向量

for (vector<int>test::iterator it = m.begin(); it != m.end(); it++) {
        cout << *it << endl;
    }

反轉元素,逆序

reverse(test.begin(),test.end());//反轉

使用sort排序,可以自定義排序規則

sort(test.begin(),test.end());