Grundlegende C++-Vektoroperationen

Inhaltsverzeichnis

1. Einleitung

2. Definition

3. Iterator

4. Kapazitätsbetrieb

1、Größe

2、Kapazität

3、leer

4、Größe ändern

5、Reservieren

Zusammenfassung (Erweiterungsmechanismus)

5. Hinzufügen, Löschen, Überprüfen und Ändern

1、push_back & Pop zurück

2、finden

3、einfügen

4、löschen

5、tauschen

6、Operator[]


1. Einleitung

Dokumenteinführung in Vector

  1. Ein Vektor ist ein Sequenzcontainer, der ein Array variabler Größe darstellt.
  2. Ebenso wie Arrays nutzen auch Vektoren kontinuierlichen Speicherplatz zum Speichern von Elementen. Dies bedeutet, dass Sie mithilfe von Indizes auf die Elemente des Vektors zugreifen können, was genauso effizient ist wie ein Array. Aber im Gegensatz zu einem Array kann seine Größe dynamisch geändert werden und seine Größe wird automatisch vom Container verwaltet.
  3. Im Wesentlichen verwendet Vector ein dynamisch zugewiesenes Array zum Speichern seiner Elemente. Wenn neue Elemente eingefügt werden, muss die Größe des Arrays geändert werden, um den Speicherplatz zu vergrößern. Dies geschieht durch Zuweisung eines neuen Arrays und anschließendes Verschieben aller Elemente in dieses Array. Zeitlich gesehen ist dies eine relativ kostspielige Aufgabe, da die Größe des Vektors nicht jedes Mal geändert wird, wenn dem Container ein neues Element hinzugefügt wird.
  4. Vector-Speicherplatzstrategie: Vector weist etwas zusätzlichen Speicherplatz zu, um mögliches Wachstum zu berücksichtigen, da der Speicherplatz größer ist als der tatsächlich benötigte Speicherplatz. Verschiedene Bibliotheken verwenden unterschiedliche Strategien, um Platznutzung und Neuzuweisung auszugleichen. In jedem Fall sollte die Neuzuweisung jedoch in der Intervallgröße logarithmisch ansteigend erfolgen, sodass das Einfügen eines Elements am Ende in konstanter Zeit erfolgt.
  5. Daher beansprucht Vector mehr Speicherplatz, um den Speicherplatz verwalten und dynamisch und effizient wachsen zu können.
  6. Im Vergleich zu anderen dynamischen Sequenzcontainern (Deque, List und Forward_list) ist der Vektor beim Zugriff auf Elemente effizienter, und das Hinzufügen und Löschen von Elementen am Ende ist relativ effizient. Bei anderen Lösch- und Einfügevorgängen, die nicht am Ende stehen, ist die Effizienz noch geringer. Es ist besser, einheitliche Iteratoren und Referenzen zu verwenden als list und forward_list.

Verwendung von Vektoren

Wenn Sie Vector lernen, müssen Sie lernen, die Dokumentation zu überprüfen:Vector-Dokumentation, Vector ist in der Praxis sehr wichtig und wir sind damit vertraut In der Praxis genügen gemeinsame Schnittstellen.

ZweitensDefiniert

Dies sind die verschiedenen überladenen Formen des Konstruktors der Klasse „vector“ in der C++-Standardbibliothek. Nachfolgend finden Sie eine Erläuterung der einzelnen Konstruktoren:

1. Parameterloser Konstruktor: „vector()“. 

vector<int> v;
  • Erstellt ein leeres „Vektor“-Objekt, das keine Elemente enthält.

2. Konstruieren und initialisieren Sie n Werte: „vector(size_type n, const value_type& val = value_type())“.

vector<int> v1(10, 1);
  • Erstellen Sie ein „Vektor“-Objekt mit „n“ Elementen, wobei jedes Element auf „val“ initialisiert wird.
  • Optional kann ein Anfangswert „val“ bereitgestellt werden. Wenn nicht angegeben, wird der Standardkonstruktor des Standardwerttyps für die Initialisierung verwendet.

3. Verwenden Sie den Iterator für die Initialisierungskonstruktion: „vector(InputIterator first, InputIterator last)“.

string s1("hello");
vector<char> v3(s1.begin(), s1.end());
  • Erstellen Sie ein „Vektor“-Objekt und initialisieren Sie es mit Elementen im Bereich „[erster, letzter)“.
  • „first“ und „last“ sind Iteratoren, die den Bereich der zu kopierenden Elemente angeben.
  • Dieser Konstruktor ermöglicht die Verwendung eines Iterators, um einen Bereich von zu kopierenden Elementen anzugeben, bei denen es sich um ein Array, einen Container oder ein anderes iterierbares Objekt handeln kann.

4. Kopierkonstruktor: „vector(const vector& x)“ Wichtige Punkte

vector<int>v1(v);
  • Erstellt ein neues „Vektor“-Objekt, dessen Elemente mit denen eines anderen „Vektor“-Objekts „x“ identisch sind.
  • Der Kopierkonstruktor wird zum Erstellen einer Kopie verwendet. Das neue „Vektor“-Objekt ist unabhängig vom Originalobjekt und Änderungen an einem Objekt haben keine Auswirkungen auf das andere Objekt.

Nehmen wir zur Veranschaulichung ein Beispiel: Die Ausgabe ist dieselbe wie die der String-Klasse, mit drei Methoden: Bereich für [] Iterator.

void test1()
{
	//无参构造
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);

	//三种输出方式 范围for [] 迭代器
	for (auto a : v)
	{
		cout << a << " ";
	}
	cout << endl;

	for (size_t i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	//vector<int>::iterator it = v.begin();
	auto it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	
	//拷贝构造
	vector<int> copy(v);
	for (auto a : copy) 
	{
		cout << a << " ";
	}
	cout << endl;
}
void test2()
{
	//构造并初始化
	vector<int> v1(6, 6);
	for (auto a : v1)
	{
		cout << a << " ";
	}
	cout << endl;

	//迭代器
	vector<int> v2(v1.begin(), v1.end());
	for (auto b : v2)
	{
		cout << b << " ";
	}
	cout << endl;

	string s1("hello");
	vector<char> v3(s1.begin(), s1.end());
	for (auto b : v3)
	{
		cout << b << " ";
	}

}
int main()
{
	test1();
    cout << endl;
    test2();
	return 0;
}

3. Iterator

begin()/end(): Holen Sie sich den Iterator/Const_iterator der ersten Datenposition, holen Sie sich den Iterator/Const_iterator der nächsten Position der letzten Daten

rbegin()/rend():Rufen Sie den reverse_iterator der letzten Datenposition und den reverse_iterator der vorherigen Position der ersten Daten ab

Durch die Verwendung dieser Schnittstellen können iterative Operationen ausgeführt werdenvector.

  • Zum Beispiel kann die Verwendung von begin() und end() die Elemente in vector durchlaufen, während < verwendet wird a i =4> und können die Elemente in umgekehrt durchlaufen. rbegin()rend()vector
  • Bitte beachten Sie, dass für den schreibgeschützten Zugriffvector const_iterator und const_reverse_iterator verwendet werden sollten, um sicherzustellen, dass keine Änderungen vorgenommen werden.vector.
void test3()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
    //正向迭代器
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
    //反向迭代器
	vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";
		++rit;
	}
}
int main()
{
    test3();
    return 0;
}

4. Kapazitätsbetrieb

1、Größe

Ermitteln Sie die Anzahl der Daten.
int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    std::cout << "Size of vector: " << v.size() << std::endl;
    return 0;
}

2、Kapazität

KapazitätErmitteln Sie die Kapazitätsgröße.
int main() {
    std::vector<int> v;
    std::cout << "Initial capacity: " << v.capacity() << std::endl;
    for (int i = 0; i < 10; i++) {
        v.push_back(i);
        std::cout << "Capacity after pushing " << i << ": " << v.capacity() << std::endl;
    }
    return 0;
}

3、leer

Stellen Sie fest, ob es leer ist.
int main() {
    std::vector<int> v;
    std::cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << std::endl;
    v.push_back(1);
    std::cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << std::endl;
    return 0;
}

4、Größe ändern

Ändern Sie die Größe des Vektors.
void resize (size_type n, value_type val = value_type());
  1. Ändern Sie die Größe des Containers, sodass er n Elemente enthält.
  2. Wenn n kleiner ist als die aktuelle Containergröße, wird der Inhalt auf seinen ersten  reduziert n a> Elemente, überschüssige Elemente entfernen (und zerstören).
  3. Wenn n größer ist als die aktuelle Containergröße, erweitern Sie den Inhalt, indem Sie am Ende eine beliebige Anzahl von Elementen einfügen, um < Die Größe eines i=3>n  . Wenn val angegeben ist, wird das neue Element als Kopie von val
  4. Wenn n auch größer ist als die aktuelle Containerkapazität, dann Der zugewiesene Speicherplatz wird automatisch neu zugewiesen.
  5. Beachten Sie, dass diese Funktion den tatsächlichen Inhalt des Containers ändert, indem sie Elemente in den Container einfügt oder löscht.
int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    v.resize(7, 100);
    for (int i : v) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    v.resize(3);
    for (int i : v) {
        std::cout << i << " ";
    }
    return 0;
}

5、Reservieren

Ändern Sie die Kapazität des Vektors.
reserve(): Diese Methode ändert die Kapazität des Vektors. Wenn die neue Kapazität größer als die aktuelle Kapazität ist, wird der Speicher des Vektors neu zugewiesen, um die zusätzlichen Elemente aufzunehmen. Wenn die neue Kapazität kleiner als die aktuelle Kapazität ist, hat diese Methode keine Auswirkung.
int main() {
    std::vector<int> v;
    std::cout << "Initial capacity: " << v.capacity() << std::endl;
    v.reserve(10);
    std::cout << "Capacity after reserving: " << v.capacity() << std::endl;
    return 0;
}

Zusammenfassung (Erweiterungsmechanismus)

  • Wenn Sie den Kapazitätscode unter VS bzw. g++ ausführen, werden Sie feststellen, dass die Kapazität unter VS um das 1,5-fache und unter g++ um das 2-fache steigt.
  • Dieses Problem wird häufig untersucht. Gehen Sie nicht starr davon aus, dass die Vektorkapazität um das Zweifache erhöht wird. Die spezifische Erhöhung wird auf der Grundlage spezifischer Anforderungen definiert. vs ist die PJ-Version STL, g++ ist die SGI-Version STL.
  • Die Reserve ist nur für die Platzerschließung verantwortlich. Wenn Sie sicher wissen, wie viel Platz benötigt wird, kann die Reserve das Kostenproblem der Vektorexpansion lindern.
  • Die Größenänderung wird auch beim Öffnen des Speicherplatzes initialisiert, was sich auf die Größe auswirkt.

Der Standarderweiterungsmechanismus von Vector kann durch den folgenden Code beobachtet werden.

void TestVectorExpand()
{
	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making v grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

Wenn Sie die ungefähre Anzahl der im Vektor zu speichernden Elemente ermittelt haben, können Sie im Voraus genügend Platz festlegen, um das Problem der Ineffizienz durch Erweiterung beim Einfügen zu vermeiden.

void TestVectorExpandOP()
{
	vector<int> v;
	size_t sz = v.capacity();
	v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
	cout << "making bar grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

5. Hinzufügen, Löschen, Überprüfen und Ändern

1、push_back & Pop zurück

Das Einfügen und Löschen beenden
int main() {
	std::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	for (int i : v) {
		std::cout << i << " ";
	}
	cout << endl;
	v.pop_back();
	for (int i : v) {
		std::cout << i << " ";
	}
	return 0;
}

2、finden

  • Suchen Die Suchfunktion ist eine Funktion im Algorithmusmodul, mit der bestimmte Elemente in einem Vektor gefunden werden.
  • Es nimmt die Start- und Endpositionen des zu findenden Elements und gibt einen Iterator zurück, der auf dieses Element zeigt.
  • Wenn Sie beispielsweise einen Vektor v haben, können Sie std::find(v.begin(), v.end(), 5) verwenden, um die Ganzzahl 5 in v zu finden.

3、einfügen

  • Einfügen Mit der Funktion Einfügen wird ein Element vor der angegebenen Position eingefügt. Es erfordert die Angabe der einzufügenden Position und des einzufügenden Werts als Parameter.
  • Wenn Sie beispielsweise einen Vektor v haben, können Sie v.insert(v.begin() + 2, 10) verwenden, um die Ganzzahl 10 an der dritten Position von v einzufügen.

4、löschen

  • Löschen Mit der Löschfunktion wird das Element an der angegebenen Position gelöscht. Es nimmt die zu löschende Position als Parameter und gibt einen Iterator zurück, der auf die Position nach dem gelöschten Element zeigt.
  • Wenn Sie beispielsweise einen Vektor v haben, können Sie v.erase(v.begin() + 3) verwenden, um das vierte Element von v zu löschen.

Der folgende Code zeigt ein Beispiel für Einfüge-, Such- und Löschvorgänge für einen Vektor.

void test5()
{
    vector<int> v;
    v.push_back(1); // 在vector末尾插入元素1
    v.push_back(2); // 在vector末尾插入元素2
    v.push_back(3); // 在vector末尾插入元素3
    v.push_back(4); // 在vector末尾插入元素4

    for (auto e : v)
    {
        cout << e << " "; // 输出vector中的每个元素
    }
    cout << endl;
    // 在vector中查找值为2的元素
    vector<int>::iterator pos = find(v.begin(), v.end(), 2); 
    if (pos != v.end())
    {
        v.insert(pos, 20); // 在找到的位置之前插入元素20
    }

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;

    pos = find(v.begin(), v.end(), 2); // 再次查找值为2的元素
    if (pos != v.end())
    {
        v.erase(pos); // 删除找到的元素
    }

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;

    v.erase(v.begin()); // 删除vector的第一个元素

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;
}

int main()
{
    test5();
    return 0;
}

5、tauschen

  • Swap Mit der Swap-Funktion werden die Datenräume zweier Vektoren vertauscht. Es muss einen anderen Vektor als Parameter bereitstellen und den Inhalt des aktuellen Vektors mit dem Inhalt des Parametervektors austauschen.
  • Wenn Sie beispielsweise zwei Vektoren v1 und v2 haben, können Sie v1.swap(v2) verwenden, um deren Inhalte auszutauschen.
int main() {
	std::vector<int> v1 = { 1, 2, 3 };
	std::vector<int> v2 = { 4, 5, 6 };
	v1.swap(v2);
	for (int i : v1) {
		cout << i << " ";
	}
	cout << endl;
	for (int i : v2) {
		cout << i << " ";
	}
	return 0;
}

6、Operator[]

Zugriff wie Array

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}

	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/m0_73800602/article/details/134853098
Recomendado
Clasificación