C++數據結構與算法筆記 —— 順序棧

定義一個模板類 MyStack

#pragma once
#include "MyUtil.h"

using namespace std;

template<class T>
class MyStack
{
public:
	MyStack(int staticCapacity = 10);
	~MyStack();
	bool IsEmpty() const; // 檢查是否爲空
	T& Top() const;       // 返回棧頂元素
	void Push(const T& item); // 入棧
	void Pop(); // 出棧
private:
	T *stack;  
	int top;      // stack的top位置
	int capacity; // stack的容量
};

// 這裏有一個需要特別注意的地方,我在開始的時候把類裏面的函數定義向通常一樣,放在另一個cpp文件裏
// 但是報錯 : 該符號在函數 _main 中被引用
// 這裏是因爲我們用的是類模板
/* 當編譯器看到模板定義的時候,它不立即產生代碼。只有在看到用到的模板時,如果調用了函數模板或調用了類模板的對象的時候,編譯器纔會產生特定的模板實例。
一般而言,當調用函數的時候,編譯器只需要看到函數的申明。類似的,定義類類型的對象時,類定義必須可用,但成員函數的定義不是必須存在的。
因此,應該將類定義和函數申明放在頭文件中,而普通函數和類成員函數的定義放在源文件中。
但模板則不同:要進行實例化,編譯器必須能夠訪問定義模板的源代碼。
模板的具體實現被稱爲實例化或具體化,除非編譯器實現了 export 關鍵字,否則將模板成員函數放置在一個獨立的實現文件中將無法運行。
因爲模板不是函數,不能單獨編譯。模板必須與特定的模板實例化請求一起使用。爲此,最簡單的方法是將所有模板信息放在一個頭文件中。
*/
template<typename T>
MyStack<T>::MyStack(int staticCapacity) : capacity(staticCapacity)
{
	if (capacity < 1)
		throw "capacity must be > 0";
	stack = new T[capacity];
	top = -1;//此時 stack 裏面是空的,將top 默認賦值爲-1
}

template<typename T>
MyStack<T>::~MyStack()
{
	delete[] stack;
}

template<typename T>
void MyStack<T>::Push(const T& item)
{
	if (top == capacity)//當 stack 滿了
	{
		ChangeSize1D(stack, capacity, capacity * 2); // 擴容兩倍
		capacity *= 2; // 擴容之後要將 capacity更新爲新的容量大小
	}
	stack[++top] = item; // 這裏先將top自加一次, 然後將 item 賦值給 stack的top位置處,入棧到頂端
}

template<typename T>
inline bool MyStack<T>::IsEmpty() const 
{
	return top == -1;// 當top 爲-1時,棧是空的,否則不爲空
}

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

template<class T>
void MyStack<T>::Pop()
{
	if (IsEmpty())
		throw "stack is empty , can not delete";
	stack[top--].~T(); // 這裏這個 .~T() 是當模板類型是類的時候,當將頂部元素出棧,要調用該類的析構函數,當我們把對象從數組裏減少的時候,要調用析構,將對象析構
}

這裏當棧空間滿了,要擴大空間


#pragma once
#define min(a,b)    (((a) < (b)) ? (a) : (b))

template<typename T>
void ChangeSize1D(T* &a, const int oldSize, const int newSize);


template<typename T>
void ChangeSize1D(T* &a, const int oldSize, const int newSize)
{
	if (newSize < 0)
		throw "New size must be >= 0";
	T* temp = new T[newSize];
	int number = min(oldSize, newSize);
	std::copy(a, a + number, temp); // 這裏 要預定義 _SCL_SECURE_NO_WARNINGS 
	delete [] a;
	a = temp;
	temp = NULL;
}

main.cpp

#include <iostream>
#include "MyStack.h"

using namespace std;

int main()
{
	MyStack<int> sk(20);
	cout << boolalpha << sk.IsEmpty() << endl;
	sk.Push(1);
	sk.Push(2);
	cout << sk.Top() << endl;
	sk.Pop();
	cout << sk.Top() << endl;

	system("pause");
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章