指针简介(4)—— 自制栈

声明:

        本文是阅读周立功老师的程序设计与数据结构后所写,很多内容其实是书中的内容,所以如果您想了解更多这方面的知识,您可以阅读这本书。

自制栈:

        对于学习嵌入式的人来说栈一定不会陌生,那么我们是否可以自己写一个栈并实现对其操作的函数那?我想这是可以的。下面我们一步一步来完成它。

        首先我们要用一个结果体来将这个栈定义出来,对于真正的栈来说可以向其中压入各种类型的数据信息,但是在这里为了简化我们只压入int类型的信息,同时我们要知道一个栈到底有多大,同时也要知道现在栈中有多少个数据了。因此我们可以将栈的结构体定义为:

struct stackCDT{
	int *data;
	size_t top;
	size_t numData;
};

        同时为了可以更加方便的操作这个栈,我们使用typedef将其定义为:

typedef struct stackCDT *stackADT;

        上面我们就定义了一个栈的结构体出来,下面我们就要对其进行操作了。我们知道这里的栈也是一种数据类型,而对于数据的基本操作就是增删改查功能,而这里由于我们在源文件(.c文件)中定义栈结构体,而在头文件(.h文件)中声明,所以对于用户来说栈结构体的定义是不可见的,所以我们这里要再增加一个初始化结构体的函数,所以在头文件中应该有的函数为:

#include <stdbool.h>
#include <stddef.h>

typedef int stackElementT;
typedef struct stackCDT *stackADT;

stackADT newStack();   //创建一个栈
void freeStack(stackADT stack);  //删除某个特定的栈
bool push(stackADT stack, stackElementT value);  //向栈中压入数据
bool pop(stackADT stack, stackElementT *pValue);  //从栈顶删除数据
bool stackIsEmpty(stackADT stack);  //检查栈是否为空
bool stackIsFull(stackADT stack);  //检查栈是否满
size_t getStackDepth(stackADT stack);  //获得栈中压入多少元素 
bool getStackElement(stackADT stack ,size_t index, stackElementT *pValue); //查找栈中某个数值所在位置

        同时我们会在源文件中将上面的函数补充完整:

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

#define MAXSIZE 100  //设置栈空间最大值

struct stackCDT{
	int *data;
	size_t top;
	size_t numData;
};

/*
*创建一个栈
*/
stackADT newStack()
{
	stackADT stack;

	stack = (stackADT)malloc(sizeof(struct stackCDT));
	stack->data = (int *)malloc(sizeof(int)*MAXSIZE);
	stack->top = 0;
	stack->numData = MAXSIZE;

	return stack;
}

/*
*删除某个特定的栈
*/
void freeStack(stackADT stack)
{
	free(stack->data);
	stack->data = 0;
	free(stack);
}

/*
*向栈中压入数据
*/
bool push(stackADT stack, stackElementT value)
{
	if(stackIsFull(stack))
		return false;
	stack->data[stack->top++] = value;
	return true;
}

/*
*从栈顶删除数据
*/
bool pop(stackADT stack, stackElementT *pValue)
{
	if(stackIsEmpty(stack))
		return false;
	*pValue = stack->data[--stack->top];
	return true;

}

/*
*检查栈是否为空
*/
bool stackIsEmpty(stackADT stack)
{
	return stack->top == 0;
}

/*
*检查栈是否满
*/
bool stackIsFull(stackADT stack)
{
	return stack->top == MAXSIZE;
}

/*
*获得栈中压入多少元素
*/
size_t getStackDepth(stackADT stack)
{
	return stack->top;
}

/*
*查找栈中某个数值所在位置
*/
bool getStackElement(stackADT stack ,size_t index, stackElementT *pValue)
{
	if(index > stack->numData) 
		return false;
	*pValue = stack->data[stack->top - index -1];
	return true;
}

        下面我分开介绍下面的各个函数:

1. 创建一个栈

/*
*创建一个栈
*/
stackADT newStack()
{
	stackADT stack;

	stack = (stackADT)malloc(sizeof(struct stackCDT));
	stack->data = (int *)malloc(sizeof(int)*MAXSIZE);
	stack->top = 0;
	stack->numData = MAXSIZE;

	return stack;
}

        由于我们要将定义的栈中的实现细节向使用者关闭,所以我们要提供一个栈初始化的函数。同时我们在上面函数中需要强调的一点是上面所定义的stackCDT为不完全类型(即函数之外、类型的大小不能被确定的类型),而只有当我们使用malloc函数向系统申请空间时才可以知道这个栈结构体所占用的空间大小,因此在初始化时既需要为结构体申请空间,同时也要为数据申请具体大小的空间。所以有代码:

	stack = (stackADT)malloc(sizeof(struct stackCDT));
	stack->data = (int *)malloc(sizeof(int)*MAXSIZE);

        并设置确定好这个栈可以放多少个数据:

stack->numData = MAXSIZE;

        由于是初始化栈,所以此时栈的深度为0,并随着数据的压入,这个值不断的增加:

stack->top = 0;

2.删除某个特定的栈

        解释完上面的函数,下面的函数就很好理解了。

/*
*删除某个特定的栈
*/
void freeStack(stackADT stack)
{
	free(stack->data);
	stack->data = 0;
	free(stack);
}

        既然我们向系统申请了一块空间,那么当我们使用完之后就一定要注销掉这块空间,不然会引起内存泄露问题,这里就是注销空间的函数,这里需要注意的一点是在注销时要先注销小的再注销大的,如上面的函数中先注销stack内的data后注销stack。

3. 检查栈

/*
*检查栈是否为空
*/
bool stackIsEmpty(stackADT stack)
{
	return stack->top == 0;
}

/*
*检查栈是否满
*/
bool stackIsFull(stackADT stack)
{
	return stack->top == MAXSIZE;
}

/*
*获得栈中压入多少元素
*/
size_t getStackDepth(stackADT stack)
{
	return stack->top;
}

        检查栈是否为空或者检查栈是否满其实就是检查栈中top标记的值是否为0或者最大值。为0即为空,为最大值即为满。为空时不可出栈,而栈满时不可入栈。

4. 向栈中压入数据

/*
*向栈中压入数据
*/
bool push(stackADT stack, stackElementT value)
{
	if(stackIsFull(stack))
		return false;
	stack->data[stack->top++] = value;
	return true;
}

        我们在前面说了栈满不可再压入数据,所以这里如果栈满在压入数据返回错误。而正常情况下将数存在栈中并将栈中标记位加一。

5. 从栈顶删除数据

/*
*从栈顶删除数据
*/
bool pop(stackADT stack, stackElementT *pValue)
{
	if(stackIsEmpty(stack))
		return false;
	*pValue = stack->data[--stack->top];
	return true;
}

        从栈中删除数据,并将这个数据返回给指定的参数,这里由于需要对pValue的值进行修改,所以在传参数的时候只能传递参数地址而并不能传递参数的值。由于栈是先入后出的机制,所以我们要从top-1处将数据取出,并使top减一。

6. 查找栈中某个位置的数值

/*
*查找栈中某个位置的数值
*/
bool getStackElement(stackADT stack ,size_t index, stackElementT *pValue)
{
	if(index > stack->numData) 
		return false;
	*pValue = stack->data[stack->top - index -1];
	return true;
}

        同样由于栈是先入后出机制,所以这里在栈查找时使用stack->top - index -1来正确获得顺序的栈值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值