📜  循环数组海豚 (1)

📅  最后修改于: 2023-12-03 15:09:52.165000             🧑  作者: Mango

循环数组海豚

循环数组海豚是一个基于循环数组的数据结构,能够解决固定长度的数组在插入和删除元素时遇到的困难。循环数组海豚可以在 $O(1)$ 的时间内插入和删除元素,同时还支持随机访问。

实现

循环数组海豚的实现需要以下几个关键部分:

  • 数组空间预分配
  • 首尾指针
  • 插入与删除的算法

首先,我们需要预先分配一块连续的内存空间作为循环数组海豚的储存空间。然后,我们需要维护两个指针,一个 head 指针记录数组头的位置,一个 tail 指针记录数组尾的位置。从头部插入数据时,head 指针向前移动,并将数据存入当前位置;从尾部插入数据时,tail 指针向后移动,并将数据存入当前位置。当 head 指针和 tail 指针相遇时,说明数组已经满了,此时我们需要进行一次“循环”,将头部的数据移动到数组尾部,然后再次向头部或尾部插入数据。

template <class T, size_t N>
class CircularDolphinArray {
public:
    CircularDolphinArray() {
        _head = _tail = 0;
        memset(_data, 0, N * sizeof(T));
    }

    void push_front(const T& x) {
        if (full()) {
            roll(); // 触发循环移动
        }
        _head = (_head + N - 1) % N;
        _data[_head] = x;
    }

    void push_back(const T& x) {
        if (full()) {
            roll(); // 触发循环移动
        }
        _data[_tail] = x;
        _tail = (_tail + 1) % N;
    }

    void pop_front() {
        if (!empty()) {
            _head = (_head + 1) % N;
        }
    }

    void pop_back() {
        if (!empty()) {
            _tail = (_tail + N - 1) % N;
        }
    }

    const T& front() const {
        assert(!empty());
        return _data[_head];
    }

    const T& back() const {
        assert(!empty());
        return _data[(_tail + N - 1) % N];
    }

    bool empty() const {
        return _head == _tail;
    }

    bool full() const {
        return (_tail + 1) % N == _head;
    }

private:
    void roll() {
        T tmp[N];
        size_t cnt = 0;
        for (size_t i = _head; i != _tail; i = (i + 1) % N) {
            tmp[cnt++] = _data[i];
        }
        memcpy(_data, tmp, cnt * sizeof(T));
        _head = 0;
        _tail = cnt;
    }

private:
    T _data[N];
    size_t _head, _tail;
};
使用

使用循环数组海豚非常方便,我们可以像使用普通数组一样使用它。下面是一些示例代码:

CircularDolphinArray<int, 5> arr;

arr.push_back(1);
arr.push_back(2);
arr.push_back(3);

assert(arr.front() == 1);
assert(arr.back() == 3);
assert(!arr.empty());

arr.pop_front();
arr.pop_front();
arr.push_front(4);
arr.push_back(5);
assert(arr.front() == 4);
assert(arr.back() == 5);
assert(!arr.full());

arr.push_back(6);
assert(arr.full());

arr.pop_front();
arr.push_back(6);
assert(arr.full());

arr.pop_front();
arr.push_back(7);
assert(arr.front() == 5);
assert(arr.back() == 7);

arr.pop_back();
arr.pop_back();
arr.pop_back();
arr.pop_back();
arr.pop_back();
assert(arr.empty());
总结

循环数组海豚是一种高效的数据结构,能够在固定长度的数组中实现插入和删除操作,同时还支持随机访问。虽然它比普通的数组多了一些细节和代码,但使用起来非常简单,而且能够提升程序的性能。