栈(stack)

栈的应用

浏览器 “回退” 功能的实现,底层使用的就是栈存储结构。当你关闭页面 A 时,浏览器会将页面 A 入栈;同样,当你关闭页面 B 时,浏览器也会将 B入栈。因此,当你执行回退操作时,才会首先看到的是页面 B,然后是页面 A,这是栈中数据依次出栈的效果。

不仅如此,栈存储结构还可以帮我们检测代码中的括号匹配问题。多数编程语言都会用到括号(小括号、中括号和大括号),括号的错误使用(通常是丢右括号)会导致程序编译错误,而很多开发工具中都有检测代码是否有编辑错误的功能,其中就包含检测代码中的括号匹配问题,此功能的底层实现使用的就是栈结构。

同时,栈结构还可以实现数值的进制转换功能。例如,编写程序实现从十进制数自动转换成二进制数,就可以使用栈存储结构来实现。

1、栈(Stack)是一种线性存储结构,它具有如下特点:

(1)栈中的数据元素遵守“先进后出"(First In Last Out)的原则,简称FILO结构。

(2)限定只能在栈顶进行插入和删除操作。
2、栈的常用操作为:

(1)弹栈,通常命名为pop

(2)压栈,通常命名为push

(3)求栈的大小

(4)判断栈是否为空

(5)获取栈顶元素的值
3.使用标准库的栈时, 应包含相关头文件,在栈中应包含头文件: #include< stack > 。定义:stack< int > stk;

stk.empty(); //如果栈为空则返回true, 否则返回false;
stk.size(); //返回栈中元素的个数
stk.top(); //返回栈顶元素, 但不删除该元素
stk.pop(); //弹出栈顶元素, 但不返回其值
stk.push(); //将元素压入栈顶

顺序栈4要素:
栈空条件:top=-1
栈满条件:top=MaxSize-1
进栈e操作:top++; 将e放在top处
退栈操作:从top处取出元素e; top–;
3.在顺序栈中实现栈的基本运算算法。

(1)初始化栈initStack(&s)
建立一个新的空栈s,实际上是将栈顶指针指向-1即可。对应算法如下:
csharp void InitStack(SqStack *&s) { s=(SqStack *)malloc(sizeof(SqStack)); s->top=-1; }
2)销毁栈ClearStack(&s)
释放栈s占用的存储空间。对应算法如下:
void DestroyStack(SqStack *&s) {    free(s); }
(3)判断栈是否为空StackEmpty(s)
栈S为空的条件是s->top==-1。对应算法如下:
bool StackEmpty(SqStack *s) {    return(s->top==-1); }
(4)进栈Push(&s,e)
在栈不满的条件下,先将栈指针增1,然后在该位置上插入元素e。对应算法如下:

		bool Push(SqStack *&s,ElemType e)
		{
 		 if (s->top==MaxSize-1)  //栈满的情况,即栈上溢出
    				return false;
			 s->top++;           //栈顶指针增1
  			 s->data[s->top]=e;      //元素e放在栈顶指针处
  			 return true;
		}

(5)出栈Pop(&s,&e)
在栈不为空的条件下,先将栈顶元素赋给e,然后将栈指针减1。对应算法如下:

   bool Pop(SqStack *&s,ElemType &e)
	{
   			if (s->top==-1)  //栈为空的情况,即栈下溢出
    				return false;
   			e=s->data[s->top];   //取栈顶指针元素的元素
   			s->top--;        //栈顶指针减1
   			return true;
	}

6)取栈顶元素GetTop(s)
在栈不为空的条件下,将栈顶元素赋给e。对应算法如下:

bool GetTop(SqStack *s,ElemType &e)
{   
   if (s->top==-1)  //栈为空的情况,即栈下溢出     
      return false;
    e=s->data[s->top];  //取栈顶指针元素的元素
    return true;
}

例:编写一个算法利用顺序栈判断一个字符串是否是对称串。所谓对称串是指从左向右读和从右向左读的序列相同。 解:对于字符串str,先将其所有元素进栈。然后从头开始扫描str,并出栈元素,将两者进行比较,若不相同则返回false。当str扫描完毕仍没有返回时返回true。实际上,从头开始扫描str是从左向右读,出栈序列是从右向左读,两者相等说明该串是对称串

bool symmetry(ElemType str[])
{  
		 int i;  ElemType e;
  		 SqStack *st;
   		InitStack(st);           //初始化栈
   		for (i=0;str[i]!='\0';i++)   //将串所有元素进栈
    			Push(st,str[i]);        //元素进栈
  		 for (i=0;str[i]!='\0';i++)
   		{   
   				 Pop(st,e);        //退栈元素e
    			if (str[i]!=e)    //若e与当前串元素不同则不是对称串
    			{  
    					DestroyStack(st);//销毁栈
       					return false;
    			}
 		  }
  		 DestroyStack(st);      //销毁栈
   		return true;
}

例:编写一个算法判断输入的表达式中括号是否配对(假设只含有左、右圆括号)。
解:该算法在表达式括号配对时返回true,否则返回false。设置一个顺序栈St,扫描表达式exp,遇到左括号时进栈;遇到右括号时:若栈顶为左括号,则出栈,否则返回false。当表达式扫描完毕,栈为空时返回true;否则返回false。

bool Match(char exp[],int n)
{  
		int i=0; char e;  bool match=true; SqStack *st;
   		InitStack(st);             //初始化栈
   		while (i<n && match)       //扫描exp中所有字符
   		{    
   				if ( exp[i]=='()  //当前字符为左括号,将其进栈
       					Push(st,exp[i]);
    			else if (exp[i]==')')   //当前字符为右括号
      			{
      				if (GetTop(st,e)==true)
       				{
       					if (e!='(')    //栈顶元素不为'('时表示不匹配
           						match=false;
       					 else
           						Pop(st,e);    //将栈顶元素出栈
       				 }
      				else  match=false;  //无法取栈顶元素时表示不匹配
     			 }
   				 i++;                 //继续处理其他字符
   		}
 	if (!StackEmpty(st))      //栈不空时表示不匹配
    		match=false;
   	DestroyStack(st);         //销毁栈
   	return match;
}

例:括号配对
不能使用栈(15min,不太好想,mad,笔试那会儿就没想到!)

   以下是我的想法,具体的过程如下:

  (1)由于不能使用栈,将左括号定义为数值1,右括号定义为数值-1,存放到向量id(C++)或列表tmp (Python)中;

  (2)初始化变量sum,用于判断总的求和结果是否等于0,若不等于0,则肯定不正确,若等于0,不一定正确;

  (3)循环遍历输入的括号向量vec,判断当前括号属性的同时,进行累加求和,如果求和值小于等于-1,break(跳出循环);

  (4)最后再检查sum是否等于0,此时若等于0,则为正确。
#include 
#include 
using namespace std;
bool isRight(vector<char> &vec)
{
   	vector<int> id(vec.size()); //用于存放左右括号的属性:左括号用1表示,右括号用-1表示
   	int sum = 0;
   	bool index = false;
   	if (vec.size() <= 1 || vec[0]!='(' || vec.size()%2!=0)
   	{
   			return index;
   	}
   	for (int i = 0; i < vec.size(); i++)
   	{
   			if (vec[i] == '(')
   			{
   					id.push_back(1);
   					sum = id[i] + sum;
   			}	
   			else if (vec[i] == ')')
   			{
   					id.push_back(-1);
   					sum = id[i] + sum;
   					if (sum <= -1)
   							break;
   			}
   	}
   	if (sum == 0)
   			index = true;
   	return index;
}
int main()
{
   		//输入不定长的括号
   		vector<char> vec;
   		char tmpCh;
   		char t;
   		cout << "输入一串括号为:";
   		do{
   				cin >> tmpCh;
   				vec.push_back(tmpCh);
   			} while ((t = cin.get()) != '\n');
   		//调用isRight函数
   		bool myRes = isRight(vec);
   		cout << myRes << endl;
   		system("pause");
   		return 0;
}

你可能感兴趣的:(算法之路)