英文:
Complexity of Deque implementation
问题
我认为这个复杂性主要是由于 balanceVectors()
函数引起的,该函数需要从两个向量的开头删除和插入元素。然而,我不确定如何使用摊销常数时间来实现这一点。任何有关降低复杂性的帮助将不胜感激。
Here is the translated code portion:
我认为这个复杂性主要是由于 `balanceVectors()` 函数引起的,该函数需要从两个向量的开头删除和插入元素。然而,我不确定如何使用摊销常数时间来实现这一点。任何有关降低复杂性的帮助将不胜感激。
Please note that the code itself remains in English, as programming code is typically written in English for consistency and compatibility. If you have any specific questions or need further assistance with the code, please feel free to ask.
英文:
I was asked to implement a deque in a programming course using two vectors (frontVector and backVector), which should contain half of the data of the deque. However, my implementation seems to be taking so much runtime. Here is the template with all functions included.
template <typename T>
MyDeque<T>::MyDeque() {}
template <typename T>
MyDeque<T>::MyDeque(int n) : frontVector(n/2), backVector(n/2 + n%2) {}
template <typename T>
MyDeque<T>::MyDeque(std::initializer_list<T> vals) : frontVector(), backVector(int(vals.size())) {
int i = 0;
for (const auto& item : vals) {
backVector[i++]=item;
}
balanceVectors();
}
template <typename T>
void MyDeque<T>::push_back(T val) {
backVector.push_back(val);
balanceVectors();
}
template <typename T>
void MyDeque<T>::push_front(T val) {
frontVector.insert(frontVector.begin(),val);
balanceVectors();
}
template <typename T>
void MyDeque<T>::pop_back() {
if (!backVector.empty()) {
backVector.pop_back();
balanceVectors();
}
else if (!frontVector.empty()) {
frontVector.pop_back();
balanceVectors();
}
}
template <typename T>
void MyDeque<T>::pop_front() {
if (!frontVector.empty()) {
frontVector.erase(frontVector.begin());
balanceVectors();
}
else if (!backVector.empty()) {
backVector.pop_back();
balanceVectors();
}
}
template <typename T>
T& MyDeque<T>::back() {
if (!backVector.empty()) {
return backVector.back();
}
return frontVector.front();
}
template <typename T>
const T& MyDeque<T>::back() const {
if (!backVector.empty()) {
return backVector.back();
}
return frontVector.front();
}
template <typename T>
T& MyDeque<T>::front() {
if (!frontVector.empty()) {
return frontVector.front();
}
return backVector.back();
}
template <typename T>
const T& MyDeque<T>::front() const {
if (!frontVector.empty()) {
return frontVector.back();
}
return backVector.front();
}
template <typename T>
bool MyDeque<T>::empty() const {
return frontVector.empty() && backVector.empty();
}
template <typename T>
int MyDeque<T>::size() const {
return int(frontVector.size()) + int(backVector.size());
}
template <typename T>
T& MyDeque<T>::operator[](int i) {
if (i < static_cast<int>(frontVector.size())) {
return frontVector[i];
}
else {
return backVector[i - frontVector.size()];
}
}
template <typename T>
const T& MyDeque<T>::operator[](int i) const {
if (i < static_cast<int>(frontVector.size())) {
return frontVector[i];
}
else {
return backVector[i - frontVector.size()];
}
}
template <typename T>
void MyDeque<T>::balanceVectors() {
if (backVector.size() > frontVector.size() + 1) {
frontVector.push_back(backVector.front());
backVector.erase(backVector.begin());
}
else if (frontVector.size() > backVector.size() + 1) {
backVector.insert(backVector.begin(), frontVector.back());
frontVector.pop_back();
}
}
template class MyDeque<int>;
template class MyDeque<double>;
template class MyDeque<char>;
template class MyDeque<std::string>;
I think that this complexity is because of the balanceVectors() function, which requires removing and inserting elements from the beginning of both vectors. However, I am not sure how can this be implemented using amortized constant time. Any help in decreasing the complexity will be appreciated.
答案1
得分: 1
你有两个问题:
-
由于你只能高效地推送到向量的末尾,所以你需要以与deque相对于deque相反的顺序表示deque的前半部分,以便在内部向前推送时将其推送到向量的后面。
-
由于重新平衡涉及O(n)的复制,
英文:
You have two problems:
-
Since you can only efficiently push to the end of a vector, you need
to represent the front part of the deque in reverse order
relative to the deque so that when you push to the front internally you are
pushing to the back of a vector. -
Since rebalancing involves O(n) copying you should not rebalance unless you have to. Never rebalance after pushing. Only rebalance before you would have to pop from either the front vector or the back vector but can't because it is empty.
Also note that there is a symmetry to the rebalancing logic such that you rebalance by doing one copy with a reverse iterator and one copy with a forward iterator when rebalancing from front to back or from back to front.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论