技术分享2026-08-21蔡明思
循环数组
循环数组作为数组的一种基本变形,是可以在某些方面有效提升数组的效率。
数组本身是不能成为环形的,但是可以通过代码让他成为逻辑上环形的。主要就是通过维护两个指针,一个start和一个end,用于记录逻辑上数组的开头和结尾。再加上求模的方式,就可以实现一个循环数组。
#include <iostream>
#include <vector>
using namespace std;
vector<int> arr = {1,2,3,4,5};
int i = 0;
//无限循环的数组
while(i<arr.size())
{
cout<< arr[i] <<endl;
i = (i+1)%arr.size();
}
当i到达数组末尾元素时,i+arr.length 取模后又为0,又倒回数组头部,所以这个数组是无限循环的。
实现过程
#include <iostream>
#include <stdexcept>
#include <vector>
#include <ostream>
using namespace std;
template <typename T> // 泛型类模板
class CycleArray {
vector<T> arr;
int start;
int end;
int count;
void resize(int newSize){
vector<T> newArr(newSize);
for(int i =0;i<count;i++)
{
newArr[i] = arr[(start+i)%arr.size()];
}
arr = std::move(newArr);
start = 0;
end = count;
}
public:
CycleArray() : CycleArray(1){}
explicit CycleArray(int size) : arr(size),start(0),end(0),count(0){}
void addFirst(const T &val){
if(isFull())
{
resize(arr.size()*2);
}
start = (start - 1 + arr.size()) % arr.size();
arr[start] = val;
count++;
}
void addLast(const T &val){
if(isFull())
{
resize(arr.size()*2);
}
arr[end] = val;
end = (end + 1) % arr.size();
count++;
}
void removeFirst(){
if(isEmpty())
{
throw runtime_error("Array is empty");
}
arr[start] = T();
start = (start + 1) % arr.size();
count--;
if(count<arr.size()/4 && count >0)
{
resize(arr.size()/2);
}
}
void removeLast(){
if(isEmpty()){
throw runtime_error("Array is empty");
}
end = (end - 1 + arr.size()) % arr.size();
arr[end] = T();
count--;
if(count<arr.size()/4 && count >0)
{
resize(arr.size()/2);
}
}
T getFirst() const{
if(isEmpty())
{
throw runtime_error("Array is empty");
}
return arr[start];
}
T getLast() const{
if(isEmpty())
{
throw runtime_error("Array is empty");
}
return arr[(end - 1 + arr.size()) % arr.size()];
}
bool isFull() const{
return count == arr.size();
}
bool isEmpty() const{
return count == 0;
}
int size() const{
return count;
}
void printDetails() const {
std::cout << "--- 内部调试信息 ---" << std::endl;
std::cout << "总容量 (capacity): " << arr.size() << std::endl;
std::cout << "元素数量 (count): " << count << std::endl;
std::cout << "start 指针: " << start << ", end 指针: " << end << std::endl;
std::cout << "物理数组内容: [ ";
for (int i = 0; i < arr.size(); i++) {
// 标记哪些位置是当前队列中的元素
bool is_in_queue = false;
if (count > 0) {
// 判断 i 是否在 [start, end) 范围内(考虑循环情况)
if (start < end) {
if (i >= start && i < end) is_in_queue = true;
} else { // 跨越边界的情况
if (i >= start || i < end) is_in_queue = true;
}
}
if (is_in_queue) std::cout << arr[i] << " ";
else std::cout << "(" << arr[i] << ") "; // 括号表示无效/空闲区域
}
std::cout << "]" << std::endl;
}
};