1、可隨機訪問,可在尾部插入元素;2、內存自動管理;3、頭文件#include <vector>
1、創建vector對象
一維:
(1) vector<int>v1;
(2) vector<int>v2(10);//10個元素,初始為0
(3) vector<int>v3(10,4);//10個元素,初始為4
(4) vector<int>v4(v3);//拷貝
(5) vector<int>v5=v4;//拷貝
(6) vector<int>v6(v.begin(), v.end());
(7) int a[4]={1,2,3}; vector<int>v7(a,a+sizeof(a)/sizeof(a[0]));//類似上面
(8) string str[]={"abc", "def", "ghi" }; vector<string>v8(str,str+sizeof(str)/sizeof(string));//類似上面
(9) char *s[]={"abc", "def", "ghi" }; vector<string>v9(s,s+sizeof(s)/sizeof(int));//類似上面
二維:
(1) int n=3, m=4; vector<vector<int>>matrix(n, m);//創建一個n行m列初始值為0的二維vector對象
(2) vector<vector<int>>mat(n,vector<int>(m,9));//賦初值為9
note: mat.size(); mat[0].size();
2、尾部元素擴張:v.push_back(elem);
3、下標方式訪問:v[index]=elem; cout<<v[index];//下面遍歷二維向量
int a[]={1,2,3,4,5}; vector<int>v(a,a+sizeof(a)/sizeof(a[0])); vector<vector<int>>mat(3,v); for(size_t i =0; i<mat.size(); i++){ for(size_t j=0; j<mat[i].size(); j++) cout<<mat[i][j]; cout<<endl; }4、v.at(index)訪問:mat.at(1).at(2)=433; cout<<mat.at(1).at(2);//二維舉例
5、用迭代器訪問與遍歷:
begin()、end()、rbegin()、rend():begin()返回的是首元素位置的迭代器;end()返回的是最後一個元素的下一元素位置的迭代器。rbegin()、rend()與他們相反。
vector<int>::iterator it; for(it=v.begin();it!=v.end();it++) cout<<*it<<" "; //使用auto,代碼顯得簡潔 for(auto i=v.begin(); i!=v.end(); i++) cout<<*i<<" "; //反向遍歷 迭代器為reverse_iterator for(auto i=v.rbegin(); i!=v.rend(); i++) cout<<*i<<" ";//這兩種遍歷方式對於其它類也可用int arr[5]={10,20,30,40,50}; vector<int>vec(arr,arr+sizeof(arr)/sizeof(arr[0])); cout<<(*vec.begin())+2<<endl;//12 cout<<*(vec.begin()+2)<<endl;//30 cout<<*vec.begin()+2<<endl;//12 //*操作符優先級大於+操作符的優先級6、元素的插入(insert把一個數據插入到迭代器位置之前) v.insert(pos,elem) v.insert(pos,n,elem) v.insert(pos,beg,end)
vector<int>v(10); int a[]={1,2,3,4,5,6,7}; vector<int>v1(a,a+sizeof(a)/sizeof(a[0])); v.insert(v.begin()+1, v1.begin(),v1.begin()+3); for(auto i=v.begin(); i!=v.end(); i++) cout<<*i; cout<<*(v1.begin()+3)<<endl; //v.insert(pos,beg,end); 拷貝區間為[beg,end)7、元素的刪除 v.erase(pos) v.erase(beg,end)。區間為[beg,end)。
8、使用reverse反向排列算法,頭文件<algorithm>
reverse(v.begin(),v.end());
9、sort排序
(1)sort(v.begin(),v.end());//默認為升序
(2)sort(v.begin(),v.end(),cmp);//以cmp條件函數排序
10、size() 與 capacity()、reserve()與resize()
(1) capacity指的是容量,size指的是實際元素的個數。size<=capacity
(2) 當元素大於容量時,容量函數增加。
(3)empty()方法返回向量是否為空,指的是實際數據個數。
(4)reserve()和resize()分別是對capacity與size的重設,當發生異常時,vector對象會自動擴容。
下表來源:http://blog.csdn.net/phoebin/article/details/3864590 string
頭文件<string>
1、創建string對象: string s;
2、給string對象賦值:
(1) s=”abc”;
(2)把字符指針賦給一個字符串對象。
char *c1="abcde"; char c2[]={'f','g','h','\0'}; string s=c1; s+=c2; cout<<s<<endl;3、在尾部添加字符、字符串
string s; s+='a'; s.push_back('b');//注意,不能用這個方法添加字符串 s.pop_back(); s+="cde"; s.append("f");//不能用這個方法添加字符 cout<<s<<endl;4、插入字符 (insert()方法把一個字符插入到迭代器位置之前)。s.insert(pos, char),s.insert(pos,n,elem) s.insert(pos,beg,end)
5、下標方式訪問。
6、刪除元素。(1)s=“”;(2)earse()
7、返回長度。s.length()或者s.size()
8、替換string對象的字符,常用的replace(beginIndex,len,str)
string s; s="abc123456"; s.replace(3,3,"good"); //從第3個開始,將連續的3個字符替換為“good”,即將“abc”替換為“good” cout<<s<<endl;9、搜索string對象的元素或子串。find()
//find()方法可查找字符、字符串,未找到返回string::npos的值(4294967295) //find 必須匹配完整的字符串,find_first_of只需要匹配部分即可(group) string s=" acbac "; cout<<s.find("ab")<<endl;//2,返回字符串的首位下標 cout<<s.find_first_not_of(' ')<<endl;//2 cout<<s.find_first_of("1234567a")<<endl;//2,只需符合該組中一個元素即可 cout<<s.find_last_not_of(' ')<<endl;//4 cout<<s.find_last_of('c')<<endl;//4 cout<<s.rfind('a')<<endl;//4,從尾部向前搜索,返回找到的第一個 int a=s.find("ab"); printf("%d", a==string::npos);//1,沒有找到,返回npos10、字符串的比較。 compare()
//如果它比對方大,則返回1;如果它比對方小,則返回-1;如果它與對方相同(相等),則返回0。 string s1="12345"; string s2="fgger"; cout<<s1.compare(s2)<<endl; //判斷是否相同可以直接用比較運算符 bool isq=s1==s2; cout<<isq<<endl; isq="1"=="1"; cout<<isq<<endl;11、用reverse反向排序string對象。reverse頭文件<algorithm>,reverse(s.begin(),s.end());
12、與數值間的相互轉化
//數值轉字符串 C++方法,使用<sstream>中的ostringstream流 double d=1.34; ostringstream o; if(o << d) //把數值d輸入流中 cout<<o.str()<<endl; else cout<<"conversion error"<<endl; //字符串轉數值 C++方法,使用<sstream>中的istringstream流 string s3="1234.234"; istringstream i(s3); //把字符串放入流中 double d2; if(i >> d2) //從流中輸出d cout<<d2<<endl; else d2=0.0; //將數值轉換為string:C方法,使用sprintf函數 char b[10]; string a; sprintf(b,"%d",1975); //不能直接打印到string上,sprintf是C函數 a=b; cout<<a<<endl;13、printf打印string對象。采用c_str()方法(printf是C函數,string屬於C++)
printf(s.c_str());printf("%s",s);//這是錯的14、其它
了解C函數sscanf()、sprintf()的使用
set
set集合容器實現了紅黑樹(Red-Black Tree)的平衡二叉檢索樹的數據結構,在插入元素時,它會自動調整二叉樹的排列,把該元素放到適當的位置,以確保每個子樹根節點的鍵值大於左子樹所有節點的鍵值,而小於右子樹所有節點的鍵值;另外,還得確保根節點左子樹的高度與右子樹的高度相等,這樣,二叉樹的高度最小,從而檢索速度最快。要注意的是,它不會重復插入相同鍵值的元素,而采取忽略處理。multiset(多重集合容器)、map(映照容器)和multimap(多重映照容器)的內部結構也是平衡二叉檢索樹。
set元素不可重復,multiset元素可重復。
對應的不排序的集合:unordered_set,頭文件<unordered_set>
set頭文件<set>
1、創建set集合對象。set<int>s;
2、插入元素。用insert(elem)方法把元素按順序插入集合,若重復插入某元素,則後來的插入無效,但不會出錯。
3、元素的反向遍歷(參考vector的反向遍歷或下面代碼)。
5、元素的刪除。s.erase(elem); 元素的清空 s.clear();
6、元素的檢索。使用find(),如果找到查找的鍵值,則返回該鍵值的迭代器位置,否則,返回集合最後一個元素後面的一個位置,即end()。
set<int>s; s.insert(4); s.insert(3); s.insert(7); s.insert(1); s.insert(3);//重復元素,不會插入 s.erase(3);//將元素3擦除 auto it= s.find(3);//查找元素3,找到返回迭代器位置,否則返回s.end() if(it!=s.end()) cout<<"found "<<*it<<endl; else cout<<"not found!"<<endl; //反向遍歷集合中元素 set<int>::reverse_iterator i; for(i=s.rbegin(); i!=s.rend(); i++) cout<<*i<<" ";7、自定義比較函數。使用insert()將元素插入到集合中去的時候,集合會根據設定的比較函數將該元素放到該放的節點上去。在定義集合的時候,如果沒有指定比較函數,那麼采用默認的比較函數,即按鍵值由小到大的順序插入元素。在很多情況下,需要自己編寫比較函數。編寫比較函數有兩種方法。
(1)如果元素不是結構體,那麼,可以編寫比較函數。//自定義比較函數myComp,重載“()”操作符 struct myComp { bool operator()(const int &a,const int &b) { if(a!=b) return a>b; else return a>b; } }; int main() { set<int, myComp>s; s.insert(4); s.insert(3); s.insert(7); s.insert(1); s.insert(3);//重復元素,不能插入 s.erase(3);//將元素3擦除 set<int, myComp>::iterator i; for(i=s.begin(); i!=s.end(); i++) cout<<*i<<" "; system("pause"); return 0; }(2)如果元素是結構體,那麼,可以直接把比較函數寫在結構體內。
struct Info { string name; float score; //重載“<”操作符,自定義排序規則 bool operator < (const Info &a) const { //按score由大到小排列。如果要由小到大排列,使用“>”號即可。 return a.score<score; } }; int main() { //定義元素類型為Info結構體的集合對象s,當前沒有任何元素 set<Info> s; //定義Info類型的元素 Info info; //插入3個元素 info.name="Jack"; info.score=80.5; s.insert(info); info.name="Tomi"; info.score=20.5; s.insert(info); info.name="Nacy"; info.score=60.5; s.insert(info); set<Info>::iterator it;//定義前向迭代器 for(it=s.begin();it!=s.end();it++) { cout<<(*it).name<<" : "<<(*it).score<<endl; } system("pause"); return 0; }map
map映照容器的元素數據是由一個鍵值和一個映照數據組成的,鍵值與映照數據之間
具有一一映照的關系。鍵值不可重復,並按照鍵值排序。multimap多重映照容器,鍵值可重復頭文件<map>
對應的不排序的unordered_set,頭文件<unordered_map>
1、map創建、元素插入和遍歷訪問
map<int,string>m; m[1]="a"; m[4]="b"; m[3]="c"; m[7]="e"; m[6]="f"; m[5]="g"; //結合pair插入元素// map<int,string>mp; pair<int,string>p; p=make_pair(1,"q"); mp.insert(p); auto mb=mp.begin(); auto me=mp.end(); cout<<mb->first<<; cout<<(*mb).second<<endl; cout<<(*mp.begin()).first; cout<<(*mp.begin()).second; for(auto i=m.begin(); i!=m.end(); i++)//遍歷輸出 cout<<(*i).first<<" : "<<(*i).second<<endl;2、刪除元素。m.erase(key)
3、反向遍歷。(參考vector)
4、元素的搜。find(),(參考set)
5、自定義比較函數。(兩種,結構體,或者非結構體,參考set)
stl的string,vector,map問題,優化
大概看了下,發現你對C++的了解和使用還欠缺很多。
整段代碼各種很低效的寫法,比如split函數按值返回一個vector,這將引起兩次vector全量拷貝,是極大的浪費,參數用的是按值傳遞而不是按const引用傳遞,等等。字符串操作混用C和C++的處理方式,一會用string一會又用char數組,等等。都是很不好的習慣。另外還用了C++中的stream,但C++中的stream效率不如C中的FILE。
另外你的編碼風格也不太好,變量名沒有任何含義,別人看得時候很難理解。
上述都是一些寫法習慣問題,你這個代碼從算法角度上說也是很低效的。
你為什麼要在循環中每次遍歷一遍vec3呢?僅僅只是為了count一下,為何不在一開始那個while循環裡面就count好呢?這樣你整個程序都只需要遍歷一遍vec3就行了啊,時間復雜度馬上降低一個量級。
還有你那個vec4,也是很不合適的用法。從你的代碼來看,你的vec4只是為了做一個重復性檢測,為什麼要用vector呢?這種時候顯然用set更好啊,在vector裡查找是很慢的,時間復雜度O(n)啊,set裡查找一個元素只需要O(logn),快一個級別。
感覺你對STL裡面的標准容器的認識還欠缺很多,沒有搞清楚這些容器的適用場合。還是需要多補補基礎啊。
去什地方下載 c++ 標准庫stl vector 的源碼
不用下的,比如你用到了vector,那就必須導入vector是不是?所以在文件開頭就有這麼一句:#include <vector>,那麼在vector上右鍵,會有打開文件或者轉到定義之類的選項,選擇就會打開了。當然我說的實在集成開發環境中。