数据结构:顺序栈

版权声明:所有内容仅供大家学习与复习使用,请勿用于任何商业用途;维特根斯坦曾说过,凡可说的,皆无意义。凡有意义的,皆不得不以荒唐的语言传递其意义。我十分赞同。 https://blog.csdn.net/qq_40828914/article/details/88919519

栈:

从数据结构上来看,栈也是线性表,但是是操作受限的线性表。

栈是限定仅在表尾进行插入或删除操作的线性表。

对栈来说,表尾端称为栈顶,表头端称为栈底。

栈是后进先出的线性表。

栈的基本操作:在栈顶插入删除,初始化,判空,取栈顶元素等

栈也有两种存储方法,一种是顺序栈,用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。另一种是链栈。这里先整理顺序栈。

顺序栈的实现及操作:

1.定义一个栈

顺序栈的定义完全可以用顺序表的定义,不过这里由于经常要用到栈顶,所以就增加一个top指针,指向栈顶元素的下一个位置。由于当前已存的元素个数length可以由栈顶指针减栈底指针求出,所以,这里就省去length,只保留一个初始化定义时给定的最大存储元素个数stacksize,当使用栈时空间不够,可以再进行扩大。

top指针方便之处,就在于,插入的时候插到top指向的位置上,然后top指针自增。出栈的时候把top指针自减,然后把top指针指向位置的元素取出即可。

#define STACK_INIT_SIZE	100				
#define STACKINCREMENT	10 	
typedef struct
{
	SElemType_Sq *base;				
	SElemType_Sq *top;				 
	int stacksize;					
}SqStack;
2.构造一个空栈

base称为栈底指针,top称为栈顶指针。构造空栈,top指针和base指针指向同一位置,此时栈里面没有元素(length=0)。其他的和构造一个空顺序表一样。

Status InitStack_Sq(SqStack &S)
{
 	S.base = (SElemType_Sq *)malloc(STACK_INIT_SIZE*sizeof(SElemType_Sq));
	if(!S.base)
		exit(OVERFLOW);
		
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	
	return OK;
} 
3.取栈顶元素

这里取栈顶元素,我们先判断栈是否为空,如果不为空,取栈顶元素。栈顶元素再top指针的上一个位置,也就是S.top - 1(这里可以类比数组,a+1也就是指向a[1]的指针),那么取出的话把地址的值给e即可。注意这里仅仅是取出,不能改变栈顶指针,不能S.top–。

Status GetTop_Sq(SqStack S, SElemType_Sq &e)
{
	if(S.top==S.base)
		return ERROR;
	e = *(S.top - 1);						
	return OK;
} 
4.插入元素e

之前说了,S.top-S.base就是length当前已存的元素个数,那么如果length=最大存储元素个数stacksize,那么再插入元素的时候就空间不够了,所以这里需要再增加一段新的空间,能够再多存STACKINCREMENT个元素。弄完之后我们的top指针应该指向栈顶元素的下一个位置,此时已经有stacksize个元素了,也就是说,top指针指向S.base + S.stacksize这个位置。(不理解可以类比数组a+stacksize就是&a[stacksize],而a时下标为0开始存元素的,也就是说现在a+stacksize指向的时第stacksize+1个元素的位置)

然后修改完top指针后,stacksize也更新为S.stacksize + STACKINCREMENT。

此时我们先把e赋值到top指针指向的位置,然后top指针指向栈顶元素的下一个位置,自己加一即可。

Status Push_Sq(SqStack &S, SElemType_Sq e)
{
	if(S.top-S.base>=S.stacksize)		
	{
		S.base = (SElemType_Sq *)realloc(S.base, (S.stacksize+STACKINCREMENT)*sizeof(SElemType_Sq));
		if(!S.base)
			exit(OVERFLOW);					
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREMENT;
	}
	*S.top = e;							
	S.top++;
	return OK;
}
5.删除栈顶元素,返回其值

出栈的时候把top指针自减,然后把top指针指向位置的元素取出即可。

Status Pop_Sq(SqStack &S, SElemType_Sq &e)
{
	if(S.top==S.base)
		return ERROR;
	S.top--;									
	e = *(S.top);
	return OK;
} 

6.清空栈,销毁栈

清空栈,意味着top指针和base指针指向同一位置。

但是销毁栈,top指针和base指针指向null而且stacksize等于0。

Status DestroyStack_Sq(SqStack &S)
{
	
	
	S.base = NULL;
	S.top = NULL;
	S.stacksize = 0;
	
	return OK;
} 

Status ClearStack_Sq(SqStack &S)
{
	S.top = S.base;
	
	return OK;
} 

栈的操作实例及代码:

代码:

#include<cstdio>
#include<cstdlib>

#define STACK_INIT_SIZE	100				
#define STACKINCREMENT	10 	

#define	OK			1			
#define	ERROR		0	
#define	OVERFLOW	-2			
#define UNDERFLOW	-3	
#define	TRUE		1			
#define	FALSE		0
typedef int Status;
typedef int SElemType_Sq;

typedef struct
{
	SElemType_Sq *base;				
	SElemType_Sq *top;				 
	int stacksize;					
}SqStack;

Status InitStack_Sq(SqStack &S)
{
 	S.base = (SElemType_Sq *)malloc(STACK_INIT_SIZE*sizeof(SElemType_Sq));
	if(!S.base)
		exit(OVERFLOW);
		
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	
	return OK;
} 

Status GetTop_Sq(SqStack S, SElemType_Sq &e)
{
	if(S.top==S.base)
		return ERROR;
		
	e = *(S.top - 1);						
	
	return OK;

} 

Status Push_Sq(SqStack &S, SElemType_Sq e)
{
	if(S.top-S.base>=S.stacksize)		
	{
		S.base = (SElemType_Sq *)realloc(S.base, (S.stacksize+STACKINCREMENT)*sizeof(SElemType_Sq));
		if(!S.base)
			exit(OVERFLOW);					
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREMENT;
	}
	
	*S.top = e;							
	S.top++;

	return OK;
} 

Status Pop_Sq(SqStack &S, SElemType_Sq &e)
{
	if(S.top==S.base)
		return ERROR;

	S.top--;									
	e = *S.top;

	return OK;
} 
void PrintElem(SElemType_Sq e)
{
	printf("%d ", e);
}
Status StackTraverse_Sq(SqStack S, void(Visit)(SElemType_Sq))
{												 
	SElemType_Sq *p = S.base;
	
	while(p<S.top)
		Visit(*p++);
	printf("\n");
	return OK;
} 
Status StackEmpty_Sq(SqStack S)
{
	if(S.top==S.base)
		return TRUE;
	else
		return FALSE;
} 

int main(){
	SqStack S;
	int i;
	SElemType_Sq e;
	printf("初始化顺序栈 S ...\n");					 		
	InitStack_Sq(S);
	printf("\n");
	StackEmpty_Sq(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
	printf("\n");
	for(i=1; i<=6; i++)									
	{
		printf("将 \"%2d\" 压入栈 S \n", 2*i);			
		Push_Sq(S, 2*i);
	}
	printf("\n");
	printf(" S 中的元素为:S = ");						 
	StackTraverse_Sq(S, PrintElem);
	printf("\n");
	Pop_Sq(S, e);
	printf("栈顶元素 \"%d\" 出栈...\n", e);
	printf(" S 中的元素为:S = ");						 
	StackTraverse_Sq(S, PrintElem);
	printf("\n");
	GetTop_Sq(S, e);
	printf("栈顶元素的值为 \"%d\" \n", e);
	printf("\n");
	
}

运行结果:

初始化顺序栈 S …

S 为空!!

将 " 2" 压入栈 S
将 " 4" 压入栈 S
将 " 6" 压入栈 S
将 " 8" 压入栈 S
将 “10” 压入栈 S
将 “12” 压入栈 S

S 中的元素为:S = 2 4 6 8 10 12

栈顶元素 “12” 出栈…
S 中的元素为:S = 2 4 6 8 10

栈顶元素的值为 “10”

猜你喜欢

转载自blog.csdn.net/qq_40828914/article/details/88919519
今日推荐