栈的动态分配顺序存储的基本操作(top为指针且指针指向栈顶元素)

top为指针且指针指向栈顶元素
在这里插入图片描述
一、栈的动态分配顺序存储的结构定义:

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

#define ERROR 0
#define OK    1

#define INIT_SIZE  10      /*栈的初始分配容量*/ 
#define INCREMENT   2      /*栈的分配量增量*/ 

typedef int  Status;
typedef int  Elemtype;
typedef struct SqStack{
	Elemtype *base;       //栈底指针,始终指向栈底的位置 
	Elemtype *top;        //栈定指针,可以指向栈顶元素下一个位置或栈顶元素 
	int StackSize;        //栈的初始可使用分配存储量 
}SqStack;

二、栈的初始化:

/*栈的动态分配顺序存储初始化,且top指针指向栈顶元素 */
Status InitStack(SqStack *S)
{
	S->base=(Elemtype*)malloc(sizeof(Elemtype)*INIT_SIZE);
	if(!S->base)
	{
		return ERROR;
	}
	S->top = S->base-1;            
	S->StackSize=INIT_SIZE;
	return OK;
}

三、入栈(压栈)操作:

/*压栈操作*/ 
void PushStack(SqStack *S,Elemtype e)
{
	
	if( S->top - S->base + 1 >= S->StackSize )
	{   /*栈满,追加空间*/
		S->base=(Elemtype*)realloc(S->base,(S->StackSize+INCREMENT)*sizeof(Elemtype));
	    assert(S->base != NULL);                //判断是否扩容成功 
		S->top = S->base + S->StackSize -1;    //修改栈顶指针 
		S->StackSize=S->StackSize+INCREMENT;   //扩容后栈的存储容量 
	}
	
	*++S->top=e;                               //将e入栈 
} 

四、栈的当前长度:

/*栈的当前长度*/
Status StackLength(SqStack *S)
{
	if( S->top >= S->base -1 )
	{
		return S->top - S->base +1;
	} 
	else return ERROR;
}

五、获取栈顶元素:

/*取栈顶元素*/
Status GetTop(SqStack *S,Elemtype *e)
{
	if(S->top > S->base -1 )
	{
		*e = *S->top;
		return OK;
	}
	else return ERROR;
} 

六、判断栈是否为空栈:

/*判断一个栈是否为空*/
Status StackEmpty(SqStack *S)
{
	if( S->top == S->base - 1 ) return ERROR;
	else return OK;
} 

七、清空栈:

/*清空栈*/
void ClearStack(SqStack *S)
{
	S->top = S->base-1;
} 

八、销毁栈:

/*销毁栈*/
void DestroyStack(SqStack *S)
{
	if(S != NULL)
	{
		free(S->base);
		S->base = S->top=NULL;
		S->StackSize=0;
	}
}

九、出栈(弹栈)操作:

/*弹栈操作*/
Status PopStack(SqStack *S,Elemtype *e)
{
	if(S->top == S->base -1)    //判断是否栈空 
	{
		return ERROR;
	}
	*e = *S->top--;
	return OK;
}

十、遍历栈:

/*遍历栈*/ 
void StackTraverse(SqStack S,void (*visit)(Elemtype))
{
	while(StackEmpty(&S))
	{
		visit(*S.base++);
	}
}
void Print(Elemtype e)
{
	printf("%d ",e);
}

十一、主函数:

int main()
{
	int i,value,length;
	Elemtype e;
	SqStack S;
	
	value=InitStack(&S);
	if(value)
	{
		printf("初始化栈成功!\n\n");
	}
	else  
	{
		puts("error!");
		return ERROR;
	}
	
	for(i=1;i<12;i++)
	PushStack(&S,i);
	printf("栈中的元素为:\n");
	StackTraverse(S,Print);
	
	value=StackEmpty(&S);
	if(value)
	{
		printf("\n非空栈!\n");
	}
	else
	{
		printf("空栈!");
	} 
	length=StackLength(&S);
	printf("当前长度为:%d\n",length);
	
	value=PopStack(&S,&e);
	if(value)
	{
		printf("\n弹出的栈顶元素为:%d\n",e);
	}
	else
	{
		printf("空栈!\n");
		return ERROR;
	}	
		
	value=GetTop(&S,&e);
	if(value)
	{
		printf("当前栈顶元素为:%d\n当前栈长度为:%d\n",e,StackLength(&S));
	} 
	else
	{
		printf("error! Stack Empty\n");
		return ERROR;
	} 
	
	ClearStack(&S);
	printf("\n\n清空栈后:\n");
	value=StackEmpty(&S);
	if(value)
	{
		printf("\n非空栈!");
	}
	else
	{
		printf("空栈!\n");
	} 
	length=StackLength(&S);
	printf("当前长度为:%d\n",length);
	
	DestroyStack(&S);
	printf("\n销毁栈后:\n top=%u,base=%u,StackSize=%d",S.top,S.base,S.StackSize);
	
	return 0;
} 

十二、运行截图:
在这里插入图片描述

  • 10
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 顺序的初始化: 1. 定义一个数组作为的存储空间; 2. 定义一个变量 top,表示栈顶元素的下标,初始值为 -1。 顺序的入: 1. 判断是否已满,如果已满则无法入; 2. 将要入元素放入数组中 top+1 的位置; 3. top 值加 1。 顺序的出: 1. 判断是否为空,如果为空则无法出; 2. 将 top 位置的元素弹出; 3. top 值减 1。 顺序的取栈顶元素: 1. 判断是否为空,如果为空则无法取栈顶元素; 2. 返回 top 位置的元素。 链的初始化: 1. 定义一个结构体作为链的存储空间,包含一个数据域和一个指向下一个节点的指针; 2. 定义一个指针 top,表示栈顶,初始值为 NULL。 链的入: 1. 创建一个新节点,将要入元素放入节点的数据域中; 2. 将新节点插入到链表的头部,使其成为新的栈顶; 3. top 指向新的栈顶节点。 链的出: 1. 判断链是否为空,如果为空则无法出; 2. 将 top 指向的节点弹出; 3. top 指向弹出节点的下一个节点。 链的取栈顶元素: 1. 判断链是否为空,如果为空则无法取栈顶元素; 2. 返回 top 指向的节点的数据域。 ### 回答2: 顺序和链是两种常见的结构实现方式,其实现方式不同,但其基本操作相似,包括初始化、入、出、取栈顶元素等。下面将详细介绍这些操作。 一、顺序的初始化 顺序的存储结构采用的是数组,因此在初始化时需要定义一个数组,并初始化栈顶指针top,一般情况下,数组下标从0开始。初始化顺序的代码如下: ```c #define MaxSize 10 // 定义的最大长度 typedef struct { int data[MaxSize]; // 存放元素的数组 int top; // 栈顶指针 }SqStack; void InitStack(SqStack &s) { s.top = -1; // 初始化栈顶指针为-1,表示为空 } ``` 二、链的初始化 链的存储结构采用的是链表,因此在初始化时需要定义一个链表节点,并初始化栈顶指针top。链的初始化代码如下: ```c typedef struct LinkStackNode { int data; // 存放元素的值 struct LinkStackNode *next; // 指向下一个节点的指针 }LinkStackNode, *LinkStackPtr; typedef struct { LinkStackPtr top; // 栈顶指针 }LinkStack; void InitStack(LinkStack &s) { s.top = NULL; // 初始化栈顶指针为空,表示为空 } ``` 三、顺序和链的入操作 顺序的入操作是将元素压入数组中,需要判断是否已满。入操作的具体代码如下: ```c int Push(SqStack &s, int x) { if (s.top == MaxSize - 1) { // 已满 return 0; } s.data[++s.top] = x; // 栈顶指针先加1,再将元素 return 1; } ``` 链的入操作是将元素插入到链表的头节点前面,需要分配一个新节点来存放该元素。入操作的具体代码如下: ```c int Push(LinkStack &s, int x) { LinkStackPtr p = (LinkStackPtr)malloc(sizeof(LinkStackNode)); // 分配一个新节点 p->data = x; // 将元素存入该节点中 p->next = s.top; // 将新节点插入到栈顶节点前面 s.top = p; // 将栈顶指针指向新节点 return 1; } ``` 四、顺序和链的出操作 顺序的出操作是将栈顶元素弹出,并将栈顶指针减1,需要判断是否为空。出操作的具体代码如下: ```c int Pop(SqStack &s, int &x) { if (s.top == -1) { // 为空 return 0; } x = s.data[s.top--]; // 将栈顶元素弹出,栈顶指针减1 return 1; } ``` 链的出操作是将栈顶元素弹出,并释放该节点所占用的内存,需要判断是否为空。出操作的具体代码如下: ```c int Pop(LinkStack &s, int &x) { if (s.top == NULL) { // 为空 return 0; } LinkStackPtr p = s.top; // 将栈顶指针指向要弹出的节点 x = p->data; // 获取要弹出的元素 s.top = p->next; // 将栈顶指针指向下一个节点 free(p); // 释放要弹出的节点所占用的内存 return 1; } ``` 五、顺序和链的取栈顶元素操作 顺序和链的取栈顶元素操作都是获取栈顶元素的值,但实现方式有点不同。 顺序的取栈顶元素操作非常简单,只需要返回栈顶指针指向元素的值即可。取栈顶元素操作的具体代码如下: ```c int GetTop(SqStack s, int &x) { if (s.top == -1) { // 为空 return 0; } x = s.data[s.top]; // 获取栈顶元素的值 return 1; } ``` 链的取栈顶元素操作需要先判断是否为空,然后再返回栈顶节点的元素值。取栈顶元素操作的具体代码如下: ```c int GetTop(LinkStack s, int &x) { if (s.top == NULL) { // 为空 return 0; } x = s.top->data; // 获取栈顶元素的值 return 1; } ``` 总结 顺序和链是两种常见的结构实现方式,其基本操作包括初始化、入、出、取栈顶元素等。顺序的存储结构采用数组,链的存储结构采用链表。对于入和出操作,顺序是在数组中插入和删除元素,链是在链表头节点前插入和删除元素。取栈顶元素操作时,顺序可以直接返回栈顶指针指向元素的值,链需要先判断是否为空,然后再返回栈顶节点的元素值。 ### 回答3: 顺序和链是常用的的实现方式。下面将在以下几个方面详细讲解顺序和链的初始化、入、出、取栈顶元素操作。 一、顺序的初始化、入、出、取栈顶元素操作 1. 顺序的初始化 顺序的初始化需要创建一个数组并确定其容量,同时将栈顶指针指向底,使其初始为空。 2. 顺序的入操作 在顺序中入操作时需要进行如下步骤: (1)判断是否已满,若已满则提示溢出; (2)将元素,即将栈顶指针加1,将元素存放到栈顶位置。 3. 顺序的出操作 在顺序中出操作时需要进行如下步骤: (1)判断是否为空,若为空则提示下溢; (2)将栈顶元素,即先取出栈顶元素值,然后将栈顶指针减1。 4. 顺序的取栈顶元素操作 在顺序中取栈顶元素操作时只需返回栈顶元素的值即可,但要注意在取之前需要判断是否为空。 二、链的初始化、入、出、取栈顶元素操作 1. 链的初始化 链的初始化需要定义一个头节点,并将栈顶指针指向头节点,使其初始为空。 2. 链的入操作 在链中入操作时需要进行如下步骤: (1)新建一个节点,存放要入元素; (2)将新节点插入到链表的表头位置; (3)更新栈顶指针指向新节点。 3. 链的出操作 在链中出操作时需要进行如下步骤: (1)判断是否为空,若为空则提示下溢; (2)将栈顶元素,即先取出栈顶元素值,然后删除链表的表头节点; (3)更新栈顶指针指向链表的新表头。 4. 链的取栈顶元素操作 在链中取栈顶元素操作时只需返回栈顶节点的值即可,但要注意在取之前需要判断是否为空。 总之,顺序和链虽然实现方式不同,但是它们的操作都比较基础,掌握了这些基础操作,再学习其他高阶操作就会变得容易很多。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值