程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> STL學習:STL庫vector、string、set、map用法,stlvector

STL學習:STL庫vector、string、set、map用法,stlvector

編輯:C++入門知識

STL學習:STL庫vector、string、set、map用法,stlvector


常用方法

 

vector

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,沒有找到,返回npos

10、字符串的比較。 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上右鍵,會有打開文件或者轉到定義之類的選項,選擇就會打開了。當然我說的實在集成開發環境中。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved