《数据结构、算法与应用C++语言描述》使用C++语言实现数组栈

news2024/11/18 6:16:42

《数据结构、算法与应用C++语言描述》使用C++语言实现数组栈

定义

栈的定义

把线性表的插入和删除操作限制在同一端进行,就得到栈数据结构。因此,栈是一个后进先出(last-in-first-out,LIFO)的数据结构。

栈(stack)是一种特殊的线性表,其插入(也称入栈或压栈)和删除(也称出栈或弹栈)操作都在表的同一端进行。这一端称为栈顶(top),另一端称为栈底(bottom)。

递归工作栈

计算机是如何执行递归函数的呢?

答案是使用递归工作栈(recursionstack)。当一个函数被调用时,一个返回地址(即被调函数一旦执行完,接下去要执行的程序指令的地址)和被调函数的局部变量和形参的值都要存储在递归工作栈中。当执行一次返回时,被调函数的局部变量和形参的值被恢复为调用之前的值(这些值存储在递归工作栈的顶部),而且程序从返回地址处继续执行,这个返回地址也存储在递归工作栈的顶部。

栈的抽象数据类型

在这里插入图片描述

代码

_14stack.h

抽象类栈。

/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月13日17点38分
Last Version:			V1.0
Descriptions:			抽象类栈
*/
#pragma once
#ifndef _STACK_H_
#define _STACK_H_
/*抽象类栈*/
template<class T>
class stack
{
public:
	virtual ~stack() {}
	//返回true,当且仅当栈为空
	virtual bool empty() const = 0;
	//返回栈中元素个数
	virtual int size() const = 0;
	//返回栈顶元素的引用
	virtual T& top() = 0;
	//删除栈顶元素
	virtual T pop() = 0;
	//将元素theElement压入栈顶
	virtual void push(const T& theELment) = 0;
};
#endif

_15arrayStack.h

/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月13日17点38分
Last Version:			V1.0
Descriptions:			数组存储的栈类的头文件
*/
#pragma once
#ifndef _ARRAYSTACK_H_
#define _ARRAYSTACK_H_
#include "_1myExceptions.h"
#include "_14stack.h"
#include<iostream>
#include<sstream>
#include<cstring>
using std::ostringstream;
using std::endl;
using std::cout;
using std::istream;
using std::ostream;
using std::string;
//测试函数
void arrayStackTest();
/*
作用:将数组的长度加倍
输入:指针a指向需要改变长度的数组,oldLength表示数组原来的长度,newLength表示需要改变的新长度
结果:将数组扩容/缩容 为newLength
*/
template<class T>
void changeLength(T*& a, int oldLength, int newLength)
{
	if (newLength < 0)
		throw illegalParameterValue("new length must be >= 0");
	T* temp = new T[newLength];
	int number = min(oldLength, newLength);
	copy(a, a + number, temp);
	delete[] a;
	a = temp;
}

/*本来可以直接派生arrayList来实现,但是该方法会损失性能。*/
/*因此本节开发一个类,利用数组来包含所有的栈元素*/
template<class T>
class arrayStack :public stack<T>
{
public:
	arrayStack(int initialCapacity = 10);
	~arrayStack() { delete[] stack; }
	bool empty() const { return stackTop == -1; }
	int size() const { return stackTop + 1; }
	int capacity() const { return stackLength; }
	T& top()
	{
		if (stackTop == -1)
			throw stackEmpty();
		return stack[stackTop];
	}
	T pop()
	{
		if (stackTop == -1)
			throw stackEmpty();
		T temp = stack[stackTop];
		stack[stackTop--].~T();//T的析构函数
		while (stackTop + 1 < stackLength / 4)
		{
			changeLength(stack, stackLength, stackLength / 2);
			stackLength /= 2;
		}
		return temp;
	}
	void push(const T& theElement);
	void clear() { stackTop = -1; }
	void split(arrayStack<T>& a, arrayStack<T>& b);
	void merge(arrayStack<T>& a);

	/*重载操作符*/
	/*重载操作符[]*/
	T& operator[](int i) { return stack[i]; }

	/*友元函数*/
	friend istream& operator>> <T>(istream& in, arrayStack<T>& m);
	//输出但是不pop()元素
	friend ostream& operator<< <T>(ostream& out, arrayStack<T>& m);
private:
	int stackTop;//当前栈顶
	int stackLength;//栈容量
	T* stack;//元素数组
};
/*友元函数*/
/*>>操作符*/
template<class T>
istream& operator>>(istream& in, arrayStack<T>& m)
{
	int numberOfElement = 0;
	cout << "Please enter the number of element:";
	while (!(in >> numberOfElement))
	{
		in.clear();//清空标志位
		while (in.get() != '\n')//删除无效的输入
			continue;
		cout << "Please enter the number of element:";
	}
	T cinElement;
	for (int i = 0; i < numberOfElement; i++)
	{
		cout << "Please enter the element " << i + 1 << ":";
		while (!(in >> cinElement))
		{
			in.clear();//清空标志位
			while (in.get() != '\n')//删除无效的输入
				continue;
			cout << "Please enter the element " << i + 1 << ":";
		}
		m.push(cinElement);
	}
	return in;
}
/*<<操作符*/
template<class T>
ostream& operator<<(ostream& out, arrayStack<T>& m)
{
	for (int i = 0; i <= m.stackTop; i++)
		out << m.stack[i] << "  ";
	out << endl;
	return out;
}

/*构造函数*/
template<class T>
arrayStack<T>::arrayStack(int initialCapacity)
{
	if (initialCapacity < 1)
	{
		ostringstream s("");
		s << "Initial capacity = " << initialCapacity << "Must be > 0";
		throw illegalParameterValue(s.str());
	}
	stackLength = initialCapacity;
	stack = new T[initialCapacity];
	stackTop = -1;
}

/*将元素theElement压入栈*/
template<class T>
void arrayStack<T>::push(const T& theElement)
{
	if (stackTop == stackLength - 1)
	{
		//空间已满,容量加倍
		changeLength(stack, stackLength, 2 * stackLength);
		stackLength *= 2;
	}
	stack[++stackTop] = theElement;
}
/*将一个栈分裂为两个栈。第一个栈包含从栈底开始的一半元素,第二个栈包含剩余元素*/
template<class T>
void arrayStack<T>::split(arrayStack<T>& a, arrayStack<T>& b)
{
	//首先清空a,b栈
	b.clear();
	a.clear();
	/*将当前栈中的前一半元素存入a栈中*/
	int i = 0;
	for (i = 0; i <= stackTop / 2; i++)
		a.push(stack[i]);
	/*将当前栈中的后一半元素存入b栈中*/
	for (; i <= stackTop; i++)
		b.push(stack[i]);
}
/*将两个栈合并,把第二个栈的所有元素置于第一个栈的顶部。不改变第二个栈中元素的相对顺序*/
template<class T>
void arrayStack<T>::merge(arrayStack<T>& a)
{
	for (int i = 0; i <= a.stackTop; i++)
		push(a.stack[i]);
}
#endif

_15arrayStack.cpp

/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月13日17点38分
Last Version:			V1.0
Descriptions:			测试_15arrayStack.h头文件中的所有函数
*/
// test array based sparse matrix class

#include <iostream>
#include "_15arrayStack.h"
using namespace std;

/*测试函数*/
void arrayStackTest()
{
	cout << endl << "*********************************arrayStackTest()函数开始*************************************" << endl;
	arrayStack<int> a;

	//测试输入和输出
	cout << endl << "测试友元函数*******************************************" << endl;
	cout << "输入输出************************" << endl;
	cin >> a;
	cout << "arrayStack a is:" << a;//arrayStack a is:1  2  3  4  5  6
	cout << endl << "测试成员函数*******************************************" << endl;
	cout << "empty()*************************" << endl;
	cout << "a.empty() = " << a.empty() << endl;//a.empty() = 0
	cout << "size()**************************" << endl;
	cout << "a.size() = " << a.size() << endl;//a.size() = 6
	cout << "top()***************************" << endl;
	cout << "a.top() = " << a.top() << endl;//a.top() = 6
	cout << "pop()***************************" << endl;
	cout << "a.capacity() = " << a.capacity() << endl;//a.capacity() = 10
	cout << "arrayStack a is:" << a;//arrayStack a is:1  2  3  4  5  6
	cout << "a.pop() = " << a.pop() << endl;//a.pop() = 6
	cout << "a.pop() = " << a.pop() << endl;//a.pop() = 5
	cout << "a.pop() = " << a.pop() << endl;//a.pop() = 4
	cout << "a.pop() = " << a.pop() << endl;//a.pop() = 3
	cout << "a.pop() = " << a.pop() << endl;//a.pop() = 2
	cout << "arrayStack a is:" << a;//arrayStack a is:1
	cout << "a.capacity() = " << a.capacity() << endl;//a.capacity() = 5
	cout << "push()**************************" << endl;
	a.push(99);
	cout << "arrayStack a is:" << a;//arrayStack a is:1  99
	cout << "split()*************************" << endl;
	arrayStack<int> b, c;
	a.split(b, c);
	cout << "arrayStack a is:" << a;//arrayStack a is:1  99
	cout << "arrayStack b is:" << b;//arrayStack b is:1
	cout << "arrayStack c is:" << c;//arrayStack c is:99
	cout << "merge()*************************" << endl;
	a.merge(b);
	cout << "arrayStack a is:" << a;//arrayStack a is:1  99  1
	cout << "arrayStack b is:" << b;//arrayStack b is:1
	cout << "*********************************arrayStackTest()函数结束*************************************" << endl;
}

main.cpp

/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月13日17点38分
Last Version:			V1.0
Descriptions:			main()函数,控制运行所有的测试函数
*/
#include <iostream>
#include "_15arrayStack.h"

int main()
{
	arrayStackTest();

	return 0;
}

_1myExceptions.h

/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月13日17点38分
Last Version:			V1.0
Descriptions:			综合各种异常
*/
#pragma once
#ifndef _MYEXCEPTIONS_H_
#define _MYEXCEPTIONS_H_
#include <string>
#include<iostream>

using namespace std;

// illegal parameter value
class illegalParameterValue
{
public:
    illegalParameterValue(string theMessage = "Illegal parameter value")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// illegal input data
class illegalInputData
{
public:
    illegalInputData(string theMessage = "Illegal data input")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// illegal index
class illegalIndex
{
public:
    illegalIndex(string theMessage = "Illegal index")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// matrix index out of bounds
class matrixIndexOutOfBounds
{
public:
    matrixIndexOutOfBounds
    (string theMessage = "Matrix index out of bounds")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// matrix size mismatch
class matrixSizeMismatch
{
public:
    matrixSizeMismatch(string theMessage =
        "The size of the two matrics doesn't match")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// stack is empty
class stackEmpty
{
public:
    stackEmpty(string theMessage =
        "Invalid operation on empty stack")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// queue is empty
class queueEmpty
{
public:
    queueEmpty(string theMessage =
        "Invalid operation on empty queue")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// hash table is full
class hashTableFull
{
public:
    hashTableFull(string theMessage =
        "The hash table is full")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// edge weight undefined
class undefinedEdgeWeight
{
public:
    undefinedEdgeWeight(string theMessage =
        "No edge weights defined")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};

// method undefined
class undefinedMethod
{
public:
    undefinedMethod(string theMessage =
        "This method is undefined")
    {
        message = theMessage;
    }
    void outputMessage() { cout << message << endl; }
private:
    string message;
};
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1047103.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

测试用例的八大基本准则

测试用例的八大基本准则 测试用例的八大基本准则功能测试性能测试兼容性测试安全测试可靠性测试易用性测试数据库测试接口测试 测试案例 测试用例的八大基本准则 上节测试用例的设计中我们讨论如何设计一个测试用例&#xff0c;知道了测试用例的设计有&#xff1a;“边界值&am…

【搭建yolox深度学习环境】

这里写目录标题 一、环境配置二、安装所需库文件2.1 安装apex 一、环境配置 首先进行yolox模型的下载&#xff1a;YOLOX(gitcode) 或者YOLOX(github) 并选择自己所需的权重模型&#xff0c;如-s-m-l等&#xff08;.pth文件&#xff09; 如果需要进行labview的使用&#xff0c;…

正则表达式贪婪模式和非贪婪模式

一、贪婪模式 贪婪模式表示尽可能多的匹配字符串&#xff0c;正则表达式六个量词元字符?、、*、{n}、{n,m}、{n,}默认是贪婪模式 接下来引入一个场景来分析说明 获取html a标签href属性的值 <a href"https://www.baidu.com/" attr"abc"></a>…

可控情感的表现力语音驱动面部动画合成

高度逼真的面部动画生成需求量很大&#xff0c;但目前仍然是一项具有挑战性的任务。现有的语音驱动面部动画方法可以产生令人满意的口部运动和嘴唇同步&#xff0c;但在表现力情感表达和情感控制的灵活性方面仍存在不足。本文提出了一种基于深度学习的新方法&#xff0c;用于从…

stm32之1602+DHT11+继电器

描述&#xff1a; 1、DHT11监测温室度&#xff0c;并显示到1602液晶上 2、通过串口打印&#xff08;或通过蓝牙模块在手机上查看&#xff09; 3、当温度大于24度时&#xff0c;开启继电器。小于时关闭继电器&#xff08;继电器可连接风扇---假想O(∩_∩)O哈哈~&#xff09; 一、…

【Axure教程】用中继器制作双坐标柱状折线图

双坐标柱状折线图常用于同时展示两组数据的图表类型&#xff0c;每组数据都有自己的纵坐标轴&#xff08;Y轴&#xff09;。一组数据通常用柱状图表示&#xff0c;而另一组数据则用折线图表示。这种图表类型有助于比较两组数据之间的关系和趋势。 那今天作者就教大家&#xff…

服务断路器_Resilience4j限流

限流YML配置 ratelimiter:instances:backendA:# 限流周期时长。 默认&#xff1a;500纳秒limitRefreshPeriod: 5s# 周期内允许通过的请求数量。 默认&#xff1a;50limitForPeriod: 2先写Controller /*** 限流* return*/GetMapping("/limiter")RateLimiter(nam…

【AI视野·今日NLP 自然语言处理论文速览 第四十二期】Wed, 27 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 27 Sep 2023 Totally 50 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Attention Satisfies: A Constraint-Satisfaction Lens on Factual Errors of Language Models Authors Mert …

Android widget 小部件使用指南强化版

小部件是主屏幕定制的一个重要方面。您可以将它们视为应用程序最重要的数据和功能的“概览”视图&#xff0c;这些数据和功能可以直接在用户的主屏幕上访问。用户可以在主屏幕面板上移动小部件&#xff0c;如果支持的话&#xff0c;还可以调整它们的大小以根据自己的喜好定制小…

DelayQueue 使用和延时功能源码分析

DelayQueue 延迟队列使用和延时功能源码分析&#xff0c;先看DelayQueue 的使用 目录 1、基本使用 2、延时功能源码分析 3、总结 1、基本使用 想要实现延时功能&#xff0c;需要实现 Delayed 接口&#xff0c;重写 getDelay 方法&#xff0c;在 getDelay 方法里返回延时时间…

关于对象数组的一些方法总结

关于数组对象的一些方法总结 一、判断对象数组是否重复二、复制对象数组 一、判断对象数组是否重复 根据某个属性判断对象数组中&#xff0c;是否含有该属性重复的对象。 let objectArr [{id: 1, name: 2, age: 3}, {id: 2, name: 3, age:24},{id: 1, name: 5, age:6} ]func…

已实现:关于富文本组件库vue2-editor的使用方法以及一些必要的注意事项,特别是设置完富文本以后的回显问题。以及在光标位置插入字符串等

前言 目前常见的基于vue的富文本编辑器有两个&#xff1a;“vue2-editor” 和 “vue-quill-editor” 都是用于Vue.js的富文本编辑器组件&#xff0c;它们具有一些共同的特点&#xff0c;但也有一些区别。 共同点&#xff1a; 1、富文本编辑功能&#xff1a; 两者都提供了富文…

【数据中台建设系列之一】数据中台-元数据管理

本编文章主要介绍数据中台核心模块—元数据模块的一些建设经验分享&#xff0c;供大家一起交流学习。 一、什么是元数据 ​ 元数据可以简单理解为是数据的"数据"&#xff0c;它描述了数据的特征&#xff0c;属性&#xff0c;来源和其他一些数据的基本信息&#xff0…

手机上记录的备忘录内容怎么分享到电脑上查看?

手机已经成为了我们生活中不可或缺的一部分&#xff0c;我们用它来处理琐碎事务&#xff0c;记录生活点滴&#xff0c;手机备忘录就是我们常用的工具之一。但随着工作的需要&#xff0c;我们往往会遇到一个问题&#xff1a;手机上记录的备忘录内容&#xff0c;如何方便地分享到…

基于微信小程序的停车场预约收费小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

数字文创产权版权登记保护多少重要

数字文创产权版权登记保护多少重要 在如今数字化时代&#xff0c;创作者们的作品往往以数字形式存储和传播&#xff0c;这给他们带来了无限的机遇&#xff0c;同时也伴随着一些挑战。在这个环境下&#xff0c;数字文创产权的版权登记显得尤为重要。它不仅能够保护创作者的利益&…

冲刺十五届蓝桥杯P0001阶乘求和

文章目录 题目描述思路分析代码解析 题目描述 思路分析 阶乘是蓝桥杯中常考的知识。 首先我们需要知道 int 和long的最大值是多少。 我们可以知道19的阶乘就已经超过了long的最大值&#xff0c;所以让我们直接计算202320232023&#xff01;的阶乘是不现实的。 所以我们需要…

【逆向】在程序空白区添加Shellcode

目录 硬编码 内存对齐和文件对齐 节表 实战 滴水逆向03-17 #include <windows.h>LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) …

Springboot和Vue:六、ORM介绍+MybatisPlus快速上手

ORM和Mybatis(Plus)介绍 ORM&#xff08;Object Relational Mapping 对象关系映射&#xff09;即映射程序中的对象和数据库中的数据。 MyBatis是一款优秀的数据持久层ORM框架&#xff0c;能够非常灵活地实现动态SQL&#xff0c;可以使用XML或注解来配置和映射原生信息&#xf…

联想笔记本重装系统Win10步骤和详细教程

我们给笔记本电脑重装系统可以解决运行缓慢、出现错误提示等问题&#xff0c;恢复笔记本电脑的流畅运行状态。但是&#xff0c;很多使用联想笔记本电脑的用户不知道重装系统Win10的具体步骤&#xff0c;下面小编给大家介绍关于重装联想笔记本电脑Win10系统的方法步骤吧。 推荐下…