摘要:時間復雜度為,和分別是和的長度示例如下輸出輸出把從號位開始長度為的子串替換為上把的迭代器范圍的子串替換為示例如下
歡迎回到:遇見藍橋遇見你,不負代碼不負卿!
目錄
【前言】
這篇是上次文章的后續(xù)哦,鐵汁們可以先回顧一下上篇的內容。
藍橋杯算法競賽系列第0章——藍橋必考點及標準模板庫STL(上)(萬字博文,建議抱走)_安然無虞的博客-CSDN博客
上次有好幾位鐵汁建議我多換點圖片,表示看膩了,也有不少熱心小友私發(fā)給了我一些,但是由于格式大小的問題,能用的不多,不過在這里還是要特別感謝一下哈,抱拳啦。
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- scanf()
- printf()
- getchar()
- putchar()
- gets()
- puts()
- sscanf()
- sprintf()
標準輸入輸出頭文件,當然除了scanf() 和 printf() 很重要外,sscanf() 和 sprintf()也是非常重要的,對于這兩個庫函數(shù),老師從未講過,但是看題解時經(jīng)常出現(xiàn),它們是用來處理字符串的利器。待會再談它們,先講一下scanf() 的弊端,對于scanf() 函數(shù),不能讀入空格,遇到空格就結束了,所以處理起字符串就很不方便。所以這里還有兩個庫函數(shù)用來處理字符串:gets() 和 puts() , gets() 用來輸入一行字符串,識別"/n" 結束,遇到空格不會結束哦,puts() 用來輸出一行字符串,并且緊跟一個換行,對于putchar()和getchar() 用得不多,有興趣可自行了解哦。
sscanf() 與 sprintf() 是處理字符串問題的利器,我們很有必要學會它們(sscanf() 從單詞上可理解為 string + scanf , sprintf 則可理解為 string + printf, 均在stdio.h 頭文件下) 。先來回顧一下scanf() 和 printf(), 如果想要從屏幕上輸入int 型變量n 并將int 型變量 n 輸出到屏幕上,則可以寫成下面這樣:
scanf("%d", &n);printf("%d", n);
事實上,上面的寫法其實可以表示成下面的樣子,其中screen 表示屏幕:
scanf(screen, "%d", &n);printf(screen, "%d", n);
可以發(fā)現(xiàn),scanf() 的輸入其實是把screen 的內容以"%d" 的格式傳輸?shù)絥 中(即從左至右),而printf() 的輸出則是把n 以“%d” 的格式傳輸?shù)絪creen 上(即從右至左)
sscanf() 和 sprintf() 與上面的格式是相同的,只不過把screen 換成了字符數(shù)組(假設定義了一個char 數(shù)組 str[100]),如下所示:
sscanf(str, "%d", &n);sprintf(str, "%d", n);
上面的sscanf() 寫法的作用是把字符數(shù)組str 中的內容以"%d" 的格式寫到n 中(還是從左至右)
示例如下:
#includeint main(){ int n = 0; char str[100] = "123"; sscanf(str, "%d", &n); printf("%d/n", n);//輸出123 return 0;}
而sprintf() 寫法的作用是把n 以"%d" 的格式寫到str 字符數(shù)組中(還是從右至左)
示例如下:
#includeint main(){ int n = 233; char str[100]; sprintf(str, "%d", n); printf("%s/n", str);//輸出233 return 0;}
上面只是一些簡單的應用,事實上,可以像使用scanf() 和 printf() 那樣進行復雜的格式的輸入和輸出。例如下面的代碼使用sscanf() 將字符數(shù)組str 中的內容按"%d:%lf,%s"的格式寫到int 型變量n、double 型變量db、char型數(shù)組str2中
#includeint main(){ int n; double db; char str[100] = "2048:3.14,hello", str2[100]; sscanf(str, "%d:%lf,%s", &n, &db, str2); printf("n = %d, db = %lf, str2 = %s/n", n, db, str2); return 0;}
類似的,下面的代碼使用sprintf() 將int 型變量n 、double 型變量db、char 型數(shù)組str2 按"%d:%lf,%s" 的格式寫到字符數(shù)組str 中
#includeint main(){ int n = 12; double db = 3.1415; char str[100], str2[100] = "good"; sprintf(str, "%d:%.2lf,%s", n, db, str2); printf("str = %s/n", str); return 0;}
主要用于生成隨機數(shù)以及動態(tài)內存開辟,常用的庫函數(shù)有srand((unsigned int) time(NULL)),rand() 和動態(tài)內存開辟用的malloc(),用new會更簡單一些
上面生成隨機數(shù)的時候,常用time()函數(shù)用于生成時間戳,作為隨機數(shù)種子
- fabs()
- sqrt()
- pow()
- floor()
- ceil()
- round()
用數(shù)學函數(shù)可以節(jié)省大量的時間,所以一定要記住,對于很常用的其實也就是fabs()、sqrt()和pow()
該函數(shù)用于對double 型變量取絕對值。
該函數(shù)用于返回 r ^ p ,要求r 和 p 都是double類型的
該函數(shù)用于返回double型變量的算數(shù)平方根
在這里就只簡單介紹這三個最常用的。
- strlen()
- strcmp()
- strcpy()
- strcat()
strlen()函數(shù)可以得到字符數(shù)組中第一個/0之前的字符的個數(shù)
strcmp()函數(shù)返回兩個字符串大小的比較結果,比較原則是按字典序,所謂字典序就是字符串在字典中的順序,因此如果有兩個字符數(shù)組str 1 和 str 2, 且滿足str 1[0...k - 1] == str 2[0...k - 1]、str1[k] < str2[k], 那么就說str 1的字典序小于str2。例如"a" 的字典序小于"b"、"aaaa" 的字典序小于"aab"
strcmp()函數(shù)的返回值:
- 如果字符數(shù)組1 < 字符數(shù)組2,則返回一個負整數(shù)(不一定是-1,由編譯器決定)
- 如果字符數(shù)組1 == 字符數(shù)組2,則返回0
- 如果字符數(shù)組1 >?字符數(shù)組2,則返回一個正整數(shù)(不一定是1,由編譯器決定)
strcpy()函數(shù)可以把一個字符串復制給另一個字符串,格式如下:
strcpy(字符數(shù)組1,字符數(shù)組2);
注意哦,是把字符數(shù)組2復制給字符數(shù)組1,這里的“復制” 包括了結束標志/0??
示例如下:
#include#includeint main(){ char str1[50] = "Thank"; char str2[50] = "you for your smile."; strcpy(str1, str2); puts(str1);//輸出you for your smile. //printf("%s/n", str1); return 0;}
strcat()可以把一個字符串拼接到另一個字符串的后面
strcat(字符數(shù)組1, 字符數(shù)組2);
注意哦,是把字符數(shù)組2拼接到字符數(shù)組1的后面?
示例如下:
#include#includeint main(){ char str1[50] = "Thank"; char str2[50] = "you for your smile."; strcat(str1, str2); puts(str1);//輸出 Thankyou for your smile. //printf("%s/n", str1); return 0; return 0;}
常用函數(shù):
- push_back()
- pop_back()
- size()
- clear()
常用函數(shù)
- push()
- pop()
- front()
- back()
- empty()
- size()
常用函數(shù):
- push()
- pop()
- top()
- empty()
- size()
常用函數(shù):
- max()
- min()
- swap()
- fill()
- sort()
下面在介紹一些常見的容器:?
在C語言中,一般使用字符數(shù)組char str[ ] 來存放字符串,但是使用字符數(shù)組有時會顯得操作麻煩,而且容易因經(jīng)驗不足產(chǎn)生錯誤,得不償失。為了使編程者可以更方便的對字符串進行操作,C++在STL中加入了string類型,對字符串常用的需求功能進行了封裝,使得操作起來更方便,且不易出錯。
如果要使用string,需要添加string頭文件,即#include
(注意string.h 和 string 是不一樣的頭文件)。除此之外,還需要在頭文件下面加上一句:"using namespace std;", 這樣就可以在代碼中使用string了。下面來看string的一些常見用法。
定義string的方式跟基本數(shù)據(jù)類型相同,只需要在string后面跟上變量名即可:
string str;
如果要初始化,可以直接給string類型的變量進行賦值:
string str = "abcd"
一般來說,可以直接像字符數(shù)組那樣去訪問string:
#include#includeusing namespace std;int main(){ string str = "abcd"; for (int i = 0; i < str.length(); i++) { printf("%c ", str[i]);//輸出a b c d } return 0;}
注意哦,如果要讀入和輸出整個字符串,則只能用cin 和? cout:
#include//cin和cout在iostream頭文件中,而不是stdio.h#includeusing namespace std;int main(){ string str; cin >> str; cout << str; return 0;}
上面的代碼對任意的字符串輸入,都會輸出同樣的字符串。
那么,真的沒有辦法用printf來輸出string嗎?其實是有的,即用c_str()將string類型轉換為字符數(shù)組進行輸出,示例如下:
#include#includeusing namespace std;int main(){ string str = "abcd"; printf("%s/n", str.c_str());//將string型str使用c_str()變成字符數(shù)組 return 0;}
一般僅通過(1)即可滿足訪問的要求,但是有些函數(shù)比如insert()與erase()則要求以迭代器為參數(shù),因此還是需要學習一下string迭代器的用法。
由于string不像其他STL容器那樣需要參數(shù),因此可以直接入下定義:
string::iterator it;
這樣就得到了迭代器it, 并且可以通過*it 來訪問string里的每一位:
#include#includeusing namespace std;int main(){ string str = "abcd"; for (string::iterator it = str.begin(); it != str.end(); it++) { printf("%c ", *it);//輸出a b c d } return 0;}
最后指出,string和vector一樣,支持直接對迭代器進行加減某個數(shù)字,如str.begin() + 3的寫法是可行的
- operator+=
- compare operator
- length() / size()
- insert()
- erase()
- clear()
- substr()
- string::nops
- find()
- replace()
這是string的加法,可以將兩個string直接拼接起來
示例如下:
#include#includeusing namespace std;int main(){ string str1 = "abc", str2 = "xyz", str3; str3 = str1 + str2;//將str1和str2拼接,賦值給str3 str1 = str1 + str2;//將str2直接拼接到str1上 cout << str1 << endl;//輸出abcxyz cout << str3 << endl;//輸出abcxyz return 0;}
兩個string類型可以直接使用==、!=、<、<=、>、>=比較大小,比較規(guī)則是字典序。
示例如下:
#include#includeusing namespace std;int main(){ string str1 = "aa", str2 = "aaa", str3 = "abc", str4 = "xyz"; if (str1 < str2)//如果str1字典序小于str2,輸出ok1 { printf("ok1/n");//輸出ok1 } if (str1 != str3)//如果str1和str3字典序不等,輸出ok2 { printf("ok2/n");//輸出ok2 } if (str4 >= str3)//如果str4字典序大于等于str3,輸出ok3 { printf("ok3/n");//輸出ok3 } return 0;}
length()返回string的長度,即存放的字符數(shù)。時間復雜度為O(1)。size()與length()基本相同
示例如下:
string str = "abcdef";printf("%d %d/n", str.length(), str.size());//輸出6 6
string的insert()函數(shù)有很多種寫法,這里給出幾種常用的寫法。時間復雜度為O(N)
1.insert(pos, string), 在pos號位置插入一個字符串string
示例如下:
string str = "abcxyz", str2 = "opq";str.insert(3, str2);//往str[3]處插入opq,將括號里的str2直接寫成"opq"也是可以的cout<
2.insert(it, it2, it3), it 為原字符串的欲插入位置,it2 和 it3 為待插字符串的首尾迭代器,用來表示串[it2, it3)將被插在it 的位置上
示例如下:
#include#includeusing namespace std;int main(){ string str = "abcxyz", str2 = "opq";//str為原字符串,str2為待插字符串 //在str的3號位(即c和x之間)插入str2 str.insert(str.begin() + 3, str2.begin(), str2.end()); cout << str << endl;//輸出abcopqxyz return 0;}
erase()有兩種用法:刪除單個元素、刪除一個區(qū)間內的所有元素。時間復雜度均為O(N)
1.刪除單個元素:str.erase(it) 用于刪除單個元素,it為需要刪除的元素的迭代器
示例如下:
#include#includeusing namespace std;int main(){ string str = "abcdefg"; str.erase(str.begin() + 4);//刪除4號位(即e) cout << str << endl;//輸出abcdfg return 0;}
2.刪除一個區(qū)間內的所有元素:有兩種方法:
示例如下:
#include#includeusing namespace std;int main(){ string str = "abcdefg"; //刪除在[str.begin() + 2, str.end() - 1)內的元素,即cdef str.erase(str.begin() + 2, str.end() - 1); cout << str << endl;//輸出abg return 0;}
示例如下:
#include#includeusing namespace std;int main(){ string str = "abcdefg"; str.erase(3, 2);//刪除de cout << str << endl;//輸出abcfg return 0;}
clear()可以清空string中的數(shù)據(jù),時間復雜度一般為O(1)
示例如下:
#include#includeusing namespace std;int main(){ string str = "abcd"; str.clear();//清空字符串 cout << str.length() << endl;//輸出0 return 0;}
substr(pos, len) 返回從pos號位開始、長度為len的子串,時間復雜度為O(len)
示例如下:
#include#includeusing namespace std;int main(){ string str = "Thank you for your smile."; cout << str.substr(0, 5) << endl;//輸出Thank cout << str.substr(14, 4) << endl;//輸出your cout << str.substr(19, 5) << endl;//輸出smile return 0;}
string::npos是一個常數(shù),其本身的值為-1 ,但由于是unsigned int 類型,因此實際上也可以認為是unsigned int 類型的最大值,可認為是4,294,967,295。string::npos 用以作為 find 函數(shù)失配時的返回值。
str.find(str) 當str2 是str 的子串時,返回其在str 中第一次出現(xiàn)的位置,如果str2 不是str 的子串,那么返回string::npos
str.find(str2, pos), 從str 的pos 號位開始匹配str2,返回值與上相同。時間復雜度為O(M*N),M和N 分別是str2 和str的長度
示例如下:
#include#includeusing namespace std;int main(){ string str = "Thank you for your smile"; string str2 = "you"; string str3 = "me"; if (str.find(str2) != string::npos) { cout << str.find(str2) << endl;//輸出6 } if (str.find(str2, 7) != string::npos) { cout << str.find(str2, 7) << endl;//輸出14 } if (str.find(str3) != string::npos) { cout << str.find(str3) << endl; } else { cout << "I know there is no position for me." << endl; } return 0;}
str.replace(pos,len,str2) 把str 從pos 號位開始、長度為len 的子串替換為上str2
str.replace(it1,it2,str2) 把str 的迭代器[it1, it2)范圍的子串替換為str2
示例如下:
#include#includeusing namespace std;int main(){ string str = "Maybe you will turn around."; string str2 = "will not"; string str3 = "surely"; cout << str.replace(10, 4, str2) << endl; cout << str.replace(str.begin(), str.begin() + 5, str3) << endl; return 0;}
queue翻譯為隊列,在STL中主要則是實現(xiàn)一個先進先出的容器,當需要實現(xiàn)廣度優(yōu)先搜索時,可以不用自己手動實現(xiàn)一個隊列,而是用queue代替,以提高程序的準確性。
要使用queue, 需要先添加頭文件#include
其定義的寫法和其他STL容器相同,typename 可以是任意基本數(shù)據(jù)類型和容器:
queue name;
由于隊列(queue)本身就是一種先進先出的限制性數(shù)據(jù)結構,因此在STL中只能通過front() 來訪問隊首元素,或是通過back() 來訪問隊尾元素。
示例如下:
#include#includeusing namespace std;int main(){ queue q; for (int i = 1; i <= 5; i++) { q.push(i);//push(i)用以將i壓入隊列,因此依次入隊1 2 3 4 5 } printf("%d %d/n", q.front(), q.back());//輸出結果為1 5 return 0;}
- push()
- front()
- back()
- pop()
- empty()
- size()
push(x) 將x 進行入隊,時間復雜度為O(1)
front(), back()可以分別獲得隊首元素和隊尾元素,時間復雜度為O(1)
注意哦,使用front() 和 pop() 函數(shù)之前,必須用empty() 判斷隊列是否為空,否則可能會因為隊列空導致錯誤
pop()令隊首元素出隊,時間復雜度為O(1)
示例如下:
#include#includeusing namespace std;int main(){ queue q; for (int i = 1; i <= 5; i++) { q.push(i); } for (int i = 0; i < 3; i++) { q.pop();//出隊列元素3次,依次出隊1 2 3 } printf("%d/n", q.front());//輸出4 return 0;}
empty()檢測queue是否為空,返回true則為空,返回false則非空,時間復雜度為O(1)
示例如下:
#include#includeusing namespace std;int main(){ queue q; if (q.empty() == true)//一開始隊列里沒有元素,所以是空 { printf("Empty/n"); } else { printf("Not Empty/n"); } q.push(1); if (q.empty() == true) { printf("Empty/n"); } else { printf("Not Empty/n"); } return 0;}
size()返回queue內元素的個數(shù),時間復雜度為O(1)
示例如下:
#include#includeusing namespace std;int main(){ queue q; for (int i = 1; i <= 5; i++) { q.push(i); } printf("%d/n", q.size());//輸出5 return 0;}
【延伸】:STL容器中還有兩種容器跟隊列有關,分別是雙端隊列(deque) 和優(yōu)先隊列(priority_queue) ,前者是首尾皆可插入和刪除的隊列,后者是使用堆實現(xiàn)的默許將當前隊列最大元素置于隊首的容器,這里暫時先不介紹,后期如果需要再進行補充。
stack 翻譯為棧,是STL中實現(xiàn)的一個先進后出的容器,stack 用來模擬實現(xiàn)一些遞歸,防止程序對棧內存的限制而導致程序運行出錯。
要使用stack,應先添加頭文件#include
其定義的寫法和其他STL容器相同,typename可以是任意基本數(shù)據(jù)類型或容器:
stack name;
由于棧(stack) 本身就是一種先進后出的數(shù)據(jù)結構,在STL的stack 中只能通過top() 來訪問棧頂元素
示例如下:
#include#includeusing namespace std;int main(){ stack st; for (int i = 1; i <= 5; i++) { st.push(i);//依次入棧1 2 3 4 5 } printf("%d/n", st.top());//輸出5 return 0;}
- push()
- top()
- pop()
- empty()
- size()
push(x) 將x 入棧,時間復雜度為O(1),
top()獲得棧頂元素,時間復雜度為O(1)
pop()用以彈出棧頂元素,時間復雜度為O(1)
示例如下:
#include#includeusing namespace std;int main(){ stack st; for (int i = 1; i <= 5; i++) { st.push(i); } for (int i = 0; i < 3; i++) { st.pop(); } printf("%d/n", st.top());//輸出2 return 0;}
empty()可以檢測stack 內是否為空,返回true 為空,返回false 為非空,時間復雜度為O(1)
size()返回stack 內元素的個數(shù),時間復雜度為O(1)
使用algorithm 頭文件,需要在頭文件下面加上一行"using namespace std;",才能正常使用
- max()、min()、abs()
- swap()
- reverse()
- next_permutation()
- fill()
- sort()
- lower_bound() 和 upper_bound()
max(x,y)和min(x,y) 分別返回x, y中的最大值和最小值,且參數(shù)必須是兩個,可以是浮點數(shù),如果想返回三個數(shù)x,y,z的最大值,可以使用max(x, max(y, z)) 的寫法;abs(x) 返回x的絕對值。注意:此時的x 必須是整數(shù),浮點數(shù)的絕對值請用math 頭文件下的fabs
示例如下:
#include#includeusing namespace std;int main(){ int x = -1; int y = -2; printf("%d %d/n", max(x, y), min(x, y));//輸出-1 -2 printf("%d %d/n", abs(x), abs(y));//輸出1 2 return 0;}
swap(x, y) 用來交換x 和 y 的值
示例如下:
#include#includeusing namespace std;int main(){ int x = 10; int y = 20; swap(x, y); printf("%d %d/n", x, y);//輸出20 10 return 0;}
reverse(it, it2) 可以將數(shù)組指針在[it, it2) 之間的元素或容器的迭代器在[it, it2) 范圍內的元素進行反轉
示例如下:
#include#includeusing namespace std;int main(){ int arr[10] = { 10,11,12,13,14,15 }; reverse(arr, arr + 4);//將arr[0]~arr[3]反轉 for (int i = 0; i < 6; i++) { printf("%d ", arr[i]);//輸出13,12,11,10,14,15 } return 0;}
如果要是對容器中的元素(例如string 字符串)進行反轉,結果也是一樣
示例如下:
#include#include#includeusing namespace std;int main(){ string str = "abcdefghi"; reverse(str.begin() + 2, str.begin() + 6);//對str[0]~str[5]反轉 for (int i = 0; i < str.length(); i++) { printf("%c", str[i]);//輸出abfedcghi } return 0;}
next_permutation() 給出一個序列在全排列中得下一個序列
例如,當n == 3 時的全排列為:
123
132
213
231
312
321
這樣231的下一個序列就是312
示例如下:
#include#includeusing namespace std;int main(){ int a[10] = { 1,2,3 }; //a[0]~a[2]之間的序列需要求解next_permutation do { printf("%d%d%d/n", a[0], a[1], a[2]); } while (next_permutation(a, a + 3)); return 0;}
在上述的代碼中,使用循環(huán)是因為next_permutation在已經(jīng)到達全排列的最后一個時會返回false, 這樣會方便退出循環(huán)。而使用do...while語句而不使用while語句是因為序列1 2 3本身也需要輸出,如果使用while會直接跳到下一個序列再輸出,這樣的話結果會少一個123
fill()可以把數(shù)組或容器中的某一段區(qū)間賦為某個相同的值。和memset 不同,這里的賦值可以是數(shù)組類型對應范圍中的任意值
示例如下:
#include#includeusing namespace std;int main(){ int a[5] = { 1,2,3,4,5 }; fill(a, a + 5, 133);//將a[0]~a[4]均賦值為133 for (int i = 0; i < 5; i++) { printf("%d ", a[i]);//輸出133 133 133 133 133 } return 0;}
顧名思義,sort()就是用來排序的函數(shù),它根據(jù)具體情形使用不同的排序方法,效率較高。一般來說,不推薦使用C語言中的qsort函數(shù),原因是qsort 用起來比較繁瑣,涉及很多指針的操作。
sort函數(shù)的使用必須加上頭文件"#include
sort(首元素地址(必填),尾元素地址的下一個地址(必填),比較函數(shù)(非必填));
可以看到,sort的參數(shù)有三個,其中前兩個是必填的,而比較函數(shù)則可以根據(jù)需要填寫,如果不寫比較函數(shù),則默認對前面給出的區(qū)間進行遞增排序。
示例如下:
#include#includeusing namespace std;int main(){ int a[6] = { 9,4,2,5,6,-1 }; //將a[0]~a[3]進行從小到大排序 sort(a, a + 4); for (int i = 0; i < 6; i++) { printf("%d ", a[i]);//輸出2 4 5 9 6 -1 } putchar("/n"); //將a[0]~a[5]進行從小到大排序 sort(a, a + 6); for (int i = 0; i < 6; i++) { printf("%d ", a[i]);//輸出-1 2 4 5 6 9 } return 0;}
【敲黑板】:特別需要注意理解的是尾元素地址的下一個地址!
對double數(shù)組進行排序:
#include#includeusing namespace std;int main(){ double a[] = { 1.4,-2.1,9 }; sort(a, a + 3); for (int i = 0; i < 3; i++) { printf("%.1lf ", a[i]); } return 0;}
對char型數(shù)組進行排序(默認是字典序)
示例如下:
#include#includeusing namespace std;int main(){ char c[] = { "T", "W","A", "K" }; sort(c, c + 4); for (int i = 0; i < 4; i++) { printf("%c", c[i]);//輸出AKTW } return 0;}
我們需要知道的是,如果對序列進行排序,那么序列中的元素一定要有可比性,因此需要制定排序規(guī)則來建立這種可比性。特別是像結構體,本身并沒有大小關系,需要認為制定比較的規(guī)則。sort 的第三個可選參數(shù)就是cmp函數(shù),用來實現(xiàn)這個規(guī)則。
下面介紹對基本數(shù)據(jù)類型、結構體類型、STL容器進行自定義規(guī)則排序時cmp的寫法。
若比較函數(shù)不填,則默認按照從小到大的順序排序。
示例如下:
#include#includeusing namespace std;int main(){ int a[] = { 3,1,4,2 }; sort(a, a + 4); for (int i = 0; i < 4; i++) { printf("%d ", a[i]);//輸出1 2 3 4 } return 0;}
如果想要從大到小來排序,則要使用比較函數(shù)cmp 來“告訴”sort 何時要交換元素(讓元素的大小比較關系反過來)
示例如下:
#include#includeusing namespace std;bool cmp(int a, int b){ return a > b;//可以理解為當a>b時把a放在b前面}int main(){ int a[] = { 3,1,4,2 }; sort(a, a + 4, cmp); for (int i = 0; i < 4; i++) { printf("%d ", a[i]);//輸出4 3 2 1 } return 0;}
這樣就可以讓數(shù)值較大的元素放在前面,也就達到了從大到小排序的要求。
同樣的,對double型數(shù)組從大到小排序的代碼如下:
#include#includeusing namespace std;bool cmp(double a, double b){ return a > b;//同樣是a>b}int main(){ double a[] = { 1.4,-2.1,9 }; sort(a, a + 3, cmp); for (int i = 0; i < 3; i++) { printf("%.1lf ", a[i]);//輸出9.0 1.4 -2.1 } return 0;}
對char型數(shù)組從大到小排序如下:
#include#includeusing namespace std;bool cmp(char a, char b){ return a > b;//可以理解為當a>b時把a放在b之前}int main(){ char c[] = { "T","W","A","K" }; sort(c, c + 4, cmp); for (int i = 0; i < 4; i++) { printf("%c", c[i]);//輸出WTKA } return 0;}
【記憶方法】:
如果要把數(shù)據(jù)從小到大排列,那么就用"<", 因為"a", 因為"a>b" 就是左大右小。而當不確定或者忘記的時候,不妨兩種都試一下,就會知道該用哪種了。
現(xiàn)在定義了如下結構體:
struct node{ int x, y;}ssd[10];
如果想將ssd數(shù)組按照 x 從大到小排序(即進行一級排序),那么可以這樣寫cmp函數(shù):
bool cmp(node a, node b){ return a.x > b.x;}
示例如下:
#include#includeusing namespace std;struct node{ int x; int y;}ssd[10];bool cmp(node a, node b){ return a.x > b.x;//按x值從大到小對結構體數(shù)組進行排序}int main(){ ssd[0].x = 2; ssd[0].y = 2; ssd[1].x = 1; ssd[1].y = 3; ssd[2].x = 3; ssd[2].y = 1; sort(ssd, ssd + 3, cmp); for (int i = 0; i < 3; i++) { printf("%d %d/n", ssd[i].x, ssd[i].y); } return 0;}
而如果想先按x 從大到小排序,但當x相等的情況下,按照y的大小從小到大來排序(即進行二級排序),那么cmp的寫法是:
bool cmp(node a, node b){ if(a.x != b.x) { return a.x > b.x; } else { return a.y < b.y; }}
這里的cmp函數(shù)首先判斷結構體內的x 元素是否相等,如果不相等則直接按照x 的大小來排序,否則,按照y 的大小來排序。
示例如下:
#include#includeusing namespace std;struct node{ int x; int y;}ssd[10];bool cmp(node a, node b){ if (a.x != b.x) { return a.x > b.x;//x 不等時按x 從大到小排序 } else { return a.y < b.y;//x 相等時按y 從小到大排序 }}int main(){ ssd[0].x = 2; ssd[0].y = 2; ssd[1].x = 1; ssd[1].y = 3; ssd[2].x = 3; ssd[2].y = 1; sort(ssd, ssd + 3, cmp);//排序 for (int i = 0; i < 3; i++) { printf("%d %d/n", ssd[i].x, ssd[i].y); } return 0;}
在STL標準容器中,只有vector、string、deque是可以使用sort的。這是因為像set、map這種容器是用紅黑樹實現(xiàn)的(了解即可),元素本身有序,故不允許使用sort排序
vector示例如下:
#include#include#includeusing namespace std;bool cmp(int a, int b)//因為vector中的元素為int型,因此仍然是int的比較{ return a > b;}int main(){ vector vi; vi.push_back(3); vi.push_back(1); vi.push_back(2); sort(vi.begin(), vi.end(), cmp); for (vector::iterator it = vi.begin(); it != vi.end(); it++) { printf("%d ", *it);//輸出3 2 1 } return 0;}
再來看string 的排序,示例如下:
#include#include#includeusing namespace std;int main(){ string str[3] = { "bbbb", "cc", "aaa" }; sort(str, str + 3);//將string數(shù)組按字典樹從小到大輸出 for (int i = 0; i < 3; i++) { cout << str[i] << endl; } return 0;}
如果上面這個例子中,需要按照字符串長度從小到大排序,那么可以這樣寫:
#include#include#includeusing namespace std;bool cmp(string str1, string str2){ return str1.length() < str2.length();//按照string 的長度從小到大排序}int main(){ string str[3] = { "bbbb", "cc", "aaa" }; sort(str, str + 3, cmp); for (int i = 0; i < 3; i++) { cout << str[i] << endl; } return 0;}
lower_bound() 和 upper_bound() 需要用在一個有序數(shù)組或容器中
lower_bound(first, last, val) 用來尋找在數(shù)組或容器的[first, last) 范圍內第一個值大于等于val元素的位置,如果是數(shù)組,則返回該位置的指針;如果是容器,則返回該位置的迭代器。
upper_bound(first, last, val) 用來尋找在數(shù)組或容器的[first, last) 范圍內第一個值大于val 的元素的位置,如果是數(shù)組,則返回該位置的指針;如果是容器,則返回該位置的迭代器。
顯然,如果數(shù)組或容器中沒有需要尋找的元素,則lower_bound() 和 upper_bound() 均返回可以插入該元素的位置的指針或迭代器(即假設存在該元素時,該元素應當在的位置)。
示例如下:?
#include#includeusing namespace std;int main(){ int a[10] = { 1,2,2,3,3,3,5,5,5,5 }; //尋找-1 int* lowerPos = lower_bound(a, a + 10, -1); int* upperPos = upper_bound(a, a + 10, -1); printf("%d %d/n", lowerPos - a, upperPos - a);//輸出0 0 //尋找1 lowerPos = lower_bound(a, a + 10, 1); upperPos = upper_bound(a, a + 10, 1); printf("%d %d/n", lowerPos - a, upperPos - a);//輸出0 1 //尋找3 lowerPos = lower_bound(a, a + 10, 3); upperPos = upper_bound(a, a + 10, 3); printf("%d %d/n", lowerPos - a, upperPos - a);//輸出3 6 //尋找4 lowerPos = lower_bound(a, a + 10, 4); upperPos = upper_bound(a, a + 10, 4); printf("%d %d/n", lowerPos - a, upperPos - a);//輸出6 6 //尋找6 lowerPos = lower_bound(a, a + 10, 6); upperPos = upper_bound(a, a + 10, 6); printf("%d %d/n", lowerPos - a, upperPos - a);//輸出10 10 return 0;}
顯然,如果只想獲得欲查元素的下標,就可以不使用臨時指針,而直接令返回值減去數(shù)組首地址即可。
【敲黑板】:這里補充一條知識點,指針 - 指針? = 兩指針之間的元素個數(shù)
示例如下:
#include#includeusing namespace std;int main(){ int a[10] = { 1,2,2,3,3,3,5,5,5,5 }; //尋找3 printf("%d %d/n", lower_bound(a, a + 10, 3) - a, upper_bound(a, a + 10, 3) - a);//輸出3 6 return 0;}
希望能給大家?guī)韼椭a字不易,如果可以動動小手來個三連那就更好啦,hh,咱們下次再見。
·
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/124089.html
摘要:針對計算機類的同學,數(shù)學建模,電子科技大賽,大創(chuàng),,藍橋杯這些都是值得參加的高含金量的比賽,無論是學校加分還是應屆招聘,都被廣泛認可。但近幾屆的藍橋杯題目難度已經(jīng)明顯增大,準備參加的同學也決不可掉以輕心。 ...
摘要:文章目錄一你應該知道的藍橋杯含金量獲獎率高不高支持哪些編程語言二川川帶你體驗藍橋杯省賽藍橋杯藍橋杯三個人感受一你應該知道的藍橋杯如果你是計算機相關專業(yè),你不知藍橋杯就過不去了,我們來看看藍橋杯如何,不知道更應該來了解下了。 ...
摘要:問題描述審美的歷程課上有位學生,帥老師展示了幅畫,其中有些是梵高的作品,另外的都出自五歲小朋友之手。輸入格式第一行兩個數(shù)和,表示學生數(shù)和圖畫數(shù)接下來是一個的矩陣如果,表示學生覺得第幅畫是小朋友畫的如果,表示學生覺得第幅畫是梵高畫的。 問題描述 《審美的歷程》課上有n位學生,帥老師展示了m幅畫,其中有些是梵高的作品,另外的都出自五歲小朋友之手。老師請同學們分辨哪些畫的作者是梵高,但是老...
摘要:而眾所周知,馬是要走日子格的。輸出格式輸出有一行,一個數(shù)表示走法數(shù)。那為了防止爆掉,我們每加完一條路的總步數(shù)之后就取一遍余。題目解法思路如上述,但是這里有一個我之前從來沒有注意過的問題,導致我一直只有分。三題解四題目鏈接過河馬 ...
摘要:現(xiàn)在小明想統(tǒng)計有哪些帖子曾經(jīng)是熱帖。如果一個帖子曾在任意一個長度為的時間段內收到不少于個贊,小明就認為這個帖子曾是熱帖。以下行列代表一張海域照片。照片保證第行第列第行第列的像素都是海洋。 2018年4月1日愚人節(jié),我第一次參加了有關計算機算法類比賽藍橋杯,這篇算是經(jīng)驗總結和題目回顧,水平有限,有不妥之處歡迎留言批評指正,也可以加QQ891465170交流~下面進入正題: 第一題:第幾...
閱讀 2662·2021-11-23 09:51
閱讀 3252·2021-11-22 14:44
閱讀 4582·2021-11-22 09:34
閱讀 5124·2021-10-08 10:14
閱讀 2437·2021-09-22 15:47
閱讀 3512·2021-09-22 15:40
閱讀 1515·2019-08-30 15:44
閱讀 1626·2019-08-28 18:23