1. 程式人生 > >STL-set (集合)之刪除元素

STL-set (集合)之刪除元素

set概述


和vector、list不同,set、map都是關聯式容器。set內部是基於紅黑樹實現的。插入和刪除操作效率較高,因為只需要修改相關指標而不用進行資料的移動。 
在進行資料刪除操作後,迭代器會不會失效呢?刪除set的資料時,實際的操作是刪除紅黑樹中的一個節點,然後相關指標做相關調整。指向其他元素的迭代器還是指向原位置,並沒有改變,所以刪除一個節點後其他迭代器不會失效。list和map也是同樣的道理。然而刪除vector中的某個元素,vector中其他迭代器會失效,因為vector是基於陣列的,刪除一個元素後,後面的元素會往前移動,所以指向後面元素的迭代器會失效。 
再稍微說一下迭代器的實現。迭代器是一個物件,vector的迭代器是封裝了陣列下標;list、map、set的迭代器是封裝了元素節點的指標。 
還有一點,從數學層面,set的一個集合,好比一個袋子裡面裝了好多個小球。但是紅黑樹是一種特殊的二叉搜尋樹,set中的元素根據其值的大小在紅黑樹中有特定的位置,是不可移動的。所以,1是search操作效率會很高O(log n),2是set中元素的值不可改變。

set的資料操作

::begin()      //迭代器
::end()      //迭代器
::clear()     //刪除set容器中的所有的元素
::empty()    //判斷set容器是否為空
::max_size()  //返回set容器可能包含的元素最大個數
::size()    //返回當前set容器中的元素個數
::rbegin   //逆迭代器
::rend()  //逆迭代器

小問題
set是基於紅黑樹實現的,那麼set的迭代器begin()、end()是指向哪裡的呢? 
一個測試程式:
#include<iostream>
#include<set>
using namespace std;
int main()
{
    set<int> myset;
    myset.insert(4);
    myset.insert(7);
    myset.insert(2);
    myset.insert(0);
    myset.insert(4);
    set<int>::iterator it;
    for(it = myset.begin(); it != myset.end(); it++)
    {
        cout<< *it;   //輸出結果是:0247
    }
}

紅黑樹首先是二叉搜尋樹,所以begin()迭代器指向紅黑樹的最左邊的節點,end()迭代器指向紅黑樹的最右邊的節點。另外這個小程式還說明了重複插入無效。

順序刪除

刪除1-100間的奇數或偶數:

#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
using namespace std;
int main()
{
    set<int>s;
    for(int i=100; i; i--)
        s.insert(i);
    set<int>::iterator it;
    for (it=s.begin(); it!=s.end(); it++)
    {
        cout<<*it<<" ";
    }
    cout<<"\n*********"<<endl;
    for (it=s.begin(); it!=s.end(); it++)
    {
        if(*it&1)
            s.erase(it);
    }
    cout<<"\n*********"<<endl;
    for (it=s.begin(); it!=s.end(); it++)
    {
        cout<<*it<<" ";
    }
    return 0;
}
此操作是能得到正確結果,但是方法正確嗎?

如果要刪除3的倍數時將會出現錯誤。

正確的應該怎麼寫呢?

#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
using namespace std;
int main()
{
    set<int>s;
    for(int i=100; i; i--)
        s.insert(i);
    set<int>::iterator it;
    for (it=s.begin(); it!=s.end(); it++)
    {
        cout<<*it<<" ";
    }
    cout<<"\n*********"<<endl;
    int i=0;
    for (it=s.begin(); it!=s.end(); it++)
    {
        i++;
        if((*it)%3==0)
            s.erase(it++);
        else
            it++;
    }
    cout<<"\n*********"<<endl;
    for (it=s.begin(); it!=s.end(); it++)
    {
        cout<<*it<<" ";
    }
    return 0;
}

原因:STL/C++__中 set(集合)  刪除元素, set的erase不會返回迭代器,這點需要注意。


相關推薦

STL-set (集合)刪除元素

set概述和vector、list不同,set、map都是關聯式容器。set內部是基於紅黑樹實現的。插入和刪除操作效率較高,因為只需要修改相關指標而不用進行資料的移動。  在進行資料刪除操作後,迭代器

坑 - stl刪除元素

iterator ima rst 技術分享 gpo 返回值 const span 返回 概述 stl中刪除元素,會使用到erase或remove,erase一般用於刪除一個或者一段範圍內的元素,而remove則可以刪除指定值的所有元素。但是在使用

STL容器刪除元素,迭代器失效

(1) vector 內部資料結構:陣列。 隨機訪問每個元素,所需要的時間為常量。 在末尾增加或刪除元素所需時間與元素數目無關,在中間或開頭增加或刪除元素所需時間隨元素數目呈線性變化。 可動態增加或減少元素,記憶體管理自動完成,但程式設計師可以使用reserve()成員函式來管理記憶體。 vector的迭代器

單詞數 (STL set集合

任務 dsm inpu 排列 結束 -c ostream ret gin 單詞數 Problem Description lily的好朋友xiaoou333近期非常空。他想了一件沒有什麽意義的事情,就是統計一篇文章裏不同單詞的總數。以下你的任務是幫助xiaoou3

關於List集合remove刪除元素的問題

 執行如下程式碼: public static void test1(){ List<String> list = new ArrayList<String>(); list.add("abc"); list.add("abc"); list.add

集合刪除元素安全的方法

文章目錄 題目 題目 list是一個ArrayList的物件,哪個選項的程式碼填寫到//todo delete處,可以在Iterater遍歷的過程中正確並安全的刪除一個list中儲存的物件 ic static void main(Stri

二叉樹刪除元素

二叉樹刪除一個節點分兩種情況, 第一種:要刪除的節點有左子樹 第二種:要刪除的節點沒有左子樹 假定有以下的二叉樹資料: 現在需要刪除3這個元素,這屬於第一種情況:需要把待刪除的節點的左子樹下的最右邊的資料給拿出來放到3這個位置 ,如果刪除30就是屬於第二種情況了,直接刪除就行了 程式

STL——set(集合)

#include <set>set<int> s;每個元素最多出現一次成員函式:begin()--返回指向第一個元素的迭代器;clear()--清楚所有元素;count()--返回某元素的個數;empty()--如果為空返回true;end()--返回

Java中按次序輸出Set集合中的元素

注意:這裡Set集合中放入的是String型別,假如我們放入一個自己定義的類例項的時候,比如Person類例項,這時候我們要自己重新hashcode和equal方法,用自己的關鍵欄位來重寫,因為當使用HashSet時,hashCode()方法就會得到呼叫,判斷已經儲存在集合中的物件的hash code值是否

STL set 集合裡面不能放結構體麼?

肯定可以,C++的設計哲學之一就是使得程式在對待自定義型別時和內建型別必須是一致的(甚至自定義型別的支援更好)。所以,肯定是你程式的問題,如下:《C++標準程式庫》中明確指出:“只要是assignable、copyable、comparable(根據某個排序準則)的型別T,

遍歷集合刪除元素,丟擲java.util.ConcurrentModificationException的解決辦法

遍歷集合刪除其中的元素時可能會丟擲java.util.ConcurrentModificationException異常。 下面的程式碼就會丟擲異常: 1: for (String s : map.keySet()) { 2: if ("val".

如何邊遍歷集合刪除元素--使用Iterator中的remove()方法

在遍歷集合時,想將符合條件的某些元素刪除,開始是用了下面的方法 public static void main(String[] args) throws UnsupportedEncodingException { List<String> list =

Java中集合迴圈刪除元素的問題

1、在一個迴圈中刪除一個列表中的元素 思考下面這一段在迴圈中刪除多個元素的的程式碼 Java程式碼 ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c"

C++ STL Set 集合

class div 模板 enc 第一個元素 union inline std left 前言set是STL中的一種關聯容器。集合具有無序性,互異性等特點。熟練使用STL中的set模板類,可以比較簡單的解決一些編程問題。關聯容器:元素按照關鍵字來保存和訪問,STL中的map

java中迴圈遍歷刪除List和Set集合元素的方

1.異常java一邊遍歷一邊刪除集合中的元素會報異常ConcurrentModificationException 2.正確的做法如下:   package list; import java.util.*; public class Demo { public

刪除陣列中重複元素 (使用stl::set)

/*  *程式作用刪除數中重複的元素,先使用set 遍歷一次陣列,然後在使用兩個指標,以及set查重,  *去重複之後使用0填補多餘空間  *複雜度 O(NlogN)  *空間複雜度 O(N) */ #include<iostream> #include<

Java學習容器上(Collection介面常用方法,Iterator介面,使用foreach迴圈遍歷Collection集合元素,Set集合通用知識(Hashset類,hashcode()與Lin

1.容器API的類圖結構如下: JAVA的集合類是一種特別有用的工具類,它可以用於儲存數量不等的多個物件,並可以實現常用資料結構,如棧,佇列等,除此之外,JAVA集合還可用於儲存具有對映關係的關聯陣列。 JAVA的集合大致上可分為:Set,List和Map三

Java集合List遍歷找到匹配元素刪除方法總結

問題:在我們使用java開發的過程中可能會遇到這樣的問題,刪除List集合中與已知元素 相同的所有元素; 比如下面這個需求: 刪除List集合中字串為“edf”的所有記錄 案例: 方案一:你可能回想到使用forEach遍歷,找到匹配的

JAVA學習路---刪除集合中的元素

1.有的時候在做業務邏輯處理的時候, 我們需要刪除集合中的元素。可是如何按照正常的邏輯進行刪除,往往達不到預期的效果,那就是報錯。以下展示通過foreach迴圈進行元素的刪除,會出現如下錯誤。 程式碼展示: public static void main(String[]

C#集合集(set)

ted var 信息 reac rar ber tor his red   包含不重復元素的集合稱為“集(set)”。.NET Framework包含兩個集HashSet<T>和SortedSet<T>,它們都實現ISet<T>接口。H