我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++栈的数组实现代码

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++栈的数组实现代码

栈的抽象数据结构。栈的成员函数需要包括这几个基本的函数:initializeStack(),isEmptyStack(),isFullStack,push(),pop(),top()

其功能如下:

  • initializeStack():初始化栈
  • isEmptyStack():判断栈是否为空
  • isFullStack():判断栈是否已满
  • push():将一个元素压入栈中
  • pop():删除栈顶元素
  • top():获得栈顶元素

​ C++中用抽象类作为基类实现ADT如下:

template<class Type>
    class stackADT
    {
        virtual void initializeStack()=0;//virtual和=0表明都是纯虚函数,抽象类中只能声明纯虚函数,不能定义
        virtual bool isEmptyStack() const=0;//const放在函数后面,表明该函数是常成员函数,在函数执行过程中不能改变函数内部变量的值
        virtual bool isFullStack() const=0;
        virtual void push(const Type&)=0;//引用常量,该函数不会自动对输入进行赋值,同时在函数内的操作也不能改变输入的值
        virtual void pop()=0;
        virtual Type top() const=0;//这里也采用常成员函数,因为函数不会对变量进行修改,只是返回变量
    };

​ 补充说明:

  • 抽象类:一个类中只要有一个纯虚函数,那么该类就是抽象类,抽象类通常作为基类,纯虚函数在抽象类中只能声明不能定义。
  • 常成员函数:什么时候才使用常成员函数?一般在如果该函数在执行过程中不会有改变变量值的操作,就会把该函数定义为常成员函数。
  • 常引用:常引用一般用于函数输入,或者函数返回值。如函数输入是常引用类型,那么说明该函数只会用到引用的值,而不会改变引用变量的值,同时可能引用变量的类型可能很大比较占内存,所以用引用可以避免输入参数的复制,从而节约了空间;若函数返回值为常引用类型,那么有两个原因,首先const表示返回值不能被修改(注意和常成员函数做区分),引用则表示函数返回时不会对返回变量进行拷贝,从而不会触发拷贝函数,因此经常被用于运算符重载,但是要注意返回值不能是函数局部变量,因为局部变量在函数结束后会被释放,从而引用了不合法的内存,会报错,像如果是运算符重载返回的基本是this指向的对象,这对于函数来说则是全局的,所以是没问题的,一般如果返回值是对象,且要避免拷贝,那么就把返回值类型设置为常引用。总之引用作为输入参数或者返回值时就是为了避免产生副本,而const则是为了保证变量不被修改。
  • 栈的动态数组实现

​ 直接继承抽象类,不管是动态数组实现还是链表实现,抽象类的那几个成员函数都是需要的,但是函数实现的内容不一样

​ 这就体现了多态了。

​ 下面是派生栈类的定义:

template <class Type>
    class stackType:public stackADT<Type> //一定要记住每次用到模板类时不要忘记后面的<Type>
    {
        public:
        stackType(int stackSize=100);//注意这里用到了参数缺省构造函数中的参数缺省必须在声明函数时给出默认值而不能在定义函数时给出默认值;stackType作为函数名,因此后面不要加<Type>
        stackType(const stackType<Type>&); //拷贝构造函数
        ~stackType();
        const stackType<Type>& operator=(const stackType<Type>&);//重载赋值运算符
        void initializeStack();
        bool isEmptyStack()const;
        bool isFullStack()const;
        void push(const Type&);
        void pop();
        Type top()const;
        private:
        Type* list;//指向栈的首地址
        int maxStackSize;//栈的最大容量
        int stackTop;//栈顶元素的位置(从1开始)
        void copyStack(const stackType<Type>&);//执行深拷贝过程
    };//注意不要忘记分号

​ 成员函数的实现如下:

​ initializeStack():

template<class Type>//在类外定义函数必须使用template,并且每定义一个函数就要写一次
void stackType<Type>::initializeStack()  //命名空间也不要忘记::,因为命名空间的名字是模板类,所以后面要有<Type>
{
    stackTop=0;//不需要把元素全部置零,只需要把栈顶元素的索引变成0即可
}

​ isEmptyStack():

template<class Type>
bool stackType<Type>::isEmptyStack()const
{
    return !stackTop;//可以认为stackTop表示栈中目前元素的个数,为0则表示空栈
}

​ isFullStack():

template<class Type>
bool stackType<Type>::isFullStack()const
{
    return stackTop==maxStackSize;
}

​ push():

template<class Type>
void stackType<Type>::pop()
{
    if(!isEmptyStack())
        stackTop--;
    else
        cout<<"The stack is empty,cannot add to an item"<<endl;
}

​ pop():

template<class Type>
void stackType<Type>::pop()
{
    if(!isEmptyStack())
        stackTop--;
    else
        cout<<"The stack is empty,cannot add to an item"<<endl;
}

​ top():

template<class Type>
Type stackType<Type>::top()const
{
    assert(!isEmptyStack());//如果栈为空那么必须终止程序,reuturn 返回的会是乱码,push和pop不需要这个操作是因为他们没有返回值,所以如果不满足执行的条件只需要在终端上显示出现异常就行。
    return list[stackTop-1];
}

​copyStack():

template<class Type>
void stackType<Type>::copyStack(const stackType<Type>& otherStack)
{
    delete [] list;   //释放当前栈的内存,注意如果delete的是一个空指针,那么delete不会执行,因此就不需要判断是否为空指针
    stackTop=otherStack.stackTop;
    maxStackSize=otherStack.maxStackSize;
    list=new Type[maxStackSize];  //
    for(int i=0;i<stackTop;i++)
        list[i]=otherStack.list[i];
}

​stackType():构造函数

template<class Type>
stackType<Type>::stackType(int stackSize)
{
    if(stackSize<=0)
    {
        cout<<"The size must be positive"<<endl;
        cout<<"creating an array of size 100"<<endl;
        maxStackSize=100;
    }
    else
    {
        maxStackSize=stackSize;
    }
    stackTop=0;
    list=new Type[maxStackSize];
}

​stackType():拷贝构造函数

template<class Type>
stackType<Type>::stackType(const stackType<Type>& otherStack)
{
    list=nullptr;       //这里list必须置为空,因为在这个程序中,赋值栈的赋值触发的是运算符重载,而拷贝构造函数只有在作为函数输入参数时或者返回参数时才会被触发,同时由于拷贝构造函数是构造函数重载,所以在触发拷贝构造函数前并不会触发构造函数,也意味着并没有给list分配内存,那么list就是一个野指针,如果不置为空那么调用copyStack()时,由于copyStack中第一条语句就是delete []list;删除没有分配内存的野指针就会报错,所以list置为空是必须的
    copyStack(otherStack);
}

operator=():赋值运算符重载

template<class Type>
const stackType<Type>& stackType<Type>::operator=(const stackType<Type>& otherStack)
{
    if(this!=&otherStack) //避免自我复制
    copyStack(otherStack);
    return *this;
}

​~stackType():析构函数

template<class Type>
stackType<Type>::~stackType()
{
    delete [] list;
}

​文件构成有两种方式

stackADT单独一个头文件,stackADT.h,stackType类在头文件stackArr.h中定义,在.cpp文件中实现。

stackArr.h

#include "stackADT.h"
//类的定义放在这里

stacArr.cpp

#include<iostream>
#include<cassert>
#include "stackArr.h"
using namespace std;
//类的实现放在这里

main.cpp

#include "stackArr.cpp" //这里不能include "stackArr.h",因为这里是模板类,模板类需要编译两次,
int main()
{
    //主函数的内容
    return 0;
}

2.把stackArr类的定义和实现都放进一个头文件stackArr.h

#ifndef H_StackType
#define H_StackType
#include<iostream>
#include<cassert>
#include "stackADT"
using namespace std;
//类的定义如下
//此处写类的成员函数的实现
#endif

总结:使用模板实现栈的一些要点

首先栈最重要的特征就是先入后出,有一端相当于是封闭的,另外栈的一个重要标识就是栈顶,如果用数组实现栈,那么就通过栈顶元素的索引+1(因为索引从0开始)来表示栈顶。

2.把对象复制过程进行了分离,这里用copyStack函数实现了对象成员变量的复制,由于成员变量中有指针,而且指针指向的是动态内存所以必须进行深拷贝,而在拷贝构造函数中直接调用copyStack函数即可,同时这里将赋值运算符进行了重载,那么对于语句a=b,调用的就不是拷贝构造函数了,而是调用运算符重载,只有在作为函数输入或者返回参数时生成对象副本次才会调用拷贝构造函数,还有析构函数要把内存释放,否则会导致内存泄漏。

3.注意push,pop,top的异常判断,这也是初学最容易忽视的点,不要嫌麻烦,对于会导致程序出错的输入要终止程序,像本程序中top函数是有返回值的所以如果是空栈的话返回的就是乱码所以遇到空栈用了assert函数退出程序,像如果只是输入不合法,像push函数,因为是先判断的栈是否已经满了,而且没有返回值,假如栈已满,我们不进行压栈操作就行了,只需要在终端打印错误信息就行,因此就没必要终止程序。

4.特别注意类模板的定义和实现,对于模板类而言最好还是把定义和实现的代码放在同一个头文件,同样采取类内声明,类外定义的方法。对非模板类而言,类的定义和实现通常不在同一个头文件,一般就是在头文件中定义类,然后在同名的.cpp文件中实现成员函数。
[[栈的链表实现]]

到此这篇关于C++栈的数组实现的文章就介绍到这了,更多相关C++栈的数组实现内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++栈的数组实现代码

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++链栈的实现代码怎么写

这篇文章主要讲解了“C++链栈的实现代码怎么写”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++链栈的实现代码怎么写”吧!链栈简述链栈从概念上看是链表和栈的结合,含有栈先进后出的特性,也具
2023-07-02

Java栈之链式栈存储结构的实现代码

Java栈之链式栈存储结构实现一、链栈采用单链表来保存栈中所有元素,这种链式结构的栈称为链栈。二、栈的链式存储结构实现package com.ietree.basic.datastructure.stack;/** * 链栈 * * Cre
2023-05-31

java中栈的数组和链表实现

栈的介绍栈,是一种先进后出(FILO)的线性数据结构,主要操作为入栈和出栈。栈底:最早进入的元素存放的位置。栈顶:最后进入元素存放的位置(有些栈中将栈顶表示为栈顶元素的下一位置)。免费在线学习视频推荐:java视频栈的数组的实现示例如下:public clas
java中栈的数组和链表实现
2014-09-11

Python数据结构之栈、队列的实现代码分享

1. 栈 栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶
2022-06-04

c++数组排序的5种方法实例代码

大家还在为大小排序而烦恼吗?今天让我我大家解决这个问题吧,下面这篇文章主要给大家介绍了关于c++数组排序的5种方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2023-01-11

C++代码调用C#代码的过程怎么实现

这篇文章主要讲解了“C++代码调用C#代码的过程怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++代码调用C#代码的过程怎么实现”吧!首先建立一个C#工程Class Library
2023-06-17

java整数与byte数组的转换实现代码

java整数与byte数组的转换实现代码 这里对java中整数与byte数组的转换进行了实现,平时的项目中很少用的到,但是特定需求的时候还是需要的,这里就记录下,亲测可用,实现代码:public class Number
2023-05-31

Python 数据结构之堆栈实例代码

Python 堆栈 堆栈是一个后进先出(LIFO)的数据结构. 堆栈这个数据结构可以用于处理大部分具有后进先出的特性的程序流 . 在堆栈中, push 和 pop 是常用术语:push: 意思是把一个对象入栈.pop: 意思是把一个对象出
2022-06-04

C++实现Matlab的zp2tf函数的示例代码

matlab 的 zp2tf 函数的作用是将极点形式的 H(s) 函数的分母展开,本文主要为大家介绍了C++实现Matlab的zp2tf函数示例代码,需要的可以参考一下
2023-05-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录