数据结构----栈(顺序栈、链栈、共享栈、判定操作序列合法性)操作

一、栈:

              只能在一端插入或删除的线性表,允许插入和删除操作的一端称为栈顶(top),栈底固定不变。

栈的操作:

                   入栈、出栈。

栈的特点:

                  先进后出,就像车队进入死胡同,只能后车先出。

栈的本质:

                  线性表

栈中n个元素的出栈序列种数:

                组合 C(2n,n)/(n+1)   = 2n! / (n!)^2 / (n+1)

二、顺序栈:

           实质是数组,需要连续的空间。

顺序栈的状态:

                栈空(top = -1)、栈满top = (MaxSize - 1)、非法状态(上溢、下溢)

上溢:

            栈满仍继续入栈

下溢:

            栈空仍出栈

顺序栈实现

#include<malloc.h>
#include<stdio.h>

//顺序栈:数组栈,用top指针,指向栈顶,判断栈是否为空或者栈满。 

#define MaxSize 10 //栈的空间

//栈 
typedef struct SequenceStack{
	int data[MaxSize];
    int top; //初始值为-1,表示栈空 
}SequenceStack;


//判断栈是否为空 
void isEmptyStack(SequenceStack stack)
{
	if(stack.top==-1)
	{
		printf("栈为空\n");
	}
	else{
		printf("栈不为空\n");
	} 
} 
//元素出栈操作
void popStack(SequenceStack &stack,int &k) //k表示要pop的元素返回处 
{
	if(stack.top!=-1)//栈不为空 
	{
		k=stack.data[stack.top];
		--stack.top; 
		printf("执行出栈操作,出栈元素%d\n",k);
	    return;
	}
	printf("执行出栈操作失败\n");
	return;
} 
//元素进栈操作
void pushStack(SequenceStack &stack,int k) //k表示要push进栈的元素 
{
	if(stack.top!=MaxSize-1)//栈不满 
	{
		stack.data[++stack.top]=k;
		printf("执行进栈操作,进栈元素%d\n",k);
		 return; 
	} 
	printf("未执行进栈操作\n");
	return;
} 

void printEle(SequenceStack stack)
{
	int i=0;
	printf("栈中元素:");
	while(i<stack.top+1)
	{
		printf("%d ",stack.data[i]);
		++i;
	}
	printf("\n");
}

//初始化顺序栈 
void initStack(SequenceStack &stack)
{
	stack.top=-1;//初始化栈顶 ,只向栈中添加 MaxSize-5 个元素 
	for(int i=0;i<MaxSize-5;++i)
	{
		pushStack(stack,i+1);//执行进栈操作 
	} 
	printf("初始化栈成功\n");
} 

int main()
{
	SequenceStack squ;
	initStack(squ);    //初始化栈 
	isEmptyStack(squ); //判断栈是否为空 
	printEle(squ);     //查看栈中元素 
	pushStack(squ,33); //元素进栈 
	printEle(squ);      
	int result=-1;      
	popStack(squ,result); //元素出栈 
	printEle(squ);  
	
} 



 顺序栈简单化

int stack[maxSize];
int top=-1;//初始化栈顶元素
//进栈
stack[++top]=x;
//出栈
ele=stack[top--];
//判空
top>-1?0:1;

三、链栈 :

            实质是一个链表,用头插法创建链栈,有一个头结点,头结点相当于链栈的栈顶指针,指向栈顶元素,控制着栈中元素的出入。(由于是动态创建,默认栈空间为无限大,不存在溢出情况)

链栈的状态:(默认内存无限大)

          栈空、栈满、

Coding

//链栈单个结点 ( 用带头结点的单链表作为存储体) 
typedef struct Node{
	int data; //数据域 
	struct Node *next; //指针域 
}StackNode;
 

//链栈进栈 
void pushChainStack(StackNode *&head,int data){
	StackNode *elem=(StackNode *)malloc(sizeof(StackNode));
	elem->data=data;
	elem->next=head->next;//将之前插入栈中的元素链在新加入的元素后面。 
	head->next=elem; //将head头指针,指向这个新加入的元素,代表栈顶。 
	printf("元素%d进栈成功\n",head->next->data);
} 
 
//链栈出栈
void popChainStack(StackNode *&head){
        if(head->next==NULL)
	{
	     printf("栈空\n");
	     return;
	}
	StackNode *elem;
	elem=head->next;
	head->next=elem->next;//将栈顶指向下一个元素。 
	printf("元素%d出栈成功\n",elem->data);  
	free(elem);//释放栈顶元素,表示出栈 
} 

//因为栈只有一端能进行操作,因此采用头插法创建链栈,head即栈顶。 
void initChainStack()
{
	StackNode *head;
	head=(StackNode *)malloc(sizeof(StackNode));
	head->next=NULL;
	int data[3]={1,2,3};//即将进栈的数据
	for(int i=0;i<3;i++)
	{
		pushChainStack(head,data[i]);//元素进栈 
	}  
	for(int i=0;i<3;i++)
	{
		popChainStack(head);//元素出栈 
	}  
} 

int main()
{
	initChainStack();//链栈
} 

四、共享栈

    两个顺序栈共享一片连续的储存空间,两个栈的栈底分别位于储存空间的两端,栈顶在储存空间内,当两个栈顶相遇时,表示储存空间用尽,栈溢出(上溢)。

目的:提高内存利用率减少溢出可能性。

五、栈操作序列合法判定

   给定序列是否合法规则( “I”表示进栈,“O”表示出栈 ):1.在给定操作序列中I的个数与O个数相等

                                                                                             2.给定序列开始到给定序列任意位置I个数大于等于O个数

void sequenceValid(char op[]) //op表示操作序列,I进栈,其它字符表示出栈
{
	int res=0; //存储栈中情况 
	int i=-1,j;
	while(op[++i]!='\0')
	{
		if(res<0) //当情况为负值即序列出栈数多于进栈数 或者 出栈的时候栈中元素为空 
		{
			printf("序列不合法\n");
			return;
		}
		if(op[i]=='I') //为I表示进栈 
		{
			res++;
		}
		else  //其他情况表示出栈 
		{
			res--;
		}
	}
	if(res!=0) //整个操作最终让栈空。res==0 
	{
		printf("序列不合法\n");
		return;
	}
	printf("序列合法\n");
 } 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值