📅  最后修改于: 2023-12-03 15:09:52.133000             🧑  作者: Mango
循环数组是一种特殊的数据结构,它可以在一定程度上简化程序的实现,提高程序的效率。
循环数组是一种采用环型存储结构的线性表。它的特点是将数组的头尾相接,形成一个环型结构,当数组尾部达到数组长度时,再从数组头部开始存储数据,实现了循环存储的功能。
template<class T, int size>
class CircularArray {
public:
CircularArray() {
head_ = tail_ = 0;
}
// 循环移动指针
inline int MovePointer(int p, int step) {
return ((p + step) + size) % size;
}
// 添加元素到数组尾部
void PushBack(T val) {
if (IsFull())
return;
data_[tail_] = val;
tail_ = MovePointer(tail_, 1);
}
// 删除数组尾部元素
void PopBack() {
if (IsEmpty())
return;
tail_ = MovePointer(tail_, -1);
}
// 添加元素到数组头部
void PushFront(T val) {
if (IsFull())
return;
head_ = MovePointer(head_, -1);
data_[head_] = val;
}
// 删除数组头部元素
void PopFront() {
if (IsEmpty())
return;
head_ = MovePointer(head_, 1);
}
// 获取数组尾部元素
T Back() {
if (IsEmpty())
return NULL;
return data_[MovePointer(tail_, -1)];
}
// 获取数组头部元素
T Front() {
if (IsEmpty())
return NULL;
return data_[head_];
}
// 判断数组是否为空
bool IsEmpty() {
return (head_ == tail_);
}
// 判断数组是否已满
bool IsFull() {
return (MovePointer(tail_, 1) == head_);
}
private:
int head_;
int tail_;
T data_[size];
};
在定义循环数组时,我们需要定义数组的容量大小,以及两个指针head和tail,用于指向数组的头部和尾部。
循环数组的元素添加与删除操作与普通的数组一样,不同的是,当数组的尾部达到数组长度时,我们需要将tail指向数组头部,实现循环存储的功能。为了实现这个功能,我们需要实现一个MovePointer函数,用于循环移动指针。
inline int MovePointer(int p, int step) {
return ((p + step) + size) % size;
}
在数组尾部添加元素时,只需将元素存储到tail所指向的数组下标处,并将tail指向下一个数组下标。删除数组尾部元素时,只需将tail指针往前移动一个数组下标。
在数组头部添加元素时,需要将head指针往前移动一个数组下标,并将元素存储到head所指向的数组下标处。删除数组头部元素时,只需将head指针往后移动一个数组下标。
此外,我们还可以提供函数获取数组头部和尾部的元素,以及判断数组是否为空或已满。
通过对循环数组的实现,我们可以看出它的优点主要在于,它可以大大简化程序设计,提高程序的效率。不过,在使用循环数组时,我们需要格外注意循环数组的边界,以及循环移动指针时的处理方式。