順序棧
- 預先分配一塊連續的內存用於存放棧中的元素,並設棧頂指針
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;
}