Data Structures in C++:棧和隊列的數組實現

順序棧

在這裏插入圖片描述

  • 預先分配一塊連續的內存用於存放棧中的元素,並設棧頂指針top 指示棧頂元素;
  • 初始值 top = -1
  • 入棧/出棧後,top++ / top--
  • top == -1時,爲空棧;
  • top == MAX_SIZE-1時,棧溢出,需要內存擴容

棧聲明:

template <class T>
class MyStack
{
public:
    MyStack(int capacity = DEFAULT_CAPACITY);           // 構造函數
    MyStack(const MyStack<T>& other);                   // 複製構造函數
    ~MyStack();                                         // 析構函數
    MyStack<T>& operator=(const MyStack<T>& other);     // 賦值運算
    T& top() const;                                     // 返回棧頂元素
    bool empty() const;                                 // const修飾表明只讀取數據成員
    int size() const;                                   // 返回元素個數
    void push(const T& item);                           // 壓棧
    void pop();                                         // 出棧
    void emplace(const T& item);                        // 玄學壓棧,不作實現
    void swap(MyStack& other);                          // 交換

private:
    T* stack;           // 棧容器
    int capacity;       // 當前容量
    int topIndex;       // 棧頂索引
    void expand();      // 容量擴充
};

棧實現:

template<class T>
inline MyStack<T>::MyStack(int _capacity) : capacity(_capacity)
{
    if (capacity <= 0) throw "stack capacity must be >0";
    stack = new T[capacity];
    topIndex = -1;
}

template<class T>
inline MyStack<T>::MyStack(const MyStack<T>& other)
{
    *this = other;
}

template<class T>
inline MyStack<T>::~MyStack()
{
    delete[] stack;
    stack = nullptr;
}

template<class T>
inline MyStack<T>& MyStack<T>::operator=(const MyStack<T>& other)
{
    delete[] stack;
    topIndex = other.topIndex;
    capacity = other.size();
    stack = new T[capacity];
    std::copy(other.stack, other.stack + other.size(), stack);
    return *this;
}

template<class T>
inline bool MyStack<T>::empty() const
{
    return -1 == topIndex;
}

template<class T>
inline int MyStack<T>::size() const
{
    return topIndex + 1;
}

template<class T>
inline T& MyStack<T>::top() const
{
    if (empty()) throw "ERROR: Stack is empty";
    return stack[topIndex];
}

template<class T>
inline void MyStack<T>::push(const T& item)
{
    if (topIndex == capacity - 1)
        expand();
    stack[++topIndex] = item;
}

template<class T>
inline void MyStack<T>::pop()
{
    if (empty()) throw "Stack is empty. Delete failed.";
    stack[topIndex--].~T();  // 指針遞減,成員析構
}

template<class T>
inline void MyStack<T>::emplace(const T& item)
{
    push(item);
}

template<class T>
inline void MyStack<T>::swap(MyStack& other)
{
    MyStack<T> temp(other);
    other = *this;
    *this = temp;
}

template<class T>
inline void MyStack<T>::expand()
{
    capacity *= 2;
    T* temp = new T[capacity];
    std::copy(stack, stack + this->size(), temp);
    delete[] stack;
    stack = temp;
}

順序隊列

在這裏插入圖片描述

  • 預先分配一塊連續的存儲單元存放隊列中的元素,並設隊頭指針front 指示隊頭元素、隊尾指針rear指示隊尾元素的下一個位置;
  • 初始值 front = rear = 0
  • 入隊/出隊後,rear++ / front++
  • front == rear時,隊列爲空;
  • rear==MAX_SIZE時,隊列已滿(假溢出),需要內存擴容,但此時可能存在內存閒置。

循環隊列

循環隊列是一種改進的順序隊列結構,操作表現同樣基於 FIFO(先進先出)原則,但隊尾被連接在隊首之後形成一個循環,也被稱爲“環形緩衝器”。
優點是能夠允許利用之前釋放的空間,解決“假溢出”問題。

在這裏插入圖片描述

  • 爲了更好地判斷循環隊列的隊空和隊滿邊界,需要犧牲 最後一個 存儲單元
  • 預先分配一塊連續的存儲單元存放隊列中的元素,並設隊頭指針front 指示隊頭元素、隊尾指針rear指示隊尾元素的下一個位置;
  • 初始值 front = rear = 0
  • 入隊包括迴繞入隊rear = (rear+1) % MAX_SIZE
  • 出隊包括迴繞出隊 front = (front+1) % MAX_SIZE
  • front == rear時,隊列爲空;
  • (rear+1) % MAX_SIZE == front時,隊列溢出,需要內存擴容
/*********************************************************
 * Data Structures in C++
 * @file    MyQueue.h
 * @author  QCH
 * @date    2020/03/19
 * @brief   順序隊列的實現,注意迴繞的處理方式,空出隊頭位置
 * Copyright (c) 2016-2020. All rights reserved.
 *********************************************************/

#pragma once

#define DEFAULT_CAPACITY  10 

template<class T>
class MyQueue
{
public:
    MyQueue(int _capacity = DEFAULT_CAPACITY);
    MyQueue(const MyQueue<T>& other);
    ~MyQueue();
    MyQueue<T>& operator=(const MyQueue<T>& other);
    T& front();
    T& back();
    bool empty();
    int size();
    void push(const T& item);
    void pop();
    void emplace(const T& item);
    void swap(const MyQueue<T>& other);

private:
    T* queue;           // 隊列容器
    int counter;        // 計數
    int capacity;       // 容量
    int frontIndex;     // 前項索引
    int backIndex;      // 後項索引
    void expand();      // 容量擴充
};

/*********************************************************************
 * 由於編譯器只能通過include“看到”頭文件而找不到模板實現代碼
 * 爲避免產生鏈接問題, 模板類的聲明和定義必須放在一起
 *********************************************************************/

template<class T>
inline MyQueue<T>::MyQueue(int _capacity) : capacity(_capacity)
{
    if (capacity <= 0) throw "Capacity must be >0";
    queue = new T[capacity];
    frontIndex = backIndex = counter = 0;
}

template<class T>
inline MyQueue<T>::MyQueue(const MyQueue<T>& other)
{
    *this = other;
}

template<class T>
inline MyQueue<T>::~MyQueue()
{
    delete[] queue;
    queue = nullptr;
}

template<class T>
inline MyQueue<T>& MyQueue<T>::operator=(const MyQueue<T>& other)
{
    delete[] queue;
    capacity = other.capacity;
    queue = new T[capacity];
    std::copy(other.queue, other.queue + capacity, queue);
    frontIndex = other.frontIndex;
    backIndex = other.backIndex;
    counter = other.counter;
    return *this;
}

template<class T>
inline T& MyQueue<T>::front()
{
    if (empty()) throw "ERROR: Queue is empty!";
    return queue[(frontIndex + 1) % capacity];
}

template<class T>
inline T& MyQueue<T>::back()
{
    if (empty()) throw "ERROR: Queue is empty!";
    return queue[backIndex];
}

template<class T>
inline bool MyQueue<T>::empty()
{
    return frontIndex == backIndex;
}

template<class T>
inline int MyQueue<T>::size()
{
    return counter;
}

template<class T>
inline void MyQueue<T>::push(const T& item)
{
    if ((backIndex + 1) % capacity == frontIndex) // 隊列滿了
    {
        expand();
        frontIndex = 0;
        backIndex = capacity - 1;
        capacity *= 2;
    }

    //if (backIndex == capacity - 1)
    //    backIndex = 0;  
    //else
    //    backIndex++;
    backIndex = (backIndex + 1) % capacity;     // 迴繞的高水平寫法
    queue[backIndex] = item;
    counter++;
}

template<class T>
inline void MyQueue<T>::pop()
{
    if (empty()) throw "ERROR: Queue is empty!";
    frontIndex = (frontIndex + 1) % capacity;    // 迴繞的高水平寫法
    queue[frontIndex].~T();
    counter--;
}

template<class T>
inline void MyQueue<T>::emplace(const T& item)
{
    push(item);
}

template<class T>
inline void MyQueue<T>::swap(const MyQueue<T>& other)
{
    MyQueue<T> temp(other);
    other = *this;
    *this = temp;
}

template<class T>
inline void MyQueue<T>::expand()
{
    T* temp = new T[capacity * 2];
    if (frontIndex < backIndex)
        std::copy(queue, queue + capacity, temp);
    else
    {
        std::copy(queue + frontIndex, queue + capacity, temp);
        std::copy(queue, queue + frontIndex, temp + capacity - frontIndex);
    }
    delete[] queue;
    queue = temp;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章