STL的一些數據結構


chunlvxiong的博客


本文默認#include <bits/stdc++.h>,默認using namesapce std。

一、vector

  vector相當於一個動態的數組。

  1、定義:vector <int> a--這樣a的存儲數據類型為int,你也可以定義一個結構體,例如vector <node> a。

  2、清空:a.clear()

  3、判斷是否空:a.empty()--如果空返回1,否則返回0

  4、元素個數:a.size()--注意實際存儲區間是0..a.size()-1

  5、讀取元素:a[i]--vector存儲區間連續,因此可以直接讀取。

  6、尾部插入元素b:a.push_back(b)--復雜度O(1)。

  7、尾部刪除元素:a.push_pop()--復雜度O(1)。

  8、返回開頭元素的位置:a.begin()

  9、返回末尾元素的后一個位置:a.end()

  10、刪除元素:a.erase()  例如:a.erase(a.begin()+3)--刪除第4個元素

  復雜度與元素在序列中的位置有關,元素位置越往后這個操作越快,如果刪除開頭元素復雜度為O(N)。

對比:

  下面這是一個用於建邊的數組模擬鏈表。

#include <bits/stdc++.h>
using namespace std;
const int maxm=10005;
const int maxn=10005;
struct node{
    int to,len,next;
}edge[maxm];
int m,head[maxn],tot;
void init(){
    memset(head,0,sizeof(head)),tot=0;
}
void makedge(int u,int v,int t){
    edge[++tot].to=v;
    edge[tot].len=t;
    edge[tot].next=head[u];
    head[u]=tot;
}
int main(){
    scanf("%d",&m),init();
    for (int i=1,u,v,t;i<=m;i++){
        scanf("%d%d%d",&u,&v,&t);
        makedge(u,v,t);
    }
    return 0;
}

  下面是用vector實現的程序。

#include <bits/stdc++.h>
using namespace std;
const int maxn=10005;
struct node{
    int to,len;
};
int m;
vector<node>edge[maxn];
void init(){
    for (int i=1;i<=maxn;i++) edge[i].clear();
}
int main(){
    scanf("%d",&m),init();
    for (int i=1,u,v,t;i<=m;i++){
        scanf("%d%d%d",&u,&v,&t);
        edge[u].push_back(node{v,t});
    }
    return 0;
}

二、map

  map是一種關聯容器,它能建立key-value的對應關系。

  1、定義:例如map <string,int> a,定義一個key為string類型,value為int類型(一般這樣可以完成字符串Hash的功能)。

  2、清空:a.clear()

  3、判斷是否空:a.empty()--如果空返回1,否則返回0

  4、元素個數:a.size()--注意實際存儲區間為0..a.size()-1

  5、插入元素:a["stjfsijf"]=5--即認為key為stjfsijf的value被修改為5--復雜度帶log

  6、讀取元素:a["……"]--類似數組方式直接讀取即可。

對比:

  下面是一個字符串hash的程序。

#include <bits/stdc++.h>
using namespace std;
int n,size;
char s[1005],name[1005][1005];
int find(char s[]){
    for (int i=1;i<=size;i++)
    if (strcmp(s,name[i])==0)
        return i;
    strcpy(name[++size],s);
    return size;
}
int main(){
    size=0;
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        scanf("%s",&s);
        printf("%d\n",find(s));
    }
    return 0;
}

    然后下面是用map實現的程序。

#include <bits/stdc++.h>
using namespace std;
map <string,int> name;
int n;
string s;
int main(){
    name.clear();
    scanf("%d",&n);
    for (int i=1,cnt=0;i<=n;i++){
        cin>>s;
        if (name[s]==0) name[s]=++cnt;
        printf("%d\n",name[s]);
    }
    return 0;
}

三、set

  set是一種集合容器,它的用途在於高效檢索。

  1、定義:set <int> a--這樣a的存儲數據類型為int,你也可以定義一個結構體,例如set <node> a。

  2、清空:a.clear()

  3、判斷是否空:a.empty()--如果空返回1,否則返回0

  4、元素個數:a.size()--注意實際存儲區間為0..a.size()-1

  5、插入值為b的元素:a.insert(b)--復雜度帶log,但要注意相同的值只會保留最前面的一個。

  6、刪除值為b的元素:a.erase(b)--復雜度帶log。

  7、返回開頭元素的位置:a.begin()

  8、返回末尾元素的后一個位置:a.end()

  9、查找元素:a.find(b)--復雜度帶log,找到返回該元素迭代器的位置,如果找不到返回a.end()。

  10、a.lower_bound(b)--返回第一個大於等於b的元素迭代器的位置,如果找不到返回a.end()(復雜度帶log)

  11、a.upper_bound(b)--返回第一個大於b的元素迭代器的位置,如果找不到返回a.end()(復雜度帶log)

實例:

  下面通過一個具體程序來說明set的用法。

#include <bits/stdc++.h>
using namespace std;
struct node{
    int x,y;
    friend operator <(node a,node b){
        return a.x<b.x;
    }
};
set <node> a;
set <node>::iterator id;
int n,q;
int main(){
    a.clear();
    scanf("%d",&n);
    for (int i=1,x,y;i<=n;i++){
        scanf("%d%d",&x,&y);
        if (a.find(node{x,0})!=a.end()) a.erase(node{x,0});
        a.insert(node{x,y});
    }
    scanf("%d",&q);
    for (int i=1,x;i<=q;i++){
        scanf("%d",&x);
        id=a.find(node{x,0});
        if (id==a.end()) puts("-1");
        else printf("%d\n",(*id).y);
    }
    return 0;
}
/*
程序要求:輸入n個key-value(均為int類型),要求使用set維護。
如果有相同的數在,將value改為后一個。
接下來有q個詢問,每個詢問一個數,如果它存在,那么輸出它的value。
如果不存在,輸出-1。 
*/

四、priority_queue

  priority_queue是優先隊列,也就是堆。

  1、定義:priority_queue <int> a--這樣a的存儲數據類型為int,你也可以定義一個結構體,例如priority_queue <node> a。

  2、入堆:a.push(b)--復雜度帶log

  3、堆頂元素出堆:a.pop()--復雜度帶log

  4、判斷是否空:a.empty()--如果空返回1,否則返回0

  5、元素個數:a.size()--注意實際存儲區間為0..a.size()-1

  6、取出堆頂元素:a.top()

對比:

  下面給出堆排(降序)的程序。

#include <bits/stdc++.h>
using namespace std;
const int maxn=105;
int n,heap_volume,heap[maxn];
void push(int x){
    int i=++heap_volume;
    while (i>1 && x>heap[i>>1]){
        heap[i]=heap[i>>1];
        i>>=1;
    }
    heap[i]=x;
}
void pop(){
    int x=heap[heap_volume--],i=1,j;
    while (i<=heap_volume){
        j=i<<1;
        if (j+1<=heap_volume && heap[j+1]>heap[j]) j++;
        if (j<=heap_volume && heap[j]>x){
            heap[i]=heap[j];
            i=j;
        }
        else{
            heap[i]=x;
            break;
        }
    }
}
int main(){
    scanf("%d",&n);
    heap_volume=0;
    for (int i=1,x;i<=n;i++)
        scanf("%d",&x),push(x);
    for (int i=1;i<=n;i++)
        printf("%d ",heap[1]),pop();
    return 0;
}

  下面給出使用priority_queue之后的堆排。

#include <bits/stdc++.h>
using namespace std;
int n;
priority_queue <int> heap;
int main(){
    scanf("%d",&n);
    for (int i=1,x;i<=n;i++)
        scanf("%d",&x),heap.push(x);
    for (int i=1;i<=n;i++)
        printf("%d ",heap.top()),heap.pop();
    return 0;
}

 五、list

  list即雙向鏈表,跟vector很像,不同之處在於其中間修改元素較快但不支持隨機訪問元素。

  1、定義:list <int> a--這樣a的存儲數據類型為int,你也可以定義一個結構體,例如list <node> a。

  2、清空:a.clear()

  3、判斷是否空:a.empty()--如果空返回1,否則返回0

  4、元素個數:a.size()--注意實際存儲區間為0..a.size()-1

  5、插入元素:

    尾部:a.push_back(b)--復雜度O(1)

    頭部:a.push_front(b)--復雜度O(1)

  6、返回開頭元素的位置:a.begin()

  7、返回末尾元素的后一個位置:a.end()

  8、刪除元素:

    尾部:a.pop_back()--復雜度O(1)

    頭部:a.pop_front()--復雜度O(1)

    a.erase()--注意此時你不能使用a.erase(a.begin()+3)來刪除第4個元素,因為list不是vector,占用連續的內存空間。

  9、排序:a.sort(cmp)--你可以自己寫比較函數

實例:

  下面用一個程序來具體說明list的用法。

#include <bits/stdc++.h>
using namespace std;
list <int> a;
list <int>::iterator id;
bool cmp(int a,int b){
    return a>b;
}
int main(){
    int x;
    while (~scanf("%d",&x)){
        a.push_back(x);
        if (a.size()>10) a.pop_front();
    }
    a.sort(cmp);
    id=a.begin();
    for (id=a.begin();id!=a.end();id++)
        printf("%d\n",(*id));
    return 0;
}
/*
程序說明:輸入一些元素加入到list中,若元素個數超過10個,那么刪掉表頭元素。
最后降序輸出所有元素。 
*/

 六、deque

  deque,雙端隊列。

    1、定義:deque <int> a--這樣a的存儲數據類型為int,你也可以定義一個結構體,例如deque <node> a。

  2、清空:a.clear()

  3、判斷是否空:a.empty()--如果空返回1,否則返回0

  4、元素個數:a.size()--注意實際存儲區間為0..a.size()-1

  5、插入元素:

    尾部:a.push_back(b)--復雜度O(1)

    頭部:a.push_front(b)--復雜度O(1)

  6、返回開頭元素的位置:a.begin()

  7、返回末尾元素的后一個位置:a.end()

  8、刪除元素:

    尾部:a.pop_back()--復雜度O(1)

    頭部:a.pop_front()--復雜度O(1)

  9、刪除元素:a.erase()  例如:a.erase(a.begin()+3)--刪除第4個元素

  這個東西復雜度與元素位置有關,如果元素位置靠近頭部或是尾部那么會比較快,但是如果元素位置在中間那么復雜度是O(N)的。

  10、讀取元素:a[i]

實例:

#include <bits/stdc++.h>
using namespace std;
deque <int> a;
int n;
int main(){
    a.clear();
    scanf("%d",&n);
    for (int i=1,x,y;i<=n;i++){
        scanf("%d%d",&x,&y);
        if (y) a.push_back(x);
        else a.push_front(x);
    }
    while (!a.empty())
        printf("%d\n",a[0]),a.pop_front();
    return 0;
}
/*
程序說明:輸入n個數,並給出其插入方式(1表末尾插入,0表頭部插入)
最后要求輸出最終序列。 
*/

七、stack/queue

  這兩個東西誰都不會陌生,一個是棧,另一個是隊列。

  1、定義:stack<int>a或是queue<int>a,支持結構體,例如:stack<node>a或是queue<node>a。

  2、元素個數:a.size()--注意實際存儲區間為0..a.size()-1

  3、判斷是否空:a.empty()--如果空返回1,否則返回0

  4、入隊/入棧:a.push(x)

     出隊/出棧:a.pop()

  5、訪問棧頂/隊頭元素:

    stack:a.top()

    queue:a.front()

  其實個人覺得這兩個東西還不如自己寫了算了。

八、iterator

  迭代器,很多數據結構都要用到的東西。

  1、定義:以vector為例:vector<int>::iterator a

  2、雙向:a++,a--  前后置迭代器

  3、輸出:(*a)或(*a).val

  4、隨機:a+=p,a-=p  前后移動迭代器p位

     也支持引用a+p,a-p。

  5、賦值:a=b

  6、比較:a==b或a!=b判斷兩個迭代器是否相同

  對於隨機迭代器,還可以通過<,>,<=,>=等符號來判斷位置關系。

下面給出上述數據結構的迭代器類型:

  vector:隨機迭代器

  map:雙向迭代器

  set:雙向迭代器

  priority_queue:不支持迭代器

  list:雙向迭代器

  deque:隨機迭代器

  stack/queue:不支持迭代器

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM