栈 知识点

本文详细介绍了栈这种数据结构,包括其基本概念、顺序存储和链式存储的实现方式。顺序栈使用静态数组实现,初始化时top设为-1或0,进栈、出栈、读栈顶元素的操作以及如何判断栈空栈满。链式栈则分为不带头结点和带头结点两种情况。此外,文章还提及了共享栈的概念,以及栈的销毁过程。
摘要由CSDN通过智能技术生成

栈的基本概念

线性表是具有相同数据类型的n个数据元素的有限序列,其中n为表长。
是只允许在栈顶进行插入或删除操作的线性表
在这里插入图片描述
如洗的盘子和 插肉串
在这里插入图片描述
栈顶:允许插入和删除的一端
栈底:不允许插入和删除的一端
在这里插入图片描述
特点:后进先出 Last In First Out(LIFO)

栈的基本操作
在这里插入图片描述
如果出栈操作和进展操作交叉进行,则会有多种出栈顺序。
n个不同的元素进栈,出栈元素不同排列的个数为
在这里插入图片描述

栈的顺序存储实现

顺序存储,用静态数组实现,并需要记录栈顶指针
顺序栈:用顺序存储方式实现的栈
基本操作:

  1. 创(初始化)
  2. 增(进栈)
  3. 删(出栈)
  4. 查(获取栈顶元素)
  5. 判空、判满

顺序栈的定义

#define MaxSize 10		//栈中元素的最大个数 
typedef struct{
	int data[MaxSize];	//静态数组存放栈中元素	 
	int top;			//栈顶指针 
}SqStack;				//sq:sequence
 
void InitStack(SqStack &S){
	S.top=-1;
}

bool StackEmpty(SqStack S){
	return (S.top==-1);
}

int main(){
	SqStack S;
	InitStack(S);
}

top指向栈顶元素,如果此时存入了五个元素,则top=4.(数组下标)
top指针不能指向0,因为此时data[0]还没有储存元素,因此可以把top的值设为负一。
要判断栈是否为空,只要看top的值是否为负一即可。
在这里插入图片描述

进栈操作

首先要判断栈是否已满,然后将指针加1,令新元素入栈
在这里插入图片描述

#define MaxSize 10		//栈中元素的最大个数 
typedef struct{
	int data[MaxSize];	//静态数组存放栈中元素	 
	int top;			//栈顶指针 
}SqStack;				//sq:sequence
 
void InitStack(SqStack &S){
	S.top=-1;
}

bool StackEmpty(SqStack S){
	return (S.top==-1);
}

bool Push(SqStack &S,int x){	//新元素入栈 
	if(S.top==MaxSize-1)	//栈满 
		return false;
	S.top=S.top+1;			//指针先加1 
	S.data[S.top=x];		//新元素入栈 
	//更简洁的写法:
	//S.data[++S.top]=x;
	return true; 
}

int main(){
	SqStack S;
	InitStack(S);
	Push(S,1); 
}

出栈操作

Pop(SqStack &S,int &x)中x有&,
出栈函数的调用者首先会在自己得函数里面定义一个变量,存放在内存中的某一个位置,加了引用符号后,在出栈操作里面的变量x和函数调用者定义的x对应的是同一份数据而不是复制品。
在这里插入图片描述

#define MaxSize 10		//栈中元素的最大个数 
typedef struct{
	int data[MaxSize];	//静态数组存放栈中元素	 
	int top;			//栈顶指针 
}SqStack;				//sq:sequence
 
void InitStack(SqStack &S){
	S.top=-1;
}

bool Pop(SqStack &S,int &x){
	if (S.top==-1)	//栈空,报错 
		return false;
	x=S.data[S.top];	//栈顶元素先出栈
	S.top=S.top-1;	//指针再减1 
	//等价于
	//x=S.data[S.top--]; 
	return true; 
} 

删除后数据还残留在内存中,只是逻辑上被删除了。
x=S.data[–S.top];等价于 S.top=S.top-1; x=S.data[S.top];

读栈顶操作

与出栈操作几乎一样,只是top不用- -

#define MaxSize 10		//栈中元素的最大个数 
typedef struct{
	int data[MaxSize];	//静态数组存放栈中元素	 
	int top;			//栈顶指针 
}SqStack;				//sq:sequence

bool GetTop(SqStack S,int &x){
	if(S.top==-1)
		return false;
	x=S.data[S.top]	;		//x记录栈顶元素
	return true; 
}


另一种方式 top=0而不是-1

top指针初始指向0,此时指向了下一个可以插入元素的位置
在这里插入图片描述
在这里插入图片描述

#define MaxSize 10		//栈中元素的最大个数 
typedef struct{
	int data[MaxSize];	//静态数组存放栈中元素	 
	int top;			//栈顶指针 
}SqStack;				//sq:sequence
 
void InitStack(SqStack &S){
	S.top=0;		//初始化栈顶指针指向0 
}

bool StackEmpty(SqStack S){
	return (S.top==0);
}

bool Push(SqStack &S,int x){	//新元素入栈 
	if(S.top==MaxSize)	//栈满 
		return false;
	S.data[S.top++]=x;
	return true; 
}

bool Pop(SqStack &S,int &x){
	if (S.top==0)	//栈空,报错 
		return false;
	x=S.data[--S.top]; 
	return true; 
} 

bool GetTop(SqStack S,int &x){
	if(S.top==0)
		return false;
	x=S.data[S.top]	;		//x记录栈顶元素
	return true; 
}

int main(){
	SqStack S;
	InitStack(S);
	Push(S,1); 
}

共享栈

顺序栈的缺点:栈的大小不可变
共享栈:两个栈共享同一片存储空间
栈满的条件:top0+1==top1
在这里插入图片描述
往0号栈放入数据元素,栈顶是从下往上依次递增
往1号栈放入数据元素,栈顶是从上往下依次递增
在这里插入图片描述

#define MaxSize 10		//栈中元素的最大个数 
typedef struct{
	int data[MaxSize];	//静态数组存放栈中元素	 
	int top0;			//0号栈栈顶指针 
	int top1;			//1号栈栈顶指针 
}ShStack; 
 
void InitStack(SqStack &S){
	S.top0=0;		//初始化栈顶指针
	S.top1=MaxSize;
}


销毁顺序栈

1.逻辑上清空一个栈 令top=-1 指向初始化的位置
2.回收这个栈所占用的内存资源 使用的是变量声明分配内存空间,没有使用malloc函数,故函数运行结束后系统自动回收内存。

在这里插入图片描述

栈的链式存储实现

出栈/进栈都只能在栈顶一端进行(链头作为栈顶)

typedef struct LinkNode{
	int data;			//数据域 
	struct LinkNode *next;	//指针域 
}*LiStack;				//栈类型定义 

栈的基本操作:

  • 初始化
  • 进栈
  • 出栈
  • 获取栈顶元素
  • 判空、判满

不带头结点:

#include<stdio.h>
#include<stdlib.h> 
#include<assert.h>

typedef struct LinkNode{
	int data;			//数据域 
	struct LinkNode *next;	//指针域 
}Linode,*LiStack;				//栈类型定义 

//初始化 
bool InitStack(LiStack &L){		
	L=NULL;		//防止脏数据 
	return true;
}

//判空 
bool isEmpty(LiStack L){
	return (L==NULL);
} 

//进栈
void PushStack(LiStack &L){
	int x;
	scanf("%d",&x);
	while(x!=9999){
		Linode *p=(Linode *)malloc(sizeof(Linode));
		assert(p);
		p->data=x;
		p->next=L;	//不带头结点 
		L=p;
		scanf("%d",&x);
	}
}
//出栈 
bool PopStack(LiStack &L,int &x){
	Linode *p;
	if(L){
		p=L;
		x=p->data;
		L=L->next;
		free(p);
		return true;
	}
	return false;
}
//获取栈顶元素 
bool GetStack(LiStack &L,int &x){
	if(L){
		x=L->data;
		return true;
	}
	return false;
}
//求表长
int StackLength(LiStack L)
{
    int count = 0;
    Linode *p=L;
    while (p)
    {
        count++;
        p = p->next;
    }
    return count;
}

//打印链栈
void PrintStack(LiStack L){
	if(L){
		while(L){
			printf("%d ",L->data);
			L=L->next;
		}
		printf("\n");
	}
} 
 
int main(){
	LiStack L;
	InitStack(L);
	printf("%d\n",isEmpty(L));
	PushStack(L);
	int x;
	int a;
	printf("%d\n",PopStack(L,x));
	printf("%d\n",x);
	printf("%d\n",GetStack(L,a));
	printf("%d\n",a);
	printf("%d\n",StackLength(L));
	PrintStack(L);
}

带头结点:

#include<stdio.h>
#include<stdlib.h> 
#include<assert.h>

typedef struct LinkNode{
	int data;			//数据域 
	struct LinkNode *next;	//指针域 
}Linode,*LiStack;				//栈类型定义 

//初始化 
bool InitStack(LiStack &L){		
	L=(Linode *)malloc(sizeof(Linode));
	if(L==NULL){
		return false;
	}
	L->next=NULL;		//防止脏数据 
	return true;
}

//判空 
bool isEmpty(LiStack L){
	return (L->next==NULL);
} 

//进栈
void PushStack(LiStack &L){
	int x;
	scanf("%d",&x);
	while(x!=9999){
		Linode *p=(Linode *)malloc(sizeof(Linode));
		assert(p);
		p->data=x;
		p->next=L->next;	//带头结点 
		L->next=p;
		scanf("%d",&x);
	}
}
//出栈 
bool PopStack(LiStack &L,int &x){
	Linode *p;
	if(L){
		p=L->next;
		x=p->data;
		L->next=L->next->next;
		free(p);
		return true;
	}
	return false;
}
//获取栈顶元素 
bool GetStack(LiStack &L,int &x){
	if(L){
		x=L->next->data;
		return true;
	}
	return false;
}
//求表长
int StackLength(LiStack L)
{
    int count = 0;
    Linode *p=L->next;
    while (p)
    {
        count++;
        p = p->next;
    }
    return count;
}

//打印链栈
void PrintStack(LiStack L){
	if(L){
		while(L){
			printf("%d ",L->next->data);
			L->next=L->next->next;
		}
		printf("\n");
	}
} 
 
int main(){
	LiStack L;
	InitStack(L);
	printf("%d\n",isEmpty(L));
	PushStack(L);
	int x;
	int a;
	printf("%d\n",PopStack(L,x));
	printf("%d\n",x);
	printf("%d\n",GetStack(L,a));
	printf("%d\n",a);
	printf("%d\n",StackLength(L));
	PrintStack(L);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值