Vector和迭代器代码实现

2,093 阅读5分钟

线性表分为

  • 链表

    • list:链表(内存不一定连续,不可以通过下标访问,方便添加删除)
  • 顺序表

    • vector:顺序表(内存连续,可以通过下标访问,方便随机访问),可变大小的动态数组
    • 添加元素:push_back()/insert()
    • 删除元素:pop_back()/erase()/clear()
    • 访问元素:front()/back()/at()/[]/begin()/end()

面试题

删除顺序表中的某个元素,与链表效率相同:把要删除的元素的值和最后一个元素交换,然后删除最后一个元素(无序情况下)

Vector代码实现

Vector.h

#pragma once
#include <iostream>
#include "Iterator.h"
class Vector {
public:
	//Vector();//默认构造函数
	Vector(int count = 2);
	//默认析构函数
	~Vector();
	//拷贝构造函数
	Vector(const Vector& vec);

	//添加一个元素
	void push_back(const int& val);
	//移出最后一个元素
	void pop_back();
	//返回第一个元素
	int& front();
	//返回最后一个元素
	int& back();

	//返回容器大小
	int getSize() const {
		return size;
	}

	//重载下标运算符
	int& operator[](int index) const;

	//重载赋值运算符
	Vector& operator=(const Vector&);

	//判断是否为空
	bool empty() const {
		return size <= 0;
	}
private:
	//判断是否已满
	inline bool full() const {
		return size == maxSize;
	}

	//扩容函数
	void expansion();

	//返回容器最大值
	int getMaxSize() const {
		return maxSize;
	}
public:
	//迭代器:begin/end/erase/insert
	Iterator begin()const;//返回指向第一个元素的迭代器
	Iterator end()const;//返回指向最后一个元素下一个的迭代器
	Iterator erase(Iterator currentIt);//参数是当前迭代器,返回值是指向删除的最后一个元素的下一位置的迭代器
	Iterator erase(Iterator startIt, Iterator endIt);//参数是一个区间
	Iterator insert(Iterator currentIt, const int &val);//第一个参数是当前迭代器,第二个参数是插入的值
	void insert(Iterator currentIt, int num, const int &val);
private:
	int *data;//省钱堆区连续的内存:首地址
	int size;//元素个数
	int maxSize;//最大容量

};

Vector.cpp

#include "Vector.h"
#include <string>
#include <iostream>

//默认申请2个大小的内存
Vector::Vector(int count):data(new int[count]),size(0),maxSize(count) {

}

Vector::~Vector() {
	delete[] data;
	data = nullptr;
}

/*
	重载下标运算符
*/
int& Vector::operator[](int index) const {
	if (index >= 0 && index < size) {
		return data[index];
	} else {
		std::runtime_error err("下标越界");
		throw err;
	}
}

/*
	重载赋值运算符
*/
Vector& Vector::operator=(const Vector& vec) {
	Vector temp(vec);
	return temp;
}

/*
	拷贝构造函数
*/
Vector::Vector(const Vector& vec) {
	this->maxSize = vec.getMaxSize();
	this->size = vec.getSize();
	data = new int[maxSize];
	for (int i = 0; i < vec.getSize(); i++) {
		data[i] = vec.data[i];
	}
}

/*
	动态增容
*/
void Vector::expansion() {
	//改变容量
	maxSize *= 2;
	//1.申请原先大小2倍的内存
	int *temp = new int[maxSize];
	//2.将就内存中的内容拷贝到新内存中
	//拷贝内存函数 1.目的地址, 2.原地址 3.拷贝的内存字节数
	memcpy(temp, data, size * sizeof(int));
	//3.释放就内存
	delete[] data;
	//4.data指向新内存
	data = temp;
}

/*
	插入一个元素
*/
void Vector::push_back(const int& val) {
	//判断容器是否满了
	if (full()) {
		expansion();
	}
	data[size++] = val;
}

/*
	移出最后一个元素
*/
void Vector::pop_back() {
	if (!empty()) {
		size--;
	} else {
		std::runtime_error err("容器为空,操作异常");
		throw err;
	}
}

/*
	返回最第一个元素
*/
int& Vector::front() {
	if (size > 0) {
		return data[0];
	} else {
		std::runtime_error err("容器为空,操作异常");
		throw err;
	}
}

/*
	返回最后一个元素
*/
int& Vector::back() {
	if (size > 0) {
		return data[size - 1];
	} else {
		std::runtime_error err("容器为空,操作异常");
		throw err;
	}
}

/*
	返回迭代器起始位置
*/
Iterator Vector::begin()const {
	return Iterator(data);
}
/*
	返回迭代器末尾位置
*/
Iterator Vector::end()const {
	return Iterator(data + size);
}

/*
	根据当前迭代器位置删除值
*/
Iterator Vector::erase(Iterator currentIt) {
	Iterator it(data);
	int i = 0;
	while ((it + i++) != currentIt);
	for (int j = i; j < size - 1; j++) {
		data[j] = data[j + 1];
	}
	size--;
	return Iterator(data + i);
}

/*
	删除一个区间
*/
Iterator Vector::erase(Iterator startIt, Iterator endIt) {
	Iterator it = startIt;
	int count = 0;
	do {
		it = erase(it);
		count++;
	} while (it != (endIt - count));

	return it;
}

/*
	在指定位置currentIt前插入值为val的元素,返回指向这个元素的迭代器
*/
Iterator Vector::insert(Iterator currentIt, const int &val) {
    //添加前先判断是否满了
	if (full()) {
		expansion();
	}
	Iterator it(data);
	int i = -1;
	//根据迭代器找到对应的下标
	while ((it + ++i) != currentIt);
	for (int j = size; j >= i; j--) {
		data[j] = data[j - 1];
	}
	data[i] = val;
	size++;
	//返回迭代器对象
	return Iterator(data + i);
}

/*
	在指定位置currentIt前插入num个值为val的元素
*/
void Vector::insert(Iterator currentIt, int num, const int &val) {
	while (num-- > 0) {
		currentIt = insert(currentIt, val);
	}
}

迭代器

迭代器:类似于指针,指向某一个元素:

  • 数据成员
  • 四大默认成员函数
  • 成员函数
    • 自增自减++/--
    • *:去内容
    • ==/!=
    • +/-
    • ->

Iterator.h

class Iterator {
public:
	Iterator(int* element = nullptr);
	~Iterator();
	//重载赋值运算符
	//Iterator& operator=(const Iterator& it);
	//前置++:先自增再运算(返回本身)
	Iterator& operator++();
	//后置++:先运算再自增(返回没有自增之前的临时变量)
	Iterator operator++(int);
	//前置--:
	Iterator& operator--();
	//后置--:
	Iterator operator--(int);
	//重载*运算符
	int& operator*() const;
	//常引用的作用:防止调用拷贝构造函数,提高效率
	//重载!=运算符
	bool operator!=(const Iterator &it)const;
	//重载==运算符
	bool operator==(const Iterator &it)const;
	//重载+运算符
	Iterator operator+(int index)const;	
	//重载-运算符
	Iterator operator-(int index)const;

private:
	int* element;
};

IIrator.cpp

#include "Iterator.h"
#include <assert.h>
#include <string.h>
Iterator::Iterator(int* element):element(element) {

}
Iterator::~Iterator(){
	element = nullptr;
}

//前置++
Iterator& Iterator::operator++() {
	this->element++;
	return *this;
}
//后置++
Iterator Iterator::operator++(int val) {
	Iterator temp = *this;
	this->element++;
	return temp;
}
//前置--:
Iterator& Iterator::operator--() {
	this->element--;
	return *this;
}
//后置--:
Iterator Iterator::operator--(int) {
	Iterator temp = *this;
	this->element--;
	return temp;
}

int& Iterator::operator*() const {
	return *element;
}

bool Iterator::operator!=(const Iterator &it)const {
	return element != it.element;
}

bool Iterator::operator==(const Iterator &it)const {
	return element == it.element;
}

Iterator Iterator::operator+(int index)const {
	//设置断言判断不为空
	assert(element + index != nullptr);
	return Iterator(element + index);
	//return *this;
}

Iterator Iterator::operator-(int index)const {
	assert(element - index != nullptr);
	return Iterator(element - index);
}

//Iterator& Iterator::operator=(const Iterator& it) {
//	int count = 0;
//	while ((it + count++) != nullptr);
//	// 避免自赋值
//	if (this != &it) {
//		// 避免内存泄露
//		if (element != nullptr) {
//			delete[] element;
//			element = nullptr;
//		}
//		element = new int[count];
//		memcpy(element, it.element, count * sizeof(int));
//	}
//
//	return *this;
//}