链栈

栈属于一种操作受限的线性表,自然也有顺序和链式之分,采用链式存储结构存储的栈称之为链栈,在前面学习链表时,介绍过头插法建表的方法,当时特别强调表的顺序和原序列相反。正好符合栈后进先出的特性。下面的链式存储结构即为采用头插法建立的链表

  • 栈空条件:s->next == NULL

  • 栈满条件:由于采用链式存储结构,不考虑

  • 入栈:将新元素插到头结点后面
    在这里插入图片描述

  • 出栈:取出头结点之后的结点并删除之
    在这里插入图片描述

链栈的存储结构

typedef struct _linkStack{
	ElemType data;
	struct _linkStack *next;
}linkStack;

链栈的基本运算

链栈的基本运算和单链表一致,不需要单独掌握

初始化

void
initStack( linkStack **s )
{
	*s = ( linkStack* )malloc( sizeof( linkStack ) );
	(*s)->next = NULL;
}

销毁

void
destroyStack( linkStack *s )
{
	linkStack *t;
	for( s; s != NULL; s = t ){
		t = s->next;
		free( s );
	}
}

判断是否为空

int
stackEmpty( linkStack *s )
{
	return ( s->next == NULL );
}

入栈

void
push( linkStack *s, char e )
{
	linkStack *t;
	t = ( linkStack* )malloc( sizeof( linkStack ) );
	t->data = e;
	t->next = s->next;
	s->next = t;
}

出栈

int
pop( linkStack *s, char *e )
{
	linkStack *t;
	if( s->next == NULL ){
		return FALSE;
	}
	t = s->next;
	*e = t->data;
	s->next = t->next;
	free( t );
	return TRUE;
}

取得栈顶元素

int
getTop( linkStack *s, char *e )
{
	if( s->next == NULL ){
		return FALSE;
	}
	*e = s->next->data;
	return TRUE;
}

栈的应用:判断表达式的括号是否配对

给定一个只有小括号的表达式,要求设计算法判断左右括号是否配对

基本的思路是遇见左括号就进栈,遇见右括号就出栈

  • 若遍历完表达式后栈不为空,则说明表达式有多余的左括号
  • 若程序试图对空栈执行出栈操作说明有多余的右括号
  • 当遍历完表达式后栈为空,且没有尝试过对空栈执行出栈操作,则说明表达式左右括号配对
	int i;
	char e;
	int right = TRUE;
	char str[] = "(((( 3 * ( 1 + 2 ) )))";
	
	linkStack *s;
	initStack( &s );
	
	for( i = 0; str[i] != '\0'; i++ ){
		if( str[i] == '(' ){
			push( s, str[i] );
		}else if( str[i] == ')' ){
			if( pop( s, &e ) == FALSE ){
				right = FALSE;
				break;
			}
		}
	}

	if( stackEmpty( s ) && right ){
		printf("Pass");
	}else{
		if( right ){
			printf("Error : 多余的左括号\n");
		}else{
			printf("Error : 多余的右括号\n");
		}
	}
	
	destroyStack( s );
posted @ 2020-07-17 20:04  LanceHansen  阅读(60)  评论(0编辑  收藏  举报