数据结构实现 1.2:数组栈(C++版)

本文详细介绍了如何使用C++实现基于动态数组的数据结构——数组栈,包括概念、基本操作(入栈、出栈、查找)的程序实现,算法复杂度分析以及完整代码展示。栈作为一种后进先出(LIFO)的数据结构,通过抽象类定义操作接口,并利用动态数组的扩容和缩容特性实现高效操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 概念及基本框架

可以看做一种特殊的 数组 ,所以我使用第一节实现的 动态数组 来实现栈这种数据结构。当然,栈也可以通过其他方式来实现。因为该栈是通过动态数组实现的,所以称之为 数组栈

数组栈
栈的结构如上图所示,可知栈的基本特性如下:
1.栈顶栈底 两端。
2.入栈出栈 操作只能从 栈顶 进行。
3.后 入栈 的先 出栈 ,即 后进先出(Last In First Out),LIFO
还有一个隐含特性,栈可以自行 扩容(缩容),而不需要用户关心,很显然,动态数组已经满足了这个要求。
由此可见,栈的操作并不多,我使用了一个由 纯虚函数 构成的 抽象类 作为一个接口来定义这些操作。具体代码如下:

template <class T>
class Stack{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	virtual void print() = 0;
	//入栈操作
	virtual void push(T num) = 0;
	//出栈操作
	virtual void pop() = 0;
	//获得栈顶元素
	virtual T peek() = 0;
};

下面只需要通过继承 抽象类,并且重写 纯虚函数 ,就可以完成 数组栈 的实现。数组栈类的框架如下:

template <class T>
class ArrayStack : public Stack<T>{
public:
	ArrayStack(int len = initialLen){
		Array<T> *p= new Array<T>(len);
		arr = p;
	}
	...
private:
	Array<T> *arr;
};

这个类内部定义一个动态数组类对象,为了保护数据,把它放在 private 部分,构造函数 ArrayStack 底层调用的就是 Array 的构造函数。用户在构造函数中也可以指定栈的大小。(默认是10)为了兼容更多类型,这里使用了泛型的概念。

2. 基本操作程序实现

2.1 入栈操作

template <class T>
class ArrayStack : public Stack<T>{
public:
	...
	//入栈操作
	void push(T num){
		arr->addLast(num);
	}
	...
};

入栈操作使用了动态数组的增加最后一个元素的操作来实现。这里动态数组内部已经提供了扩容操作。

2.2 出栈操作

template <class T>
class ArrayStack : public Stack<T>{
public:
	...
	//出栈操作
	void pop(){
		arr->removeLast();
	}
	...
};

出栈操作使用了动态数组的删除最后一个元素的操作来实现。这里动态数组内部已经提供了缩容操作。

2.3 查找操作

template <class T>
class ArrayStack : public Stack<T>{
public:
	...
	T peek(){
		return arr->get(arr->size() - 1);
	}
	...
};

因为栈只能获得栈顶元素,所以这里的查找操作也非常简单。

2.4 其他操作

template <class T>
class ArrayStack : public Stack<T>{
public:
	...
	int size(){
		return arr->size();
	}
	bool isEmpty(){
		return arr->size() == 0;
	}
	void print(){
		cout << "ArrayStack: ";
		cout << "Size = " << arr->size() << endl;
		cout << '[';
		for (int i = 0; i < arr->size(); ++i){
			cout << arr->get(i);
			if (i != arr->size() - 1){
				cout << ',';
			}
		}
		cout << "]top" << endl;
	}
	...
};

3. 算法复杂度分析

3.1 入栈操作

函数最坏复杂度平均复杂度
pushO(1+n) = O(n)O(1+1) = O(1)

最坏复杂度 O(1+n) 中第一个 1 是指元素移动操作,第二个 n 是指动态数组中的 resize 函数,以下同理。
入栈可能会引发扩容操作,平均而言,每增加 n 个元素,会扩展一次,会发生 n 个元素的移动,所以平均下来是 O(1)

3.2 出栈操作

函数最坏复杂度平均复杂度
popO(1+n) = O(n)O(1+1) = O(1)

3.3 查找操作

函数最坏复杂度平均复杂度
peekO(1)O(1)

总体情况:

操作时间复杂度
O(1)
O(1)
O(1)

由此可以看出,栈操作都是 O(1) 级别的时间复杂度。
注:这里并没有改的操作,如果更改,需要先出栈,再入栈。

4. 完整代码

动态数组类 代码:

#ifndef __ARRAY_H__
#define __ARRAY_H__

using namespace std;

const int initialLen = 10;
template <class T>
class Array{
public:
	Array(int len = initialLen){
		T *p = new T[len];
		m_data = p;
		m_capacity = len;
		m_size = 0;
	}
	int capacity(){
		return m_capacity;
	}
	int size(){
		return m_size;
	}
	void resize(int len){
		T *p = new T[len];
		for (int i = 0; i < m_size; ++i){
			p[i] = m_data[i];
		}
		delete[] m_data;
		m_data = p;
		m_capacity = len;
	}
	bool isEmpty(){
		return m_size == 0;
	}
	void print(){
		cout << "Array: ";
		cout << "Capacity = " << m_capacity << ", " << "Size = " << m_size << endl;
		cout << '[';
		for (int i = 0; i < m_size; ++i){
			cout << m_data[i];
			if (i != m_size - 1){
				cout << ',';
			}
		}
		cout << ']' << endl;
	}
	//增加操作
	void add(int index, T num);
	void addFirst(T num);
	void addLast(T num);
	//删除操作
	T remove(int index);
	T removeFirst();
	T removeLast();
	void removeElement(T num);
	//修改操作
	void set(int index, T num);
	//查找操作
	T get(int index);
	int find(T num);
	bool contains(T num);
private:
	T *m_data;       //数组数据
	int m_capacity;  //数组容量
	int m_size;      //数组大小
};

template <typename T>
void Array<T>::add(int index, T num){
	if (index < 0 || index > m_size){
		cout << "添加位置非法!" << endl;
		return;
		//throw 0;  //这里可以使用抛异常,下面也可以
	}
	if (m_size >= m_capacity){
		resize(2 * m_capacity);
	}
	for (int i = m_size; i > index; --i){
		m_data[i] = m_data[i - 1];
	}
	m_data[index] = num;
	m_size++;
}
template <class T>
void Array<T>::addFirst(T num){
	add(0, num);
}
template <class T>
void Array<T>::addLast(T num){
	if (m_size >= m_capacity){
		resize(2 * m_capacity);
	}
	m_data[m_size] = num;
	m_size++;
}

template <class T>
T Array<T>::remove(int index){
	if (index < 0 || index >= m_size){
		cout << "删除位置非法!" << endl;
		return NULL;
	}
	T res = m_data[index];
	m_size--;
	for (int i = index; i < m_size; ++i){
		m_data[i] = m_data[i + 1];
	}
	if (m_size < m_capacity / 4){
		resize(m_capacity / 2);
	}
	return res;
}
template <class T>
T Array<T>::removeFirst(){
	T res = m_data[0];
	remove(0);
	return res;
}
template <class T>
T Array<T>::removeLast(){
	if (m_size == 0){
		cout << "删除位置非法!" << endl;
		return NULL;
	}
	m_size--;
	if (m_size < m_capacity / 4){
		resize(m_capacity / 2);
	}
	return m_data[m_size];
}
template <class T>
void Array<T>::removeElement(T num){
	int flag = find(num);
	if (flag != -1){
		remove(flag);
	}
}

template <class T>
void Array<T>::set(int index, T num){
	if (index < 0 || index >= m_size){
		cout << "修改位置非法!" << endl;
		return;
	}
	m_data[index] = num;
}

template <class T>
T Array<T>::get(int index){
	if (index < 0 || index >= m_size){
		cout << "访问位置非法!" << endl;
		return NULL;
	}
	return m_data[index];
}
template <class T>
int Array<T>::find(T num){
	for (int i = 0; i < m_size; ++i){
		if (m_data[i] == num){
			return i;
		}
	}
	return -1;
}
template <class T>
bool Array<T>::contains(T num){
	for (int i = 0; i < m_size; ++i){
		if (m_data[i] == num){
			return true;
		}
	}
	return false;
}

#endif

抽象类 接口代码:

#ifndef __STACK_H__
#define __STACK_H__

template <class T>
class Stack{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	virtual void print() = 0;
	//入栈操作
	virtual void push(T num) = 0;
	//出栈操作
	virtual void pop() = 0;
	//获得栈顶元素
	virtual T peek() = 0;
};

#endif

数组栈 代码:

#ifndef __ARRAYSTACK_H__
#define __ARRAYSTACK_H__

#include "Array.h"
#include "Stack.h"

template <class T>
class ArrayStack : public Stack<T>{
public:
	ArrayStack(int len = initialLen){
		Array<T> *p= new Array<T>(len);
		arr = p;
	}
	int size(){
		return arr->size();
	}
	bool isEmpty(){
		return arr->size() == 0;
	}
	void print(){
		cout << "ArrayStack: ";
		cout << "Size = " << arr->size() << endl;
		cout << '[';
		for (int i = 0; i < arr->size(); ++i){
			cout << arr->get(i);
			if (i != arr->size() - 1){
				cout << ',';
			}
		}
		cout << "]top" << endl;
	}
	//入栈操作
	void push(T num){
		arr->addLast(num);
	}
	//出栈操作
	void pop(){
		arr->removeLast();
	}
	//获得栈顶元素
	T peek(){
		return arr->get(arr->size() - 1);
	}
private:
	Array<T> *arr;
};

#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九霄星河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值