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;
}
发布了80 篇原创文章 · 获赞 19 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qiukapi/article/details/105314028