1. 程式人生 > >3. 陣列實現的雙端佇列

3. 陣列實現的雙端佇列

  • 《演算法導論》10.1-5 棧插入和刪除元素只能在同一端進行,佇列的插入操作和刪除操作分別在兩端進行,與它們不同的,有一種雙端佇列(deque),其插入和刪除操作都可以在兩端進行。寫出4個時間均為O(1)的過程,分別實現在雙端佇列的兩端插入和刪除元素的操作,該佇列是用一個數組實現的。
#include <iostream>

template<typename Object>
class Deque
{
public:
    Deque()
    {
        init();
    }
    Deque(const Deque& rhs)
    {
        init();
        head = rhs.head;
        size = rhs.size;
        for(int i = head, idx; i != head + size; ++i)
        {
            idx = index(i);
            p[idx] = rhs.p[idx];
        }
    }
    Deque(Deque&& rhs):p(rhs.p),head(rhs.head),size(rhs.size)
    {
        rhs.p = nullptr;
        rhs.head = rhs.size = 0;
    }
    Deque& operator =(const Deque& rhs)
    {
        Deque copy(rhs);
        std::swap(copy.p, this->p);
        std::swap(copy.head, this->head);
        std::swap(copy.size, this->size);
        return *this;
    }
    Deque& operator =(const Deque&& rhs)
    {
        std::swap(rhs.p, this->p);
        std::swap(rhs.head, this->head);
        std::swap(rhs.size, this->size);
        return *this;
    }

    void push_front(const Object& object)
    {
        if(full())
        {
            std::cout << "overflow" << std::endl;
        }
        else
        {
            p[index(--head)] = object;
            ++size;
        }
    }

    void push_front(Object&& object)
    {
        if(full())
        {
            std::cout << "overflow" << std::endl;
        }
        else
        {
            p[index(--head)] = std::move(object);
            ++size;
        }
    }

    void push_back(const Object& object)
    {
        if(full())
            std::cout << "overflow" << std::endl;
        else
            p[index(head + size++)] = object;
    }
    void push_back(Object&& object)
    {
        if(full())
            std::cout << "overflow" << std::endl;
        else
            p[index(head + size++)] = std::move(object);
    }

    Object pop_front()
    {
        if(empty())
        {
            std::cout << "underflow" << std::endl;
            return Object();
        }
        else
        {
            Object& object = p[head];
            head = index(++head);
            --size;
            return object;
        }
    }

    Object pop_back()
    {
        if(empty())
        {
            std::cout << "underflow" << std::endl;
            return Object();
        }
        else
        {
            --size;
            return p[index(head + size)];
        }
    }

    bool empty() const {return 0 == size;}
    bool full() const  {return MAX_SIZE == size;}

private:
    static constexpr int MAX_SIZE = 4;
    Object* p;
    int     head;
    int     size;

    inline void init()
    {
        p = new Object[MAX_SIZE];
        head = size = 0;
    }

    inline int index(int i) const
    {
        if(i >= MAX_SIZE)
            i -= MAX_SIZE;
        else if(i < 0)
            i += MAX_SIZE;
        return i;
    }
};

void testDeque()
{
    using namespace std;
    struct Student
    {
        char name[10];
        int  age;
    };
    Deque<Student> dq;
    dq.push_back(Student{"Tom", 12});
    dq.push_back(Student{"Micheal", 13});
    dq.push_back(Student{"Anna", 14});
    dq.push_back(Student{"Lily", 10});
    dq.push_back(Student{"James", 19});

    decltype(dq) dq_copy(dq), dq_reverse;
    while(!dq_copy.empty())
    {
        auto stu = dq_copy.pop_front();
        dq_reverse.push_front(stu);
    }
    dq_copy.pop_front();

    while(!dq_reverse.empty())
    {
        auto stu = dq_reverse.pop_back();
        cout << "name: " << stu.name << " age: " << stu.age << endl;
    }

    decltype(dq) dq_move(std::move(dq));
}

/*output:
overflow
underflow
name: Tom age: 12
name: Micheal age: 13
name: Anna age: 14
name: Lily age: 10
*/