【考研】栈和栈的应用

因为今年考研的原因,所以就根据王道后面的习题进行总结
大致归类了一些顺序、链表存储结构、基本算法实现代码合集,也是为了后续方便复习


1.1顺序栈


1.1.1结点结构

#define MaxSize 50 //定义栈中元素的最大个数
typedef struct 
{
	ElemType data[MaxSize] ;//存放栈中元素 
	int top ;//栈顶指针
	ElemType base;	//栈底指针
	int StackSize	//	栈长
}SqStack; //顺序栈的简写

1.1.2基本操作

(1)初始化
//初始化顺序栈,构造一个空栈
void InitSqStack (SqStack &S){
	S.top = -1;		//初始化栈顶指针
}
(2)空栈
bool StackEmpty(SqStack S){
	if(s.top == -1) return true ;
	else return false ;
}
(3)满栈
//判断是否为满栈
void judgeFull(SqStack &s){
	if(s.top-s.base == s.StackSize){
		printf("栈满!\n");
	}else{
		printf("栈未满!\n");
	} 
}
(4)入栈
bool Push(SqStack &S , ElemType x){
	if(S.top == MaxSize-1) return false ;
	S.data[++top] = x ; 
	return true ;
}
(5)出栈
bool Pop(SqStack &S,ElemType &x) {
	if(S.top == -1) return false ;
	x = S.data[top--] ;
	return true ;
}
(6)读取栈顶元素
bool Pop(SqStack &S , ElemType &x){
	if(s.top == 1)
		return false;
	x = S.data[top];
	return true;
}

1.2链表栈


1.2.1结点结构

typedef struct SNode
{
	ElemType data ;//存放栈中元素 
	struct SNode *next ; //栈顶指针 
}SNode , *SLink; //链栈的结点 

typedef struct LinkStack
{
	Slink top ; //栈顶指针 
	int count ; //链栈结点数 
}LinkStack, *SqStack; //链栈

1.2.2基本操作


(1)进栈
bool Push(LinkStck &S , ElemType x){
	SLink p = (Slink*)malloc(sizeof(Slink));//给新元素分配空间
	p->data = x;			//新元素的值
	p->next = S->top;		//p的后继指向栈顶元素
	S->top = p;				//栈顶指针指向新的元素
	S->count++;				//栈中元素个数加1
	return true;
}
(2)出栈
bool Pop(LinkStack *S , ElemType &x) {
	if(S->top == NULL) return false ;
	x = S->top->data ;			  //栈顶元素值 
	Slink p = S->top ;			 //辅助指针 
	S->top = S->top->next ; 	  //栈顶指针后移
	free(p);			 //释放被删除数据的存储空间 
	S->count-- ;			//栈中元素个数减一 
	return true ;
}

1.3共享栈


1.3.1数据结构

#define MaxSize 100	//定义栈中元素的最大个数
typedef struct{
	ElemType daata[MaxSize];	//存放栈中元素
	int top1;	//栈1栈顶指针
	int top2;	//栈2栈顶指针
}SqDoubleStack;	//顺序共享栈的缩写

1.3.2基本操作


(1)进栈
bool Push(SqDoubleStack &S ,ElemType x , int stackNum){
	if(S.top1+1 == S.top2)
		return false;		//栈满
	if(stackNum == 1)		//栈1有元素进栈
		S.data[++top1] = x;
	else(stackNum == 2)		//栈2有元素进栈
		S.data[--top2] =x;
	return true;
}
——————————————————————————————————————————————————
——————————————————————————————————————————————————
int push(int i , elemType x){
//入栈,i为栈号,i=0表示左边的s1栈,i=1表示右边的s2栈,x是入栈元素 
//入栈成功则返回1,否则返回0 
	if(i<0 ||i>1){
		printf("栈号输入不对\n");
		exit(0); 		
	}
	if(S.top1 - S.top2 = 1){
		printf("栈已满\n")
		exit(0);
	}
	switch(i){
		case 1 : S.data[++top1];
			return 1;
			break;
		case 2 : S.data[++top2];
			return 1;
	}
}
(2)退栈
int pop(int i){
//退栈算法,i代表栈号,i=0时s1栈,i=1时为s2栈
//退栈成功则返回退栈元素,否则返回-1 
	if(i<0 ||  i>1){
		printf("栈号输入错误\n");
		exit(0);
	} 
	switch(i){
		case 0:
			if(top1 == -1 ){
				printf("栈空\n");
				exit(-1);
			}
			else
				return S.data[top1 --];
		case 1:
			if(top2 == MaxSize){
				printf("栈空\n");
				return -1;
			}
			else
				return S.data[top2++];
	}
}

2.算法


2.1判断是否为合法序列

I为进栈,O为出栈,计算入栈出栈的次数,进行对比来判断,序列为A数组。

bool JudgeStck(char A[]){
	int i=0;	//记录数组的下标 
	int j=0;	//记录入栈次数 
	int k=0;	//出栈的次数 
	while(A[i] != '\0'){
		switch(A[i]){
			case 'I' j++ ; break;	//入栈加1 
			case 'O' k++ ; break;	//出栈加1 
				if(k>j)
					return false;
		}
		i++;
	}
	if(j != k){
		printf("非法序列\n");
		return false;
	}
	else
		printf("合法序列\n");
		return true;
}

2.2链表是否中心对称

int compareStack(LinkList &L , int n){
//L是具有带头结点的带n个元素的单链表,本算法检测是否中心对车 
	int i;					//记录栈里面的数值 
	char s[n/2]; 			//s字符栈
	LNode *p = L->next;	//p是工作指针,指向待处理的元素 
	for(i = 0 ; i<n/2 ;i++){//链表前一半入栈 
		s[i] = p->data;
		p = p->next;
	} 
	i--;			//恢复到最后的i值
	if(n%2 == 1 )	//若链表是奇数链,则后移中心点 
		p = p->next;
	while( p!= NULL && s[i] ==p->data){	
	//检测是否是中心对称 
		i--;
		p = p->next;
	}	 
	if(i == -1)			//栈为空栈 
		return 1;		//中心对称 
	else				//非空 
		return 0;		//中心不对称 
}

2.3两个栈模仿队列:入队,出队

入队

bool Enqueue(SqStack &S1,SqStack &S2 , int x){//S1入队,S2出队 
	if( !JudgeFull(S1)){		//确保S1非满才能弹出 
		Push(S1 , x);
		return 1;	 
	}
	if(JudgeFull(S1) && !StackEmpty(S2)){
		printf("栈满\n");
		return 0; 
	}
	if(StackEmpty(S2) && !JudgeFull(S1) ){
		while(!StackEmpty(S1)){
			Pop(S1 , x);
			Push(S2 ,x);
		}
	}
	Push(S1 ,x);
	return 1;
}

出队

bool DeQueue(SqStack &S1 , SqStack &S2 , int x){
	if(!StackEmpty(S2)){
		Pop(S2 , x);
	}
	else if(StackEmpty(S1)){
		printf("队空\n");
	}
	else{
		while(!StackEmpty(S1)){
			Pop(S1 ,x);
			Push(S2 , x);
		}
	Pop(S2 ,x):
	}
} 

2.4括号匹配

bool Check(char *str){
	Stack s ;
	InitStck(s) ;
	int len = strlen(str) ; //字符串长度为len 
	for (int i = 0; i<len ; i++)
	{
		char a = str[i] ;
		swith(a){
			case '(':
			case '[':
			case '{':
				Push(s,a) ;
				break ;
			case ')':
				if(Pop(s) != '(' ) 
					return false ; //出栈顶。如果不匹配直接返回不合法 
				break ;
			case ']':
				if(Pop(s) != '[' ) return false ;
				break ;
			case '}':
				if(Pop(s) != '{' ) return false ;
				break ;
		}
	}
	if(Empty(s)) return true ;//匹配完所有括号最后要求栈中为空 
	else return false ;
}

2.5火车变轨换座问题

void Train_Arranger(char *train){
//用train表示火车H为硬座,S为软座
	char *p = train , *q = train , c;
	SqStack S;
	InitStack(S);
	while(*p){
		if( p == 'H'){
			Push(S , p);	//把H存入栈中 
		}
		else
			*(q++) = *p;	//把S接在前部 
		p++;
	}
	while(!StackEmty(S)){
		Pop(S , c);
		*(p++) = *c;		//把H接在后部 
	}		
}

非递归运算——用栈实现
在这里插入图片描述

struct Recursion {
	int no;		//保存n
	int val;	//保存Pn(x)值
};
struct Stack {
	Recursion *arr;
	int len;
	int top;
};
int getP(Stack *s,int n,int x) {//该算法函数,传入栈,n和x
	if (n==0) {
		return 1;
	}
	int fv1 = 1, fv2 = 2*x;
	for (int i = n; i >= 2;i--) {
	//将序号入栈,从上至下,从2到n
		s->top++;
		s->arr[s->top].no = i;
	}
	while (s->top>=0) {//边出栈边计算
		s->arr[s->top].val = 2 * x*fv2 - 2 * (s->arr[s->top].no - 1)*fv1;
		fv1 = fv2;
		fv2 = s->arr[s->top].val;
		s->top--;
	}
	return fv2;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值