【考研数据结构】栈

自己学习整理的笔记,给自己温故而知新。

1.栈说明

1.1 表和数组

表是动态的数据结构,大小可以改变。
数组是静态的数据结构,在程序编译的时候它的大小是固定的。

1.2 栈

栈是一种形式的表。是LIFO后进先出的。

1.3 栈的编程实例:

此时用到的栈是C++STL标准库当中的,我们可以拿来用,但是不知道里面具体内容,这就是信息隐藏的一种。
(1)反转表

#include<iostream>
#include<stack>
using namespace std;

int main(){
	/*Pre:The user supplies an integer n and n decimal numbers  前置条件 
	Post:The number are printed in reverse order                后置条件 
	Uses:The STL class stack and its methods*/                //使用方法  
	int n;
	double item; 
	stack<double> numbers;
	cout<<"Type in an integer n followed by n decimal numbers."<<endl
	    <<"The numbers will be printed in reverse order."<<endl;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>item;
		numbers.push(item);
	}
	cout<<endl;
	while(!numbers.empty()){
		cout<<numbers.top()<<" ";
		numbers.pop();
	}
	cout<<endl;
}

(2)字符串反转

#include<iostream>
#include<stack>
using namespace std;

int main(){
	/*Pre:The user supplies an string 前置条件 
	Post:The string are printed in reverse order                后置条件 
	Uses:The STL class stack and its methods*/                //使用方法  
	char input;
	stack<char> text;
	cout<<"Type in an string."<<endl
	    <<"The string will be printed in reverse order."<<endl;
	while((input=cin.get())!='\n'){
		text.push(input);
	}
	while(!text.empty()){
		cout<<text.top();
		text.pop();
	}
	cout<<endl;
}

(3)整数条件反转

#include<iostream>
#include<stack>
using namespace std;

int main(){
	/* Pre: An increasing sequence of integers is entered, input is terminated by a final integer that
			is smaller than its predecessor.
	   Post: The sequence is printed in decreasing order. */
	int input; 
	stack<int> numbers;
	cout<<"Type in an integer n followed by n int numbers."<<endl
	    <<"The numbers will be printed in reverse order."<<endl;
	cin>>input;
	numbers.push(input);
	while(1){
		cin>>input;
		if(input>numbers.top()){
			numbers.push(input);
		}
		else
			break;
	}
	while(!numbers.empty()){
		cout<<numbers.top()<<" ";
		numbers.pop();
	}
	cout<<endl;
}

1.4栈的八股文常考题型:

1.进栈顺序为abcde,有哪些合法的出栈顺序?
这里引入一个概念,叫卡特兰(Catalan)数。
n个不同元素进栈,出栈元素不同排列的个数为在这里插入图片描述
这就是卡特兰数。
在这里插入图片描述
记忆方法:10个元素进栈,n=10,2n=20,n+1=11,故卡特兰数为:
20 * 19 * 18 *… * 11
——————————
11 * 10 * … * 1
若要说写出具体的出栈顺序,只能枚举了,可以通过卡特兰数防止少写。

2. 栈的实现

C++STL中有几种栈的实现,作为新手,用用STL倒无可厚非,但是当实际遇到项目时,程序某些功能可能与这些栈不相匹配,导致程序性能不能进一步被开发,故还得自己设计和改进。

2.1栈方法

必须包括empty()、top()、push()、pop()的基本操作以及空栈的初始化。
1.构造函数
在这里插入图片描述
2.元素类型与泛型
我们用Stack_entry作为Stack栈中的类型,它可以是int,也可以是char。
typedef char Stack_entry;
对于不同的元素类型使用同样的基本数据结构和操作的能力称为泛型(generic)。

3.错误处理
使用单一的称为Error_code的枚举类型来报告所有来自于程序和函数的错误。

4.方法说明
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

2.2 类说明

//类定义一般放在stack.h中 
//相对应的代码文件称为stack.c 
const int maxstack = 10;

class Stack{
public:
	Stack();
	bool empty() const;
	Error_code pop();
	Error_code top(Stack_entry &item) const;
	Error_code push(const Stack_entry &item);
private:
	int count;
	Stack_entry entry[maxstack]; 
};
#include<stack.h>

Error_code Stack::push(const Stack_entry &item)
/* Pre: None.
   Post: If the Stack is not full, item is added to the top of the Stack. If the Stack
		 is full, an Error_code of overflow is returned and the Stack is left unchanged. */
{
	Error_code outcome=success;
	if(count>=maxstack)
		outcome=overflow;
	else
		entry[count++]=item;
	return outcome;
}

Error_code Stack :: pop( )
/* Pre: None.
   Post: If the Stack is not empty, the top of the Stack is removed. If the Stack is
         empty, an Error_code of underflow is returned. */
{
	Error_code outcome = success;
	if (count == 0)
		outcome = underflow;
	else --count;
	return outcome;
}

Error_code Stack ::top(Stack_entry &item) const
/* Pre: None.
   Post: If the Stack is not empty, the top of the Stack is returned in item. If the
		 Stack is empty an Error_code of underflow is returned. */
{
	Error_code outcome = success;
	if (count == 0)
		outcome = underflow;
	else
		item = entry[count - 1];
	return outcome;
}

bool Stack :: empty( ) const
/* Pre: None.
   Post: If the Stack is empty, true is returned. Otherwise false is returned. */
{
	bool outcome = true;
	if (count > 0) outcome = false;
	return outcome;
}

Stack :: Stack( )
/* Pre: None.
   Post: The stack is initialized to be empty. */
{
	count = 0;
}

只有pop、push、top三个方法的数据类型是Error_code,因为就这三个可能会出现错误和异常。

例题:
在这里插入图片描述
在这里插入图片描述

Error_code copy_stack(Stack &dest, Stack &source)
/* Pre: None.
Post: Stack dest has become an exact copy of Stack source; source is unchanged. If an error is
detected, an appropriate code is returned; otherwise, a code of success is returned. */
{
dest = source;
return success;
}
Error_code copy_stack(Stack &dest, Stack &source)
/* Pre: None.
Post: Stack dest has become an exact copy of Stack source; source is unchanged. If an error is
detected, an appropriate code is returned; otherwise, a code of success is returned. */
{
Error_code detected = success;
Stack temp;
Stack_entry item;
while (detected == success && !source.empty( )) {
detected = source.top(item);
detected = source.pop( );
if (detected == success) detected = temp.push(item);
}
while (detected == success && !temp.empty( )) {
detected = temp.top(item);
detected = temp.pop( );
if (detected == success) detected = source.push(item);
if (detected == success) detected = dest.push(item);
}
return detected;
}
Error_code copy_stack(Stack &dest, Stack &source)
/* Pre: None.
Post: Stack dest has become an exact copy of Stack source; source is unchanged. If an error is
detected, an appropriate code is returned; otherwise, a code of success is returned. */
{
dest.count = source.count;
for (int i = 0; i < source.count; i++)
dest.entry[i] = source.entry[i];
return success;
}

第一个版本当然是最容易编写的,如果堆栈几乎满了,它将运行得最快,因为编译器将生成机器代码比第三个方法的循环更快地复制所有条目。但是,如果堆栈更接近空,那么第三个方法将是最快的,因为它只复制占用的条目,而第一个方法复制数组中的所有位置,无论是否占用。由于所有函数调用,第二个版本可能运行最慢,但如果堆栈几乎为空,它可能会超过第一个版本。
当栈满的时候,都是要复制所有条目,编译器生成机器代码进行复制是最接近底层的,最快的。但是若栈更接近于空的时候,编译器生成机器代码还是一股脑的全复制,所以还是第三个方法快。

第二个版本独立于实现,因此,如果实现可能发生更改,则最好使用第二个版本。第一种方法将在链接实现中失败,因为它只会将变量source和dest设置为指向同一节点。因此,第一种方法不会制作新的堆栈副本;source和dest成为同一个堆栈,更改其中一个将更改另一个。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值