数据结构——堆栈
(一)堆栈
1.定义:
栈的定义:栈是插入和删除只能在其一端进行的线性表。并按后进先出的原则进行操作。
栈顶:进行插入、删除的一端;
栈底:另一端;
空栈:表中没有元素时。
2.特性:后进先出性、封闭性
3.基本操作:
(1)栈初始化
(2)进栈 Push
(3)出栈 Pop
(4)读取栈顶元素 Peek
(5)判栈空 StackEmpty
(6)判栈满 StackFull
(7)置空栈
(二)顺序栈
1.定义
顺序栈AStack的类定义
template < class T >
class AStack {
private:
int size ; // 数组的规模
T * stackArray ; // 存放堆栈元素的数组
int top ; // 栈顶所在数组元素的下标
public:
AStack ( int MaxStackSize ) // 构造函数
{ size = MaxStackSize ; stackArray = new T [MaxStackSize] ; top = -1 ; }
~AStack ( ) { delete [ ] stackArray ; } // 析构函数
bool Push ( const T& item ) ; // 向栈顶压入一个元素
bool Pop ( T & item ) ; // 从栈顶弹出一个元素
bool Peek ( T & item ) const ; // 存取栈顶元素
int IsEmpty ( void ) const { return top = = -1 ; } // 检测栈是否为空
int IsFull ( void ) const { return top size 1 ; } // 检测栈是否为满
void clear ( void ) { top1 ; } // 清空栈
} ;
2.入栈
bool Stack<T>::Push(const T &item)
{
if(isFull())
return false;
StackArrayt[++top]=item;
return true;
}
3.出栈
bool Stack<T>::Pop(const T &item)
{
if(isEmpty())
return false;
item=StackArray[top--];
return true;
}
bool Stack<T>::Peek( T & item)
{
if(isEmpty())
return false;
item=StackArray[top];
return true;
}
(三)链式栈
1.定义
template < class T >
class LStack{
private :
SLNode <T> * top ; // 栈顶指针指向表头
public :
LStack ( ) { top = NULL ; } // 构造函数
~LStack ( ) { clear ( ) ; } // 析构函数
void clear ( ) ; // 清空栈
bool Push ( const T& item ) ; // 向栈顶压入一个元素
bool Pop ( T & item ) ; // 从栈顶弹出一个元素
bool Peek ( T & item ) const ; // 读取栈顶元素
int IsEmpty ( void ) const { return top = = NULL ; } // 检测栈是否为空
} ;
2.入栈
bool Push(const T&item)
{
top=new SLNode<T> (item,pop);
return true;
}
3.出栈
bool Pop(const T&item)
{
if(isEmpty()) {
cout<<"Poping from an empty stack!"<<endl;
return false;
}
item =top->data;
SLNode<T> *temp=top;
top=top->next;
delete temp;
return true;
}
(代码懒得贴了)
(四)顺序栈和链式栈的比较
1.在空间复杂性上,顺序栈必须初始就申请固定的空间,当栈不满时,必然造成空间的浪费;链式栈所需空间是根据需要随时申请的,其代价是为每个元素提供空间以存储其next指针域。
2.在时间复杂性上,对于针对栈顶的基本操作(压入、弹出和栈顶元素存取),顺序栈和链式栈的时间复杂性均为O(1) .
(五)堆栈的应用
1.括号匹配问题:
高级语言程序设计中的各种括号应该匹配,例如:“(” 与 “)”匹配、“[”与 “]” 匹配、“{”与 “}” 匹配等。字符串{a=(b*c}+free( ) ]中的括号就没有匹配上,因为串中第一个关括号 “}” 和最近的未匹配开括号 “(” 不匹配。
void main ( )
{
LStack<char> bracket ; // 声明一个链式栈对象
char read_in = cin.get() ;
bool is_matched = true ;
while ( is_matched && read_in != '\n')
{
if ( read_in = = '{' || read_in = = '[' || read_in = = '(' ) /*若输入开括号,则将其压入栈*/
bracket.push ( read_in ) ;
else if ( read_in = = '}' || read_in = =']' || read_in = = ')' ) /* 若输入关括号,则检测是否匹配*/
{
if ( bracket. IsEmpty () )
{ cout << “Unmatched closing bracket ” << read_in << “is
detected”<<endl ;
is_matched = false ; return ;
}
char open_bracket ;
bracket.pop (open_bracket) ;
is_matched = ( open_bracket = = '(' && read_in = = ')' )|| ( open_bracket = ='[' && read_in = = ']' ) || ( open_bracket = = '{' && read_in = = '}' )
if ( ! is_matched )
{
cout<< “Bad match ”<< read_in<<open_bracket<<endl ;
return ;
}
}
read_in = cin.get() ;
}
// 若堆栈中仍有开括号,说明匹配失败,因为已无关括号与之匹配
if ( ! bracket. IsEmpty () )
cout<< “Unmatched opening bracket detected. ”<<endl ;
return ;
}
2.将十进制数转换成其它进制数
(1)步骤
a.十进制整数 x 除以基数 r,所得整余数是 r 进制数 y 的最低位 y0,放入堆栈;
b.用 x除以 r 的整数商,除以 r,所得整余数是 y 的次低位 y1,放入堆栈;
c.依此类推,
d.直到商为 0 ,所得整余数是 y 的最高位ym,放入堆栈;
e.此时,栈中的 m+1 个 r 进制数即为所得。
(2)实现
#include <stdio.h>
#include <malloc.h> //malloc
#include <math.h> //含有overflow
#define S_SIZE 100 //栈的空间大小
typedef struct SqStack{
int top; //栈顶
int maxtop; //栈最大的存储空间
int *stack;
}SqStack;
//初始化空栈
void InitStack(SqStack &S)
{
S.stack=(int *)malloc(S_SIZE*sizeof(int)); //动态申请一维数组
S.maxtop=S_SIZE;
S.top=-1;
}
//判断空栈
int StackEmpty(SqStack &S)
{
if(S.top==-1)
return 1;
else
return 0;
}
//判断栈满
int StackFull(SqStack &S)
{
if(S.top==S.maxtop)
return 1;
else
return 0;
}
//进栈
void push(SqStack &S,int x)
{
if(StackFull(S))
printf("overflow\n");
S.stack[++S.top]=x;
}
//出栈
int pop(SqStack &S)
{
int x;
if(StackEmpty(S))
printf("underflow\n");
x=S.stack[S.top];
S.top--;
return x;
}
//进制转化函数
void convert(SqStack &S,int N,int n)
{
int i,x;
do
{
push(S,N%n);
N/=n;
} while (N!=0);
while(!StackEmpty(S))
{
x=pop(S);
if(x>9) //十六进制时输出字母
{
x=x+55;
printf("%c",x);
}
else
printf("%d",x);
}
printf("\n");
}
//清空栈
void StackClear(SqStack &S)
{
S.top=-1;
}
int main()
{
int n,N;//要转换成的进制数和要转换的数
SqStack s;
scanf("%d%d",&n,&N) ;
InitStack(s);
printf("%d转换为%d进制后为:\n",n,N);
convert(s,n,N);
StackClear(s);
return 0;
}