【数据结构】第八章_栈

8.1定义和描述

  1. 定义:栈(stack)是一种特殊的线性表,其插入(入栈、压栈)和删除(出栈、弹栈)操作都在表的同一端进行
  2. 栈顶top:允许插入和删除的一端
  3. 栈底bottom:另一端
  4. 可以使用任意一种线性表的描述方法
    在这里插入图片描述
    在这里插入图片描述

8.2抽象数据类型

ADT

抽象数据类型stack 
{
    实例
		元素线性表,一端为栈底,另一端为栈顶
	操作
		empty();//栈为空时返回true,否则返回false 
    	size();//返回栈中元素个数
    	top();//返回栈顶元素
    	pop();//删除栈顶元素
    	push(x);//将元素x压入栈
}

c++抽象类

template <class T>
class stack
{
    public:
		virtual ~stack(){}
    
    	//栈为空时返回true,否则返回false
		virtual bool empty() const = 0;
    	//返回栈中元素个数	
 		virtual int size()const = 0;    
    	//返回栈顶元素
		virtual T& top() = 0;    
    	//删除栈顶元素
 		virtual void pop() = 0;    
    	//将元素theElement压入栈Y
		virtual void push(const T& theElement) = 0;
};

8.3数组描述

两种方法:

  • arrayList类上派生得到数组描述的栈类derivedArrayStack
  • 定制数组描述的栈类arrayStack

8.3.1作为一个派生类实现

在这里插入图片描述

补:arrayList类

template<class T>
class arrayList:public linearList<T>
{
    public:
    	//构造函数、复制构造函数、析构函数
    	arrayList(int initialCapacity = 10);
    	arrayList(const arrayList<T>&);
    	~arrayList(){delete[]element;}
    	//ADT方法
    	bool empty() const {return listSize == 0;}
 		int size() const {return listSize;}
    	T& get(int theIndex) const;
    	int indexOf(const T&theElement) const;
    	void erase(int theIndex);
    	void insert(int theIndex,const T&theElement);
    	void Output(ostream& out) const;
    	//其他方法
    	int capacity() const{return arrayLength;}
    protected:
    	//若索引theIndex无效,则抛出异常
    	void checkIndex(int theIndex) const;
    	T *element;//存储线性表元素的一维数组
    	int arrayLength;//一维数组的容量
    	int listSize;//线性表的元素个数
}; 

派生出的数组栈类

同时继承arrayList以及抽象类stack并实现对应方法

template<class T>
class derivedArrayStack:private arrayList<T>,public stack<T>
{
    public:
		derivedArrayStack(int initialCapacity = 10):
			arrayList<T>(initialCapacity){}
		bool empty()const {return arrayList<T>::empty();}
		int size() const {return arrayList<T>::size();}
 		T& top()
        {
            if (arrayList<T>::empty())
                throw StackEmpty();
			return get(arrayList<T>::size()-1);
        }
		void pop()
        {
            if(arrayList<T>::empty())
                throw StackEmpty();
            erase(arrayList<T>::size()-1);
        }
		void push(const T& theElement)
			{insert(arrayList<T>::size(),theElement);}
};

评价:

  • 优点:大大减少了编码两,程序的可靠性得到很大的提高
  • 缺点:运行效率降低(push中不必要的下标检查和拷贝)

8.3.2 类arrayStack

在这里插入图片描述

  • 栈顶元素:stack[stackTop]
  • 栈底元素:stack[0]

类的声明

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;}
    	T& top();
    	void pop();
		void push(const T& theElement);
	private:
    	int stackTop;//当前栈顶
		int arrayLength;//栈容量
		T*stack;//元素数组
};

构造函数

template<class T>
arrayStack<T>::arrayStack(int initialCapacity = 10)
{
    if(initialCapacity < 1)
    {
        ostringstream s;
        s << "initialCapacity Must be > 0";
        throw illegalParameterValue(s.str());
    }
    arrayLength = initialCapacity;
    stack = new T[arrayLength];
    stackTop = -1;
}

方法top

返回栈顶元素

template<class T>
T& arrayStack<T>::top()
{
    if(stackTop == -1)
        throw StackEmpty;
    return stack[stackTop];
}

方法pop

删除栈顶元素

template<class T>
void arrayStack<T>::pop()
{
    if(stackTop == -1)
        throw StackEmpty;
    //T的析构函数
    stack[stackTop--].~T();
}

方法push

像栈顶压入一个元素

template<class T>
void arrayStack<T>::push(const T& theElement)
{
    //如果栈已满,则容量加倍. 
    if(stackTop == arrayLength-1)
	{
        changeLength(stack, arrayLength, 2*arrayLength);
        arrayLength *= 2;
    }
    //在栈顶插入元素
	stack[++stackTop] = theElement;
}

在一个数组中描述两个栈

在这里插入图片描述

8.4链表描述

两种方法:

  • 通过chain类派生得到链表描述的栈类derivedLinkedStack
  • 定制链表描述的栈类linkedStacked类
  • 选择链表的左端作为栈顶

8.4.1类derivedLinkedStack

在这里插入图片描述
在这里插入图片描述

类linkedStack

在这里插入图片描述

template<class T>
struct chainNode
{
    T element;
    chainNode<T>*next;
    chainNode(){}
    chainNode(const T&element)
    	{this->element = element;}
    chainNode(const T&element,chainNode<T>*next)
    {
        this->element = element;
        this->next = next;
    }
};
template<class T>
class linkedStack:public stack<T>
{
    public:
    	//构造函数
    	linkedStack(int initialCapacity = 10)
        	{stackTop = NULL; stackSize = 0;}
    	~linkedStack();//析构函数
    	bool empty() const
        	{return stackSize == 0;}
    	int size() const
        	{return stackSize;}
    	T& top()
        {
            if(stackSize == 0)
                throw stackEmpty();
            return stackTop->element;
        }
    	void pop();
    	void push(const T& theElement)
        {
            srackTop = new chainNode<T>(theElement,stackTop);
            stackSize++;
        }
    private:
    	chainNode<T>*stackTop;//栈顶指针
    	int stackSize;//栈中元素个数
};
//析构函数,不断的删除栈顶元素
template<class T>
linkedStack<T>::~linkedStack()
{
    while(stackTop != NULL)
    {
        //删除栈顶节点
        chainNode<T>*nextNode = stackTop->next;
        delete stackTop;
        stackTop = nextNode;
    }
}
//删除
template<class T>
void linkedStack<T>::pop()
{
    if(stackSize == 0)
    	throw stackEmpty();
    chainNode<T>* nextNode = stackTop->next;//复制栈顶的下一个元素
    delete stackTop;//删除栈顶
    stackTop = nextNode;//更新栈顶元素
    stackSize--;
}

8.5应用

8.5.1括号匹配

图解括号匹配
括号匹配(含代码)
在这里插入图片描述

8.5.2汉诺塔

//全局变量,tower【1:3】表示三个塔
arrayStack<int> tower[4];
//把n个碟子从塔x移动到塔y,可借助于塔z
void moveAndShow(int n,int x,int y,int z); 
void towersOfHanoi(int n)
{
    //函数moveAndShow的预处理程序
	for(int d = n;d > 0;d--)//初始化
		tower[1].push(d);//把碟子d放到塔1上
	//把塔1上的n个碟子移动到塔2上,借助于塔3的帮助
    moveAndShow(n,1,2,3);
}
void moveAndShow(int n, int x, int y, int z)
{
    //把n个碟子从塔x移动到塔y,可借助于塔z 
    	if(n>0)
        {
			moveAndShow(n-l,x,z,y);
            int d = tower[x].top();//碟子编号
            tower[x].pop();//从x中移走一个碟子
            tower[y].push(d);//把这个碟子放到y上
            ShowState();//显示塔的布局
            moveAndShow(n-l,z,y,x);
       	}	
}

8.5.3列车车厢重排

  • 问题描述:
    在这里插入图片描述
    在这里插入图片描述

8.5.6迷宫老鼠

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值