<C/C++数据结构> 栈

一,栈的基本定义

栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。


1、栈的操作

 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
  (1)通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。
  (2)当表中没有元素时称为空栈。
  (3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表。
 栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除。


2,栈的示图

元素是以a1,a2,…,an的顺序进栈,退栈的次序却是an,an-1,…,a1。



二,数组实现栈(C++模板)

1,stack.h的实现:

#include "iostream"
#include "windows.h"
using namespace std;
template<typename DataType> 
class MyStack
{
public:
	MyStack(int size)
	{
		maxSize = size;                   //设置最大容量
		top = -1;                         //初始化为空栈
		elements = new DataType[size];    //动态分配连续的数组空间,共size个数据
		for (int i=0;i<maxSize;i++)
		{
			elements[i]=0;
		}
		
	}

	~MyStack()
	{
		if (elements!=NULL)
		{
			delete[] elements;
			elements=NULL;
		}
	}
	//入栈操作
	bool push(DataType data);
	//出栈操作
	DataType pop();
	//判断栈是否为空
	bool IsEmpty();
	//获取元素个数
	int GetNums();
	//摧毁栈
	void DestroyStack();
	//求取栈中的最小值
	DataType Min();
	//求取栈中的最大值
	DataType Max();
private:
	DataType *elements;           //数据域指针
	int top;                     //栈顶,top=0,就表示有一个数据了
	int maxSize;                 //栈的最大容量
};

/*****************入栈操作************************/
template<typename DataType> 
bool MyStack<DataType>::push(DataType data)
{
	if((top+1) == maxSize)                     //入栈前一定要先判断是否栈满
	{
		cout<<"已经满栈!此时栈顶为"<<data<<endl;
		return false;
	}
	else
	{
		top++;
		elements[top] = data;     //从栈顶压入元素,并且top加一
	}
	return true;
}

/********************出栈操作(去元素)*******************/
template<typename DataType> 
DataType MyStack<DataType>::pop()
{
	if(IsEmpty())                          //判断是否栈空
	{
		cerr<<"栈为空,注意检查"<<endl;
		exit(1);
	}
	else
	{
		return elements[top--];                //返回当前栈顶元素,随后top减一
		//top--;
	}
}

/*************************栈判断是否空***********************/
template<typename DataType>
bool MyStack<DataType>::IsEmpty()
{
	if(top == -1)
		return true;
	else
		return false;
}

/*********************获取当前元素个数数********************/
template<typename DataType> 
int MyStack<DataType>::GetNums()
{
	if(top >= 0)
		return top+1;
	else
		return 0;
}

template<typename DataType> 
void MyStack<DataType>::DestroyStack()
{
	maxSize = 0;                   //设置最大容量
	top = 0;                         //初始化为空栈
	delete[] elements ;    //动态分配连续的数组空间,共size个数据
	elements=NULL;
}

template<typename DataType> 
DataType MyStack<DataType>::Min()//直接遍历的方法求最小值(或者最大值)
{
	DataType temp=elements[0];
	for (int i = 1;i < top+1;i++)
	{
		if (elements[i] < temp)
		{
			temp=elements[i];
		}
	}
	return temp; 
}

template<typename DataType> 
DataType MyStack<DataType>::Max()
{
	DataType temp=elements[0];
	for (int i = 1;i < top+1;i++)
	{
		if (elements[i] > temp)
		{
			temp=elements[i];
		}
	}
	return temp; 
}


2,主测试代码:

// ConsoleAppStack.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Stack.h"
#include "iostream"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	//首先按顺序入栈 
	MyStack<int> s = MyStack<int>(10);               //创建栈结构,这个栈可以容纳10个元素  
	//入栈  
	s.push(10);  
	s.push(15);  
	s.push(1);  
	s.push(6);  
	s.push(45);  
	s.push(9);  
	s.push(35);  
	cout<<"当前栈中元素个数为:  "<<s.GetNums()<<endl;  
	int temp = s.pop();
	cout<<"栈顶元素出栈: "<<temp<<endl;
	cout<<"当前栈中元素个数为:  "<<s.GetNums()<<endl;  
	cout<<"栈的最小值"<<s.Min()<<endl;
	cout<<"栈的最大值"<<s.Max()<<endl;
	s.DestroyStack();
	cout<<"栈已经摧毁!"<<endl;
	system("pause");
	return 0;  
}


3,测试结果:


 

三,链表实现栈(C++模板)

1,StackLink.h的实现:

#include "stdafx.h"
#include "iostream"
using namespace std;

template<class DataType> class Stack;

template<class DataType>
class LinkNode
{
public:
	LinkNode()
	{
		next=NULL;
		nData=0;
	}

	LinkNode(DataType newData)
	{
		next=NULL;
		nData=newData;
	}

	~LinkNode()
	{

	}
private:
	friend class Stack<DataType>;
	LinkNode<DataType> *next;
	DataType nData;
};

template<class DataType>
class Stack
{
public:
	Stack(int size)
	{
		top=NULL;
		count=0;
		maxSize=size;
	}
	~Stack()
	{
		int len=getNum();
		for ( int i=0;i< len;i++)
		{
			LinkNode<DataType> *p=top;
			top=p->next;
			delete p;
		}
	}
	int getNum()
	{
		return count;
	}
	//进栈
	bool InsertNode(DataType newData);
	//出栈
	bool outNode();
private:
	LinkNode<DataType> *top;
	int count;
	int maxSize;
};

template<class DataType>
bool Stack<DataType>::InsertNode(DataType newData)
{
	if (getNum() == maxSize)
	{
		cerr<<"栈已经满,请勿再进行插入操作!"<<endl;
		return false;
	}else
	{
		LinkNode<DataType> *newNode=new LinkNode<DataType>(newData);
		if (top == NULL)
		{
			top=newNode;
			count++;
			return true;
		}else
		{
			newNode->next=top;
			top=newNode;
			count++;
			return true;
		}
	}
}


template<class DataType>
bool Stack<DataType>::outNode()
{
	if (getNum() == 0)
	{
		cerr<<"数据已经全部出栈,请勿再继续操作!"<<endl;
		return false;
	}
	else
	{
		LinkNode<DataType> *p=top;
		cout<<"当前出栈数据为"<<p->nData<<endl;
		top=p->next;
		delete p;
		count--;
		return true;
	}
}

2,主测试代码如下:

// ConsoleAppStackList.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "StackList.h"
#include "iostream"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	int len=10;
	Stack<char> S(len);
	char str='A';
	for (int i = 0;i < len;i++)
	{
		S.InsertNode(str++);
	}
	cout<<"当前栈中数据个数为:"<<S.getNum()<<endl;
	cout<<"--------------栈初始化已经完成---------------"<<endl;
	for (int j=0; j<11;j++)
	{
		if (S.getNum() == 0)
		{
			cerr<<"数据已经全部出栈,操作即将停止!"<<endl;
			break;
		}
		S.outNode();
	}
	system("pause");
	return 0;
}

3,测试结果:





四,小试牛刀

1,括号匹配问题

题目描述:

    在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注.

输入:

    输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100。
    注意:cin.getline(str,100)最多只能输入99个字符!

输出:

    对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$","?"和空格组成,"$"和"?"表示与之对应的左括号和右括号不能匹配。

样例输入:
)(rttyy())sss)(
样例输出:
)(rttyy())sss)(
?            ?$


#include "iostream"  
#include "string"  
#include "stack"  
 
using namespace std;
 
void BracketMatch(const string srcStr);
int main()
{
    string str;
    while (cin >> str)
    {
        cout << str << endl;
        BracketMatch(str);
    }
    return 0;
}
 
void BracketMatch(const string srcStr)
{
    stack<int> s;
    string ansStr(srcStr.length(),'0');
    for (unsigned int i = 0; i < srcStr.length(); i++)//从左往右开始遍历  
    {
        if (isalpha(srcStr[i]))
        {
            ansStr[i]=' ';
            continue;
        }
        switch (srcStr[i])
        {
                //对左括号仅作压栈处理,也就是说栈中只可能是左括号  
            case '(':
                if (i != (srcStr.length() - 1))//当是最后一个字符时已经没有必要输出空格了
                    ansStr[i] = ' ';
                s.push(i);//注意,这里
                break;
 
                //对右括号做匹配判断
            case ')':
                if (!s.empty())
                {//如果不为空,说明一定有左括号(实际上是其数组下标)
                    s.pop();
                    ansStr[i] = ' ';
                }
                else//如果为空
                    ansStr[i] = '?';
                break;
 
            default:
                cerr << "错误的括号" << endl;
        }
    }
    while (!s.empty())
    {  //解决多余的左括号  
        ansStr[s.top()] = '$';
        s.pop();
    }
    cout << ansStr << endl;
}



注:

本文部分文字学习并copy自网络,代码参考并改编自《算法导论》.

如果侵犯了您的版权,请联系本人tangyibiao520@163.com,本人将及时编辑掉!


参考资源:

【1】《百度文库》

【2】《算法导论》


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REaDME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值