顺序栈
栈的定义
栈是一种只能在一端进行插入或删除操作的线性表
 
- 允许进行插入、删除操作的一端称为栈顶
- 表的另一端称为栈底
- 当栈中没有数据元素时,称为空栈
- 栈的插入操作通常称为进栈或入栈
- 栈的删除操作通常称为退栈或出栈
栈的主要特点是后进先出(Last In First Out),即后进栈的元素先出栈,栈也称后进先出表(LIFO表)
进栈出栈的变化形式
栈对线性表的插入和删除的位置进行了限制,并没有对元素进出的时间进行限制,也就是说进栈和出栈的操作是可以交替进行的,只要保证是栈顶的元素就可以出栈。
 以下面的输入顺序为例
 
     
      
       
        
         1
        
        
         ,
        
        
         2
        
        
         ,
        
        
         3
        
       
       
         1,2,3 
       
      
     1,2,3
 第一种情况:输出321
 
 第二种情况:输出123
 
 第三种情况:输出213
 
 第四种情况:输出132
 
 第五种情况:输出231
 
 按照排列组合的公式,3个元素应该有6种排列形式
 
     
      
       
        
         
          A
         
         
          3
         
         
          3
         
        
        
         =
        
        
         3
        
        
         !
        
        
         =
        
        
         6
        
       
       
         A^3_3 = 3!=6 
       
      
     A33=3!=6
 还有一种排列情况是312,这种情况有没有可能呢?
 显然,当第一个出栈元素是3的时候,1被2压住了,1不可能是第二个出栈的元素,所以不存在312这种输出结果。
出 栈 序 列 的 个 数 计 算 公 式 C a t a l a n 数 1 n + 1 C 2 n n = 1 n + 1 × ( 2 n ) ! n ! × n ! 出栈序列的个数计算公式\\ Catalan数\\ \frac 1 {n+1}C^n_{2n}=\frac 1{n+1} \times \frac {(2n)!} { n! \times n!} 出栈序列的个数计算公式Catalan数n+11C2nn=n+11×n!×n!(2n)!
例1
设一个栈的输入序列为a,b,c,d,栈的输出序列不可能是
 A. c,d,b,a
 B. d,c,b,a
 C. a,c,d,b
 D. d,a,b,c
比较难想象的是A和C

 
 对于D来说,如果先出去的是d,这意味这a和b都被c堵着,没办法先出,所以D的输出顺序是不可能的。
例2
一个栈的入栈序列为1,2,3,…,n,其出栈序列是p1,p2,p3,…,pn。若p1 = 3,则p2可能取值的个数是
显然这道题目中,进栈的同时也会出栈,先按照1,2,3的顺序进栈,然后3出栈,后面的操作,可能是
- 2出栈,1种可能
- 新的元素进栈后出栈(n - 3种可能)
3已经出栈了,减去
 1被2压住,没办法第二个出栈
 所以可能性是n-2
栈的顺序存储结构
typedef struct _sqStack{
	ElemType data[ MAX_SIZE ];
	int top;
}sqStack;
用数组作为栈的空间,top指向了栈顶的位置
- 建立一个空栈时,top初始化为-1
- 当top == MAX_SIZE - 1时,栈满
- 进栈top++,出栈top--
顺序栈的基本运算
初始化栈
void
initStack( sqStack **s )
{
	*s = ( sqStack* )malloc( sizeof( sqStack ) );
	(*s)->top = -1;
}
销毁栈
void
destroyStack( sqStack *s )
{
	free( s );
}
判断栈是否为空
int
stackEmpty( sqStack *s )
{
	return ( s->top == -1 );
}
进栈
先判断栈是否为满,为满返回FALSE,还有空间时,让top指向下一个位置,将新元素压入栈,返回TRUE
#define TRUE	1
#define FALSE	0
int
push( sqStack *s, int e )
{
	if( s->top == MAX_SIZE - 1 ){
		return FALSE;
	}
	s->data[ ++s->top ] = e;
	return TRUE;
}
出栈
先判断栈是否为空,为空返回FALSE,不为空把栈顶元素取出并弹出,返回TRUE
#define TRUE	1
#define FALSE	0
int
pop( sqStack *s, int *e )
{
	if( s->top == -1 ){
		return FALSE;
	}
	*e = s->data[ s->top-- ];
	return TRUE;
}
取栈顶元素
先判断栈是否为空,为空返回FALSE,不为空把栈顶元素取出,返回TRUE
#define TRUE	1
#define FALSE	0
int
getTop( sqStack *s, int *e )
{
	if( s->top == -1 ){
		return FALSE;
	}
	*e = s->data[ s->top ];
	
	return TRUE;
}
两栈共享空间
要实现两个相同类型的栈,最简单粗暴的方法就是分别做两个数组,还有一种比较巧妙的方法是让两个栈共用一个空间,即在一个数组中存储两个栈。

 两个栈从两端向中间生长,只要它们两个不相遇,栈就可以一直使用。
typedef struct _dsqStack{
	ElemType data[ MAX_SIZE ];
	int top1;
	int top2;
}dsqStack;
top1指向了栈1的栈顶,top2指向了栈2的栈顶
- 建立一个空栈时,top1初始化为-1,top2初始化为MAX_SIZE
- 栈1进栈top1++,出栈top1--
 栈2进栈top2--,出栈top2++
- 当top2 - top1 == 1,两个栈都满
初始化
void
initDstack( dsqStack **s )
{
	*s = ( dsqStack* )malloc( sizeof( dsqStack ) );
	(*s)->top1 = -1;
	(*s)->top2 = MAX_SIZE;
}
进栈
int
push( dsqStack *s, int stack_tag, int e )
{
	if( 1 == s->top2 - s->top1 ){
		return FALSE;
	}
	if( 1 == stack_tag ){
		s->data[ ++s->top1 ] = e;
	}else{
		s->data[ --s->top2 ] = e;
	}
	return TRUE;
}
出栈
int
pop( dsqStack *s, int stack_tag, int *e )
{
	if( 1 == stack_tag ){
		if( -1 == s->top1 ){
			return FALSE;
		}else{
			*e = s->data[ s->top1-- ];
		}
	}else{
		if( MAX_SIZE == s->top2 ){
			return FALSE;
		}else{
			*e = s->data[ s->top2++ ];
		}
	}
	return TRUE;
}
栈的应用:判断回文序列
	int i;
	int flag = TRUE;
	char str[] = "AGCTTCGA";
	const char *info[] = { "NO", "YES" };
	sqStack *s;
	initStack( &s );
	for( i = 0; i < strlen( str ); i++ ){
		if( push( s, str[i] ) == FALSE ){
			printf("栈上溢出");
			break;
		}
	}
	for( i = 0; i < strlen( str ); i++ ){
		char temp;
		if( pop( s, &temp ) == FALSE ){
			printf("栈下溢出");
			break;
		}
		if( str[i] != temp ){
			flag = FALSE;
			break;
		}
	}
	printf("%s\n", info[ flag ] );

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号